pypresent 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pypresent-0.1.0/.gitignore +221 -0
- pypresent-0.1.0/CHANGELOG.md +81 -0
- pypresent-0.1.0/LICENSE +21 -0
- pypresent-0.1.0/PKG-INFO +235 -0
- pypresent-0.1.0/README.md +188 -0
- pypresent-0.1.0/demos/README.md +69 -0
- pypresent-0.1.0/docs/README.md +673 -0
- pypresent-0.1.0/docs/img/quoted-figure.png +0 -0
- pypresent-0.1.0/docs/img/quoted-output.png +0 -0
- pypresent-0.1.0/pyproject.toml +88 -0
- pypresent-0.1.0/src/pypresent/__init__.py +76 -0
- pypresent-0.1.0/src/pypresent/__main__.py +3 -0
- pypresent-0.1.0/src/pypresent/assets/deck.css +157 -0
- pypresent-0.1.0/src/pypresent/assets/deck.js +69 -0
- pypresent-0.1.0/src/pypresent/blocks.py +192 -0
- pypresent-0.1.0/src/pypresent/cli.py +175 -0
- pypresent-0.1.0/src/pypresent/console.py +27 -0
- pypresent-0.1.0/src/pypresent/context.py +41 -0
- pypresent-0.1.0/src/pypresent/deck.py +402 -0
- pypresent-0.1.0/src/pypresent/markup.py +69 -0
- pypresent-0.1.0/src/pypresent/model.py +45 -0
- pypresent-0.1.0/src/pypresent/nbio.py +193 -0
- pypresent-0.1.0/src/pypresent/presentation.py +495 -0
- pypresent-0.1.0/src/pypresent/render/__init__.py +6 -0
- pypresent-0.1.0/src/pypresent/render/html.py +201 -0
- pypresent-0.1.0/src/pypresent/render/markdown.py +117 -0
- pypresent-0.1.0/src/pypresent/theme.py +270 -0
- pypresent-0.1.0/src/pypresent/themes/dark.toml +23 -0
- pypresent-0.1.0/src/pypresent/themes/office.toml +23 -0
- pypresent-0.1.0/src/pypresent/themes/slate.toml +29 -0
- pypresent-0.1.0/src/pypresent/themes/warm.toml +47 -0
- pypresent-0.1.0/tests/conftest.py +100 -0
- pypresent-0.1.0/tests/test_blocks.py +152 -0
- pypresent-0.1.0/tests/test_cli.py +181 -0
- pypresent-0.1.0/tests/test_console.py +84 -0
- pypresent-0.1.0/tests/test_markdown_source.py +113 -0
- pypresent-0.1.0/tests/test_markup.py +50 -0
- pypresent-0.1.0/tests/test_notebook_source.py +143 -0
- pypresent-0.1.0/tests/test_presentation.py +226 -0
- pypresent-0.1.0/tests/test_readme.py +93 -0
- pypresent-0.1.0/tests/test_render.py +137 -0
- pypresent-0.1.0/tests/test_theme.py +111 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py.cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
# Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# UV
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
# uv.lock
|
|
102
|
+
|
|
103
|
+
# poetry
|
|
104
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
+
# commonly ignored for libraries.
|
|
107
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
+
# poetry.lock
|
|
109
|
+
# poetry.toml
|
|
110
|
+
|
|
111
|
+
# pdm
|
|
112
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
113
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
114
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
115
|
+
# pdm.lock
|
|
116
|
+
# pdm.toml
|
|
117
|
+
.pdm-python
|
|
118
|
+
.pdm-build/
|
|
119
|
+
|
|
120
|
+
# pixi
|
|
121
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
122
|
+
# pixi.lock
|
|
123
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
124
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
125
|
+
.pixi
|
|
126
|
+
|
|
127
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
128
|
+
__pypackages__/
|
|
129
|
+
|
|
130
|
+
# Celery stuff
|
|
131
|
+
celerybeat-schedule
|
|
132
|
+
celerybeat.pid
|
|
133
|
+
|
|
134
|
+
# Redis
|
|
135
|
+
*.rdb
|
|
136
|
+
*.aof
|
|
137
|
+
*.pid
|
|
138
|
+
|
|
139
|
+
# RabbitMQ
|
|
140
|
+
mnesia/
|
|
141
|
+
rabbitmq/
|
|
142
|
+
rabbitmq-data/
|
|
143
|
+
|
|
144
|
+
# ActiveMQ
|
|
145
|
+
activemq-data/
|
|
146
|
+
|
|
147
|
+
# SageMath parsed files
|
|
148
|
+
*.sage.py
|
|
149
|
+
|
|
150
|
+
# Environments
|
|
151
|
+
.env
|
|
152
|
+
.envrc
|
|
153
|
+
.venv
|
|
154
|
+
env/
|
|
155
|
+
venv/
|
|
156
|
+
ENV/
|
|
157
|
+
env.bak/
|
|
158
|
+
venv.bak/
|
|
159
|
+
|
|
160
|
+
# Spyder project settings
|
|
161
|
+
.spyderproject
|
|
162
|
+
.spyproject
|
|
163
|
+
|
|
164
|
+
# Rope project settings
|
|
165
|
+
.ropeproject
|
|
166
|
+
|
|
167
|
+
# mkdocs documentation
|
|
168
|
+
/site
|
|
169
|
+
|
|
170
|
+
# mypy
|
|
171
|
+
.mypy_cache/
|
|
172
|
+
.dmypy.json
|
|
173
|
+
dmypy.json
|
|
174
|
+
|
|
175
|
+
# Pyre type checker
|
|
176
|
+
.pyre/
|
|
177
|
+
|
|
178
|
+
# pytype static type analyzer
|
|
179
|
+
.pytype/
|
|
180
|
+
|
|
181
|
+
# Cython debug symbols
|
|
182
|
+
cython_debug/
|
|
183
|
+
|
|
184
|
+
# PyCharm
|
|
185
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
186
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
187
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
188
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
189
|
+
# .idea/
|
|
190
|
+
|
|
191
|
+
# Abstra
|
|
192
|
+
# Abstra is an AI-powered process automation framework.
|
|
193
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
194
|
+
# Learn more at https://abstra.io/docs
|
|
195
|
+
.abstra/
|
|
196
|
+
|
|
197
|
+
# Visual Studio Code
|
|
198
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
199
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
200
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
201
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
202
|
+
# .vscode/
|
|
203
|
+
# Temporary file for partial code execution
|
|
204
|
+
tempCodeRunnerFile.py
|
|
205
|
+
|
|
206
|
+
# Ruff stuff:
|
|
207
|
+
.ruff_cache/
|
|
208
|
+
|
|
209
|
+
# PyPI configuration file
|
|
210
|
+
.pypirc
|
|
211
|
+
|
|
212
|
+
# Marimo
|
|
213
|
+
marimo/_static/
|
|
214
|
+
marimo/_lsp/
|
|
215
|
+
__marimo__/
|
|
216
|
+
|
|
217
|
+
# Streamlit
|
|
218
|
+
.streamlit/secrets.toml
|
|
219
|
+
|
|
220
|
+
# pypresent: built decks, all rebuilt by demos/build.sh
|
|
221
|
+
demos/out/
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
The format is [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the
|
|
4
|
+
versions are [semantic](https://semver.org/spec/v2.0.0.html).
|
|
5
|
+
|
|
6
|
+
## [Unreleased]
|
|
7
|
+
|
|
8
|
+
## [0.1.0] — 2026-11-07
|
|
9
|
+
|
|
10
|
+
The first release. It began as a single `present.py` that built one lecture's
|
|
11
|
+
deck, and is now a package.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **Markdown decks.** A `.md` file is a source in its own right: headings and
|
|
16
|
+
`---` lines cut it into slides, and a `key: value` front matter block declares
|
|
17
|
+
the deck the way a notebook's first cell does.
|
|
18
|
+
- **Markdown output.** `--format md` writes the same slides as a markdown
|
|
19
|
+
document — a readable handout that `pypresent` can read straight back in.
|
|
20
|
+
Pictures are data URIs by default, or written out beside the file with
|
|
21
|
+
`render_markdown(assets=…)`.
|
|
22
|
+
- **Themes.** Every colour, size and font is a named token; the stylesheet is
|
|
23
|
+
written entirely in terms of them. A theme is a name, a `.toml`/`.json`/`.yaml`
|
|
24
|
+
file, a dict, or a `Theme` — with `base` to build on a built-in. Four ship:
|
|
25
|
+
`warm`, `office`, `dark`, `slate`. `pypresent themes NAME` prints one as a file
|
|
26
|
+
you can edit.
|
|
27
|
+
- **`pypresent check`** as a command of its own, so drift can be found without
|
|
28
|
+
rendering.
|
|
29
|
+
- **`notes()`**, and `notes=` on a slide: speaker notes that stay in the deck and
|
|
30
|
+
never reach the slide.
|
|
31
|
+
- **`kernel="auto"`** (the default): a notebook is executed by the very
|
|
32
|
+
interpreter `pypresent` is installed in, so a fresh virtualenv and a CI runner
|
|
33
|
+
both work with no kernelspec registered anywhere.
|
|
34
|
+
- Images beyond PNG — jpg, gif, webp, svg — embedded by their real type.
|
|
35
|
+
- A test suite, a demo folder, and CI on Linux, macOS and Windows.
|
|
36
|
+
|
|
37
|
+
### Removed
|
|
38
|
+
|
|
39
|
+
- **`audit`.** It opened the built deck in headless Chrome to report which
|
|
40
|
+
slides the renderer had shrunk to fit. That is one subprocess, one browser to
|
|
41
|
+
have installed and one injected probe script, to say something you see the
|
|
42
|
+
moment you open the deck. The shrinking itself is unchanged — an over-full
|
|
43
|
+
slide still scales rather than overflowing — and with it went `fit_floor`,
|
|
44
|
+
`sparse`, `audit_size` and `chrome` on a `Presentation`.
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
|
|
48
|
+
- `present.py` is now the `pypresent` package, and the tool is `pypresent`
|
|
49
|
+
rather than `python present.py`.
|
|
50
|
+
- `lecture=` is now `source=`, since the notebook being quoted need not be a
|
|
51
|
+
lecture. `lecture=` still works, and a deck whose declaration was stored under
|
|
52
|
+
the old name still loads.
|
|
53
|
+
- The command's first positional is the deck, and it may be a `.md`.
|
|
54
|
+
- **`build` runs the source notebook as well, by default.** The deck quotes what
|
|
55
|
+
the source printed, so a build that does not re-run it can put new code beside
|
|
56
|
+
an old number; that was opt-in behind `--source` and is now what a build is.
|
|
57
|
+
The two runs are taken away rather than added: `--skip-source-run` and
|
|
58
|
+
`--skip-slides-run` replace `--source` and `--no-run`, and passing both
|
|
59
|
+
executes nothing. In Python, `build(run=…, source=…)` is now
|
|
60
|
+
`build(run_source=…, run_slides=…)`.
|
|
61
|
+
- `export --mode slide --format md` now uses this package's own renderer rather
|
|
62
|
+
than nbconvert, so it writes the slides rather than the notebook.
|
|
63
|
+
- `-o` on the command line is relative to the shell's directory rather than the
|
|
64
|
+
deck's.
|
|
65
|
+
|
|
66
|
+
### Fixed
|
|
67
|
+
|
|
68
|
+
- `trim={'head': n, 'tail': n}` on a block that already fits no longer truncates
|
|
69
|
+
it and drops the tail.
|
|
70
|
+
- The cell that declares the presentation is no longer rendered as a slide of its
|
|
71
|
+
own source, and `check` no longer complains that it declares no slide.
|
|
72
|
+
- **A non-UTF-8 terminal no longer breaks a build.** A deck carries arrows, a
|
|
73
|
+
middle dot and often Hebrew, and a redirected stdout under a locale that
|
|
74
|
+
cannot encode them - a pipe on a Windows runner, a cron job with `LC_ALL=C` -
|
|
75
|
+
made `pypresent` die printing its own progress line. Messages now fall back to
|
|
76
|
+
a plain-text equivalent (`·` to `-`, `…` to `...`); the deck file itself was
|
|
77
|
+
always written as UTF-8 and is unchanged. CI runs the suite under `LC_ALL=C`
|
|
78
|
+
so this is caught in seconds rather than in the Windows job.
|
|
79
|
+
|
|
80
|
+
[Unreleased]: https://github.com/Barakkol33/pypresent/compare/v0.1.0...HEAD
|
|
81
|
+
[0.1.0]: https://github.com/Barakkol33/pypresent/releases/tag/v0.1.0
|
pypresent-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Barak Kolnik
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
pypresent-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: pypresent
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Slides from a Jupyter notebook, quoting its code and output, as one self-contained HTML file.
|
|
5
|
+
Project-URL: Homepage, https://github.com/Barakkol33/pypresent
|
|
6
|
+
Project-URL: Documentation, https://github.com/Barakkol33/pypresent/blob/main/docs/README.md
|
|
7
|
+
Project-URL: Source, https://github.com/Barakkol33/pypresent
|
|
8
|
+
Project-URL: Issues, https://github.com/Barakkol33/pypresent/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/Barakkol33/pypresent/blob/main/CHANGELOG.md
|
|
10
|
+
Author-email: Barak Kolnik <barakkol@gmail.com>
|
|
11
|
+
License-Expression: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: html,jupyter,markdown,notebook,presentation,reveal,slides
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Environment :: Console
|
|
16
|
+
Classifier: Framework :: Jupyter
|
|
17
|
+
Classifier: Intended Audience :: Education
|
|
18
|
+
Classifier: Intended Audience :: Science/Research
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Topic :: Multimedia :: Graphics :: Presentation
|
|
25
|
+
Classifier: Topic :: Text Processing :: Markup :: HTML
|
|
26
|
+
Classifier: Typing :: Typed
|
|
27
|
+
Requires-Python: >=3.10
|
|
28
|
+
Requires-Dist: tomli>=2.0; python_version < '3.11'
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
31
|
+
Requires-Dist: ipykernel>=6.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: nbclient>=0.9; extra == 'dev'
|
|
33
|
+
Requires-Dist: nbconvert>=7.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: nbformat>=5.9; extra == 'dev'
|
|
35
|
+
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
|
|
36
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
37
|
+
Requires-Dist: pyyaml>=6.0; extra == 'dev'
|
|
38
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
39
|
+
Provides-Extra: jupyter
|
|
40
|
+
Requires-Dist: ipykernel>=6.0; extra == 'jupyter'
|
|
41
|
+
Requires-Dist: nbclient>=0.9; extra == 'jupyter'
|
|
42
|
+
Requires-Dist: nbconvert>=7.0; extra == 'jupyter'
|
|
43
|
+
Requires-Dist: nbformat>=5.9; extra == 'jupyter'
|
|
44
|
+
Provides-Extra: yaml
|
|
45
|
+
Requires-Dist: pyyaml>=6.0; extra == 'yaml'
|
|
46
|
+
Description-Content-Type: text/markdown
|
|
47
|
+
|
|
48
|
+
# pypresent
|
|
49
|
+
|
|
50
|
+
**The notebook is the slides.** `pypresent` turns a Jupyter notebook into one
|
|
51
|
+
self-contained HTML deck: no server, no build folder, no `_files/` directory,
|
|
52
|
+
nothing to upload. One file you can mail, open from a memory stick, or commit
|
|
53
|
+
next to the notebook it came from.
|
|
54
|
+
|
|
55
|
+
And the deck never pastes the code — it quotes the lecture, at build time.
|
|
56
|
+
|
|
57
|
+
[](https://github.com/Barakkol33/pypresent/actions/workflows/ci.yml)
|
|
58
|
+
[](https://pypi.org/project/pypresent/)
|
|
59
|
+
[](https://pypi.org/project/pypresent/)
|
|
60
|
+
[](LICENSE)
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pip install pypresent # rendering only - no Jupyter needed
|
|
64
|
+
pip install "pypresent[jupyter]" # and executing the notebooks
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## The point of it
|
|
68
|
+
|
|
69
|
+
A lecture notebook and its deck usually drift apart: the code is pasted onto a
|
|
70
|
+
slide, the number beside it was true three runs ago, and the chart is a PNG
|
|
71
|
+
somebody exported in March.
|
|
72
|
+
|
|
73
|
+
`pypresent` never pastes. A cell in the lecture is named with a comment, and is
|
|
74
|
+
otherwise an ordinary cell that knows nothing about any deck — here `tokenize`
|
|
75
|
+
came from a cell above it:
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
# slide: counts
|
|
79
|
+
from collections import Counter
|
|
80
|
+
|
|
81
|
+
CORPUS = 'the cat sat on the mat and the cat sat again'
|
|
82
|
+
counts = Counter(tokenize(CORPUS))
|
|
83
|
+
print(counts.most_common(3))
|
|
84
|
+
print(f'{len(counts)} distinct tokens')
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Run the lecture and it prints:
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
[('cat', 2), ('sat', 2), ('mat', 1)]
|
|
91
|
+
6 distinct tokens
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The deck then quotes that cell **by name**, and copies nothing:
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
slide('''
|
|
98
|
+
## And what it printed
|
|
99
|
+
|
|
100
|
+
- `result()` is the cell's own output, not a number typed twice
|
|
101
|
+
- re-run the lecture and the slide changes with it
|
|
102
|
+
''',
|
|
103
|
+
code('counts', drop=['from collections']),
|
|
104
|
+
result('counts'),
|
|
105
|
+
layout='split',
|
|
106
|
+
)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Then:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
pypresent build # run the lecture, run the deck, write one html file
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
which is this slide — the listing is the code that ran, and the numbers under it
|
|
116
|
+
are the ones it printed:
|
|
117
|
+
|
|
118
|
+

|
|
119
|
+
|
|
120
|
+
`code()` is the listing, `result()` is what it printed, and `figure()` is what it
|
|
121
|
+
drew — a chart is code output the same way a number is, read out of the lecture's
|
|
122
|
+
stored output at render time, so there is no PNG beside the deck to go stale:
|
|
123
|
+
|
|
124
|
+

|
|
125
|
+
|
|
126
|
+
All three are resolved when the deck is built, so what a slide shows is what
|
|
127
|
+
actually ran — and a name that stops matching is reported by the build rather
|
|
128
|
+
than going quietly stale.
|
|
129
|
+
|
|
130
|
+
Both slides above are [`demos/05-notebook-slides.ipynb`](demos/05-notebook-slides.ipynb)
|
|
131
|
+
as it stands, rendered by `./demos/build.sh` and screenshotted by
|
|
132
|
+
[`demos/screenshot.sh`](demos/screenshot.sh).
|
|
133
|
+
|
|
134
|
+
## What a deck declares
|
|
135
|
+
|
|
136
|
+
The slide notebook says everything about itself in its first cell, so the
|
|
137
|
+
command line needs nothing but the file:
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
from pypresent import Presentation, slide, code, result, figure
|
|
141
|
+
|
|
142
|
+
deck = Presentation(
|
|
143
|
+
slides='talk-slides.ipynb', # this notebook: nothing but slide() calls
|
|
144
|
+
source='talk.ipynb', # what code(), result() and figure() quote
|
|
145
|
+
output='out/talk.html',
|
|
146
|
+
title='A talk', lang='en', theme='office',
|
|
147
|
+
)
|
|
148
|
+
deck # the last line, so the cell stores it
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The declaration is kept as a cell output, the way a slide is. A flag still wins
|
|
152
|
+
over it: `pypresent build --theme dark -o /tmp/x.html`.
|
|
153
|
+
|
|
154
|
+
## Themes
|
|
155
|
+
|
|
156
|
+
Every colour, size and font is a named token, and the stylesheet is written
|
|
157
|
+
entirely in terms of them — so restyling is changing values, never forking a
|
|
158
|
+
renderer.
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
Presentation(..., theme='dark') # a built-in
|
|
162
|
+
Presentation(..., theme={'base': 'office', 'accent': '#a8441f'})
|
|
163
|
+
Presentation(..., theme='themes/house-style.toml') # a file
|
|
164
|
+
Presentation(..., theme=Theme.named('slate').replace(bullet_size='4.6cqh'))
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Four built-ins ship with it — `warm`, `office`, `dark`, `slate`. To start from
|
|
168
|
+
one, print it as a file you can edit:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
pypresent themes # what there is
|
|
172
|
+
pypresent themes dark > mine.toml
|
|
173
|
+
pypresent build --theme mine.toml
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
`css=` is still there for the one selector no token covers.
|
|
177
|
+
See [the theme reference](docs/README.md#themes) for every token.
|
|
178
|
+
|
|
179
|
+
## Right to left
|
|
180
|
+
|
|
181
|
+
`lang='he'` implies `dir="rtl"`, which mirrors the whole layout — bullets, the
|
|
182
|
+
two-tone title rule, the cover band, the arrow keys — and switches to a
|
|
183
|
+
Hebrew-first font stack, while keeping code and output left to right, because
|
|
184
|
+
Python does not read right to left.
|
|
185
|
+
|
|
186
|
+
## Commands
|
|
187
|
+
|
|
188
|
+
| | |
|
|
189
|
+
| --- | --- |
|
|
190
|
+
| `pypresent build` | run the source notebook, then the slide notebook, check, render |
|
|
191
|
+
| `pypresent build --skip-source-run` | leave the source notebook alone |
|
|
192
|
+
| `pypresent build --skip-slides-run` | check and render the stored outputs |
|
|
193
|
+
| `pypresent render` | render only, no kernel and no check |
|
|
194
|
+
| `pypresent check` | what has drifted, said and not corrected |
|
|
195
|
+
| `pypresent export --mode nb --format html` | the source notebook through nbconvert |
|
|
196
|
+
| `pypresent themes [name]` | the built-in themes |
|
|
197
|
+
|
|
198
|
+
## It also takes a markdown file
|
|
199
|
+
|
|
200
|
+
A `.md` file works as a source, cut into slides by its headings and `---` lines,
|
|
201
|
+
with a front matter block declaring the deck. It quotes nothing — there is no
|
|
202
|
+
notebook to quote — so it is the lesser half of this, but it is there when a talk
|
|
203
|
+
has no code in it:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
pypresent render talk.md
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
`--format md` writes slides back out the same way. See
|
|
210
|
+
[the docs](docs/README.md#writing-slides).
|
|
211
|
+
|
|
212
|
+
## Documentation
|
|
213
|
+
|
|
214
|
+
**[The documentation is one page](docs/README.md)**, with everything on it:
|
|
215
|
+
|
|
216
|
+
- [Quickstart](docs/README.md#quickstart) — from nothing to a deck
|
|
217
|
+
- [Writing slides](docs/README.md#writing-slides) — every block, and what it is for
|
|
218
|
+
- [Themes](docs/README.md#themes) — every token, and how to ship your own
|
|
219
|
+
- [The command line](docs/README.md#the-command-line)
|
|
220
|
+
- [The Python API](docs/README.md#the-python-api)
|
|
221
|
+
|
|
222
|
+
And [`demos/`](demos/) is the same thing as decks you can open — every block, the
|
|
223
|
+
four themes, a right-to-left deck, a hand-written theme, and a notebook deck that
|
|
224
|
+
quotes its lecture.
|
|
225
|
+
|
|
226
|
+
## Why not reveal.js / Quarto / RISE
|
|
227
|
+
|
|
228
|
+
Those are all good, and all bigger. `pypresent` is for one case: a lecture
|
|
229
|
+
notebook that must stay the single source of the code, and a deck of it that
|
|
230
|
+
must be one file with no toolchain to reproduce. If you want speaker view,
|
|
231
|
+
fragments, plugins and a themeing ecosystem, use reveal.js.
|
|
232
|
+
|
|
233
|
+
## License
|
|
234
|
+
|
|
235
|
+
MIT — see [LICENSE](LICENSE).
|