Skip to main content

A Python-powered slideshow maker with steroids.

Project description

Auditorium

PyPI - License PyPI - Python Version PyPI Travis (.org) Codecov

A Python-powered slideshow creator with steroids.

See the demo at auditorium-demo.apiad.net (sorry, no HTTPS yet).

What's this about?

Auditorium is a Python-powered slideshow generator. You write pure Python code, and obtain an HTML+JavaScript slideshow (using the amazing reveal.js library). The awesomeness comes from the fact that your Python backend is connected to the slideshow frontend, which allows your slideshow to dynamically change according to user input or automatically.

This opens the door to a few interesting use cases:

  • The slides content itself can be generated by code. For example, long and repetitive sets of slides can be automatically generated, or tables and graphs embedded in slides can be generated on-the-fly with matplotlib, bokeh, altair, plotly, or any visualization package that produces HTML output.
  • You can insert components in the slides that respond to user input, and execute a Python code in response. For example, you can generate an interactive graph that can be modified by moving sliders in a slideshow.
  • You can create beautiful animations with simple Python code, that automatically play on a slide, using visualization libraries or simple HTML markup.

And all of this without writing a single line of HTML or JavaScript.

Alternatively, if you need little to no Python code, you can author your slideshow in pure Markdown and add some Python sprinkless here and there when necessary.

Installation

Simply run:

pip install auditorium

To see a quick demo run:

auditorium demo

And point your browser at localhost:6789.

Quick Start - Python First

In auditorium you create a presentation via the Show class:

# Content of <file.py>

from auditorium import Show
show = Show("My Show")

Every slide in your show is a Python method that renders the content and powers the backend logic. Slides are decorated with the @show.slide decorator.

@show.slide
def one_slide():
    # content

Then run the show:

auditorium run <file.py>

Optionally, you can specify --host and --port as well as --debug which activates hot-reload and outputs debug info (powered by Sanic).

Alternatively, you can also directly call show.run, although the recommended way is the previous one.

show.run('localhost', 6789)

The simplest possible form of content is static Markdown. You can add it with show.markdown and/or directly as the docstring of the corresponding slide function:

@show.slide
def static_content():
    """
    ## Static content

    Can be added very simply with:

    * Method _docstrings_
    * Calling `show.markdown`
    """

    show.markdown("> Like this")

There are several components in auditorium to style and layout your presentation, including reactive components that respond to user input.

@show.slide
def interactive():
    show.markdown("Enter your name")
    name = show.text_input(default="World")
    show.markdown(f"> Hello {name}")

The slide code is considered stateless, and will be executed every time the input changes. You should design your slides with this in mind to, for example, provide sensible default values that will work when your presentation first opens.

Simple stateless animations can be created with show.animation, which execute the backend code for every frame. Combining this with drawing logic from, for example, matplotlib allows for very simple animated graphs and visualizations:

@show.slide
def pyplot():
    with show.animation(steps=50, time=0.33, loop=True) as anim:
        # Every 0.33 seconds the graph will move
        step = anim.current * 2 * math.pi / 50
        x = np.linspace(0, 2 * math.pi, 100)
        y = np.sin(x + step) + np.cos(x + step)
        plt.plot(x, y)
        plt.ylim(-2,2)
        show.pyplot(plt, fmt='png', height=350)

Quick Start - Markdown First

Alternatively, if you need little to no Python, you can author your slideshow in pure Markdown. Every level-2 header (##) becomes a slide.

## Static content

Static content can be added with pure markdown.

* Some _markdown_ content.
* More **markdown** content.

Pure Markdown can be used as long as all you need is static content. If you need more advanced features, you can add a Python code section anywhere in your slideshow and it will be executed.

## Dynamic content

If you need interaction or advanced `auditorium` features,
simply add a code section.

```python :run
with show.columns(2) as cl:
    text = show.text_input("World")

    cl.tab()

    with show.success("Message"):
        show.markdown(f"Hello {text}")
```

An instance named show will be magically available in every Python code section. Beware that local variables are not persisted between different code sections. This is a by-design decision to save you a bunch of headaches, believe me. If you want variables to persist accross code sections, add :persist in the code declaration section. This also let's you interpolate Python variables directly inside the Markdown content.

```python  :run :persist
text = show.text_input("World")
```

Hello {text}. This is pure Markdown.

You need to add :run to the code section declaration for it to be executed, otherwise auditorium will consider it just Markdown code and simply print it. If you want both to run and print the code, then add :run :echo to the code declaration part.

Once you finished authoring you slideshow, simply run it just like before:

auditorium run <file.md>

If you want to see an example, check auditorium/static/md/demo.md

What's the catch

Auditorium covers a fairly simple use case that I haven't seen solved for a long time. I came up with this idea while trying to make better slideshows for my lectures at the University of Havana. I usually need to display complex math stuff and graphs, ideally animated, and sometimes make modifications on the fly according to the interaction with students. They could ask how a function would look if some parameters where changed, etc.

Along that path I grew up from Power Point to JavaScript-based slides (like reveal.sj) and sometimes even coded some simple behavior in JS, like changing a chart's parameters. However, for the most complex stuff I wanted to use Python, because otherwise I would need to redo a lot of coding in JS. For example, I'm teaching compilers now, and I want to show interactively how a parse tree is built for a regular expression. I simply cannot rewrite my regex engine in JS just for a slideshow.

Then I discovered streamlit and for a while tried to move my slides to streamlit format. Streamlit is awesome, but is aimed at a completely different use case. It's quite cumbersome to force it to behave like a slideshow, the flow is not natural, and the styling options are very restrictive. On the other hand, they handle a lot of complex scenarios which I simply don't need in a slideshow, like caching and a lot of magic with Pandas and Numpy. Contrary to streamlit, I do want custom CSS and HTML to be easy to inject, because styling is very important in slides.

So I decided to write my own slideshow generator, just for my simple use cases. That being said, there are some known deficiencies that I might fix, and some others which I probably will not, even in the long run.

Slides need to be fast

A slide's code is executed completely every time that slide needs to be rendered. That is, once during loading and then when inputs change or animations tick. Hence, you slide logic should be fairly fast. This is particularly true for animations, so don't expect to be able to train a neural network in real time. The slide logic is meant to be simple, the kind of one-liners you can run every keystroke, like less than 1 second fast. If you need to interactively draw the loss value of a neural network, either is gonna take a while or you will have to fake it, i.e., compute it offline and then simply animate it.

All slides are executed on load

For now, on the first load all slides are going to be run, which might increase significantly your loading time if you have complex logic in each slide. At some point, if I run into the problem, I may add a "lazy" loading option so that only the first few slides are executed. If this is an issue for a lot of people it might become a priority.

The show state is global

Right now there is a single Show instance running the show, so several people looking at the same slideshow will share the values for the interactive inputs and animation steps. This might create weird scenarios in which you are typing into an input text box and you see a different result because another viewer is typing on a different browser. I don't know right now the extent to which this is an important issue, so I might fix it in the future if necessary.

Watch out for code injection!

It is very tempting to do things like getting a text from an input box and passing it through eval in Python, so that you can render different functions interactively. As long as you serve your presentations on localhost and show them yourself, feel free. However, beware when hosting presentations online. Since the backend code runs in your computer, a viewer could inject nasty stuff such as importing os and deleting your home folder! In the future I might add a --safe option that only allows for animations and other interactive behaviors that don't use input directly from the user. Staying away from eval and exec should keep you safe in most scenarios, but the basic suggestion is don't do anything you wouldn't do in a regular web application, since all security issues are the same.

History

v0.4.3

  • Improved test coverage a lot.

v0.4.2

  • Added support for interpolating Python variables in Markdown mode.

v0.4.0

  • Ported to Sanic 🤓!

v0.3.1

  • Improved support for running Markdown.

v0.3.0

  • Added support for running directly from Markdown files with auditorium run <file.md>.

v0.2.0

  • Added command auditorium run <file.py> for running a specific slideshow. This is now the preferred method.
  • Added command auditorium demo for running the demo.

v0.1.5

  • Added support for reveal.js themes via show.theme and query-string argument ?theme=....
  • Improved testing coverage.
  • Fixed error with missing static files in the distribution package.

v0.1.3

  • Added support for fragments.
  • Added support for vertical slides.
  • Added custom layout options with show.columns.
  • Added styled block with show.block.
  • Added parameter language for show.code, defaulting to "python".
  • Improved layout for columns, with horizontal centering.
  • Improved layout for input texts.
  • Improved example for the pyplot support in the demo.
  • Fixed some style issues.
  • Fixed error reloading on a slide with an animation.
  • Updated Readme with some examples.

v0.1.2

  • Refactor custom CSS and JavaScript into auditorium.css and auditorium.js respectively.

v0.1.1

  • Added basic binding for variables.
  • Added support for simple animations with show.animation.
  • Added support for pyplot rendering.

v0.1.0

  • Initial version with basic functionality.

Collaboration

License is MIT, so you know the drill: fork, develop, add tests, pull request, rinse and repeat.

MIT License

Copyright (c) 2019 Alejandro Piad

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

License for Reveal-js

auditorium includes a copy a reveal-js which is itself licensed under MIT.

Copyright (C) 2019 Hakim El Hattab, http://hakim.se, and reveal.js contributors

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

auditorium-0.4.3.tar.gz (1.6 MB view hashes)

Uploaded Source

Built Distribution

auditorium-0.4.3-py3-none-any.whl (1.7 MB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page