Giter VIP home page Giter VIP logo

reprexlite's Introduction

reprexlite: Python reproducible examples for sharing

Docs Status Supported Python versions PyPI Version conda-forge Version conda-forge feedstock tests codecov

reprexlite is a tool for rendering reproducible examples of Python code for sharing. With a convenient CLI and lightweight dependencies, you can quickly get it up and running in any virtual environment. It has an optional IPython extension with cell magic for easy use in Jupyter or VS Code. This project is inspired by R's reprex package.

  • Paste or type some Python code that you're interested in sharing.
  • reprexlite will execute that code in an isolated namespace. Any returned values or standard output will be captured and displayed as comments below their associated code.
  • The rendered reprex will be printed for you to share. Its format can be easily copied, pasted, and run as-is by someone else. Here's an example of an outputted reprex:
from itertools import product

grid = list(product([1, 2, 3], [8, 16]))
grid
#> [(1, 8), (1, 16), (2, 8), (2, 16), (3, 8), (3, 16)]
list(zip(*grid))
#> [(1, 1, 2, 2, 3, 3), (8, 16, 8, 16, 8, 16)]

Writing a good reprex takes thought and effort (see "Reprex Do's and Don'ts" for tips). The goal of reprexlite is to be a tool that seamlessly handles the mechanical stuff, so you can devote your full attention to the important, creative work of writing the content.

Reprex-style code formatting—namely, with outputs as comments—is also great for documentation. Users can copy and run with no modification. Consider using reprexlite when writing your documentation instead of copying code with >>> prompts from an interactive Python shell. In fact, reprexlite can parse code with >>> prompts and convert it into a reprex for you instead.

reprexlite is a lightweight alternative to reprexpy and is similarly meant as a port of the R package reprex.

Why reproducible examples?

If you're asking for help or reporting a bug, you are more likely to succeed in getting others to help you if you include a good reprex. If you're writing documentation, your readers will appreciate examples that they can easily run. See "Design Philosophy" for more on both "Why reproducible examples?" and "Why reprexlite?"

Installation

reprexlite is available on PyPI:

pip install reprexlite

Optional dependencies can be specified using the "extras" mechanism, e.g., reprexlite[ipython]. Available extras are:

  • black : for optionally autoformatting your code
  • ipython : to use the IPython interactive shell editor or %%reprex IPython cell magic
  • pygments : for syntax highlighting and the RTF venue

Development version

The development version of reprexlite is available on GitHub:

pip install https://github.com/jayqi/reprexlite.git#egg=reprexlite

Basic usage

Command-line interface

The easiest way to use reprexlite is through the CLI. It allows you to create a reprex without entering a Python session. Simply invoke the command:

reprex

This will take you into your system's default command-line text editor where you can type or paste your Python code. On macOS, for example, this will be vim. You can set your default editor using the $VISUAL or $EDITOR environment variables—I'm personally a fan of nano/pico.

Once you're done, reprexlite will print out your reprex to console.

To see available options, use the --help flag.

IPython interactive shell editor

Requires IPython. [ipython]

reprexlite optionally supports an IPython interactive shell editor. This is basically like a normal IPython interactive shell except that all cell contents are piped through reprexlite for rendering instead of the normal cell execution. It has the typical advantages of using IPython like auto-suggestions, history scrolling, and syntax highlighting. You can start the IPython editor by using the --editor/-e option:

reprex -e ipython

If you need to configure anything, use the other CLI options alongside the editor option when launching the shell.

Compared to using the IPython cell magic (next section), you don't need to load the reprexlite extension or write out the %%reprex cell magic every use.

IPython/Jupyter Cell Magic

Requires IPython. [ipython]

reprexlite also has an optional IPython extension with a %%reprex cell magic. That means you can easily create a reprex in an IPython shell (requires IPython), in Jupyter (requires Jupyter), or in VS Code's Interactive Python window (requires ipykernel). This can be handy if you're already working in a Jupyter notebook and want to share some code and output, which otherwise doesn't neatly copy and paste in a nice format.

To use, simply load the extension with

%load_ext reprexlite

and then put %%reprex at the top of a cell you want to create a reprex for:

%%reprex
from itertools import product

grid = list(product([1, 2, 3], [8, 16]))
grid
list(zip(*grid))

The magic accepts the same inline option flags as the CLI. Use the line magic %reprex (note single %) to print out help. See the documentation for more details.

Python library

The same functionality as the CLI is also available from the reprex function with an equivalent API. Simply pass a string with your code, and it will print out the reprex, as well as return a Reprex object that contains all the data and formatting machinery. See the API documentation for more details.

from reprexlite import reprex

code = """
from itertools import product

grid = list(product([1, 2, 3], [8, 16]))
grid
list(zip(*grid))
"""

reprex(code)
#> ```python
#> from itertools import product
#>
#> grid = list(product([1, 2, 3], [8, 16]))
#> grid
#> #> [(1, 8), (1, 16), (2, 8), (2, 16), (3, 8), (3, 16)]
#> list(zip(*grid))
#> #> [(1, 1, 2, 2, 3, 3), (8, 16, 8, 16, 8, 16)]
#> ```
#>
#> <sup>Created at 2021-02-26 00:32:00 PST by [reprexlite](https://github.com/jayqi/reprexlite) v0.3.0</sup>
#> <reprexlite.formatting.GitHubReprex object at 0x109059f10>

reprexlite's People

Contributors

jayqi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

pjbull

reprexlite's Issues

Option to add more whitespace

The current reprex output is pretty compact, but sacrifices some readability. Having the option for adding more whitespace can potentially be useful.

  • Horizontal whitespace between output comment indicator and output.
  • Vertical whitespace (new lines) between output and associated code.

Run async code directly

There are other tools that let users run async code directly. See this comment for details.

Right now, if you try to execute a code example with async code, you get something like

SyntaxError: 'async with' outside async function

This is probably because exec and eval are not run as async.

Support configuration files

There are a lot of options so it might be nice to support configuration files so that users can customize defaults.

Perhaps implement using dynaconf

Blank lines are being dropped

import math

math.prod([2, 2])

is producing

import math
math.prod([2, 2])
#> 4

Should be fixed to preserve the original blank line.

Parsing of copied-from-REPL examples

Parsing code examples with >>> prompts could enable a few use cases:

  • You were already in the Python REPL, wrote some code, and now want to convert it into a reprex
  • You were given a code example that was copied from REPL, and you want to run it
  • Migrating existing docs from doctest-style examples to reprexes.

reprextest module like doctest

https://docs.python.org/3/library/doctest.html

The doctest module searches for pieces of text that look like interactive Python sessions, and then executes those sessions to verify that they work exactly as shown.

This is useful for making sure that documentation is up-to-date and that examples still work.

It would be cool to have something like this for reprexes.

Better handling/stack trace for syntax errors

Real syntax errors get gnarly stack traces:

raise SyntaxError("real syntax error")
#> Traceback (most recent call last):
#>   File "/Users/jqi/repos/reprexlite/reprexlite/code.py", line 69, in evaluate
#>     result = eval(str(self).strip(), scope, scope)
#>   File "<string>", line 1
#>     raise SyntaxError("real syntax error")
#>     ^
#> SyntaxError: invalid syntax
#> 
#> During handling of the above exception, another exception occurred:
#> 
#> Traceback (most recent call last):
#>   File "/Users/jqi/repos/reprexlite/reprexlite/code.py", line 71, in evaluate
#>     exec(str(self).strip(), scope, scope)
#>   File "<string>", line 1, in <module>
#>   File "<string>", line None
#> SyntaxError: real syntax error

This is because it runs through both the eval and exec branches and fails both. This can probably be handled more gracefully.

User configuration of defaults

Right now it takes some effort to use non-default options. It may be useful for a user to be able to set system-wide or project-wide defaults.

Not sure about implementation.

  • Environment variables? R reprex uses options which are like environment variables.
  • Configuration file? Many Python projects support configuration files, setup.cfg, and/or pyproject.toml.

Option to run in global namespace

This goes against the philosophy of reproducible examples, and would therefore be discouraged. However, it could still be potentially be handy to create a reprex that ran in the global namespace.

One potential use case is someone working in a Jupyter notebook, who wants to quickly share a snippet of code and output that is not meant to be runnable. They could run the cell magic and evaluate the code in notebook's namespace.

creating doctest output

thank you for creating this handy tool (and the jupyter cell magic!) 💯

it would be very handy to be able to create doctest compatible output from reprexlite (I see there is already an issue for reading doctest format inputs)

so basically going from

from itertools import product
grid = list(product([1, 2, 3], [8, 16]))
grid
#> [(1, 8), (1, 16), (2, 8), (2, 16), (3, 8), (3, 16)]
list(zip(*grid))
#> [(1, 1, 2, 2, 3, 3), (8, 16, 8, 16, 8, 16)]

to

>>> from itertools import product
>>> grid = list(product([1, 2, 3], [8, 16]))
>>> grid
[(1, 8), (1, 16), (2, 8), (2, 16), (3, 8), (3, 16)]
>>> list(zip(*grid))
[(1, 1, 2, 2, 3, 3), (8, 16, 8, 16, 8, 16)]

I tried to get there by using the options but run into a few issues:

  • how can I pass 'nothing' to the --comment option?
  • is there an option for code prefixes? (adding >>> to the code lines)

(ultimately having --venue=doctest available would really sweet obviously)

Hide reprexlite part of tracebacks

Tracebacks look like this:

x = 0
y = 2
y / x
#> Traceback (most recent call last):
#>   File "/Users/jqi/repos/reprexlite/reprexlite/code.py", line 69, in evaluate
#>     result = eval(str(self).strip(), scope, scope)
#>   File "<string>", line 1, in <module>
#> ZeroDivisionError: division by zero

The first two lines are just calling out reprexlite's code execution, and can potentially be distracting because they're not really relevant to the real error.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.