polyglot-pmd 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.
- polyglot_pmd-0.1.0/.gitignore +6 -0
- polyglot_pmd-0.1.0/LICENSE +22 -0
- polyglot_pmd-0.1.0/PKG-INFO +127 -0
- polyglot_pmd-0.1.0/README.md +106 -0
- polyglot_pmd-0.1.0/example.pmd +34 -0
- polyglot_pmd-0.1.0/pyproject.toml +47 -0
- polyglot_pmd-0.1.0/spec.md +437 -0
- polyglot_pmd-0.1.0/src/pmd_notebook/__init__.py +14 -0
- polyglot_pmd-0.1.0/src/pmd_notebook/bindings.py +104 -0
- polyglot_pmd-0.1.0/src/pmd_notebook/cli.py +101 -0
- polyglot_pmd-0.1.0/src/pmd_notebook/graph.py +163 -0
- polyglot_pmd-0.1.0/src/pmd_notebook/models.py +75 -0
- polyglot_pmd-0.1.0/src/pmd_notebook/parser.py +128 -0
- polyglot_pmd-0.1.0/src/pmd_notebook/render.py +84 -0
- polyglot_pmd-0.1.0/src/pmd_notebook/runner.py +189 -0
- polyglot_pmd-0.1.0/src/pmd_notebook/sql_engine.py +39 -0
- polyglot_pmd-0.1.0/tests/test_conformance.py +265 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PMD contributors
|
|
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.
|
|
22
|
+
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: polyglot-pmd
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A reusable Python implementation of the PMD polyglot Markdown notebook format
|
|
5
|
+
Author: PMD contributors
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Topic :: Text Processing :: Markup
|
|
13
|
+
Requires-Python: >=3.10
|
|
14
|
+
Requires-Dist: markdown-it-py<5,>=3.0
|
|
15
|
+
Requires-Dist: pyyaml<7,>=6.0
|
|
16
|
+
Provides-Extra: dev
|
|
17
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
18
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
19
|
+
Requires-Dist: twine>=5; extra == 'dev'
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# Polyglot PMD
|
|
23
|
+
|
|
24
|
+
`polyglot-pmd` is a reusable Python implementation of the PMD 0.1 polyglot
|
|
25
|
+
Markdown notebook specification in [`spec.md`](spec.md). It parses and validates
|
|
26
|
+
plain-text `.pmd` documents, resolves their dependency graph, runs every cell in
|
|
27
|
+
an isolated process, and renders a self-contained HTML report.
|
|
28
|
+
|
|
29
|
+
> PMD cells execute arbitrary code with the privileges of the user running
|
|
30
|
+
> `pmd`. Review a document before running, testing, or rendering it.
|
|
31
|
+
|
|
32
|
+
## Install
|
|
33
|
+
|
|
34
|
+
From this checkout:
|
|
35
|
+
|
|
36
|
+
```console
|
|
37
|
+
python -m pip install -e ./pmd-impl
|
|
38
|
+
pmd check pmd-impl/example.pmd --graph
|
|
39
|
+
pmd run pmd-impl/example.pmd --fresh
|
|
40
|
+
pmd test pmd-impl/example.pmd
|
|
41
|
+
pmd render pmd-impl/example.pmd --to html
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Once published:
|
|
45
|
+
|
|
46
|
+
```console
|
|
47
|
+
python -m pip install polyglot-pmd
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Python 3.10 or newer is required. The package depends only on PyYAML and
|
|
51
|
+
markdown-it-py. Language interpreters used by a document must also be installed.
|
|
52
|
+
|
|
53
|
+
## Library API
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from pathlib import Path
|
|
57
|
+
|
|
58
|
+
from pmd_notebook import Runner, load, render_html, validate
|
|
59
|
+
|
|
60
|
+
document = load("analysis.pmd")
|
|
61
|
+
errors = validate(document)
|
|
62
|
+
if errors:
|
|
63
|
+
raise ValueError("\n".join(errors))
|
|
64
|
+
|
|
65
|
+
result = Runner().run(document, fresh=True)
|
|
66
|
+
if not result.ok:
|
|
67
|
+
failed = [cell for cell in result.cells if cell.status == "failed"]
|
|
68
|
+
|
|
69
|
+
page, render_result = render_html(document, result)
|
|
70
|
+
Path("analysis.html").write_text(page, encoding="utf-8")
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The public API exports `parse`, `load`, `validate`, `closure`,
|
|
74
|
+
`topological_order`, `graph_lines`, `Runner`, `Cache`, `execute`, and
|
|
75
|
+
`render_html`, plus the corresponding result dataclasses.
|
|
76
|
+
|
|
77
|
+
## Context Bindings
|
|
78
|
+
|
|
79
|
+
Each cell receives `PMD_CELL_OUT` and `PMD_CTX_FILE`. Built-in engines add these
|
|
80
|
+
bindings:
|
|
81
|
+
|
|
82
|
+
| Engine | Read | Write | Presence check |
|
|
83
|
+
| --- | --- | --- | --- |
|
|
84
|
+
| Python | `ctx.get("key")` or `ctx.key` | `ctx.set("key", value)` or `ctx.key = value` | `ctx.has("key")` |
|
|
85
|
+
| Bash/sh | `ctx_get key` | `ctx_set key 'JSON_VALUE'` | `ctx_has key` |
|
|
86
|
+
| PowerShell | `Get-CtxValue key` | `Set-CtxValue key $value` | `Test-CtxValue key` |
|
|
87
|
+
| SQL | `ctx_get('key')` | `ctx_set('key', 'JSON_VALUE')` | not provided |
|
|
88
|
+
|
|
89
|
+
Shell reads print JSON, so a stored string includes JSON quotes. SQL uses an
|
|
90
|
+
isolated in-memory SQLite database. Override commands under frontmatter
|
|
91
|
+
`engines.<language>.command`; custom engines still receive the two environment
|
|
92
|
+
variables but must provide their own context helpers.
|
|
93
|
+
|
|
94
|
+
Write `.png`, `.jpg`, `.jpeg`, `.svg`, `.csv`, `.md`, or any other attachment
|
|
95
|
+
under `PMD_CELL_OUT`. The HTML renderer embeds all files and makes no network
|
|
96
|
+
requests. Python also receives `display.markdown`, `display.csv`,
|
|
97
|
+
`display.image`, and `display.file` convenience methods.
|
|
98
|
+
|
|
99
|
+
## Caching
|
|
100
|
+
|
|
101
|
+
Successful dependency results are cached under `PMD_CACHE_DIR`, or
|
|
102
|
+
`~/.cache/polyglot-pmd` by default. Keys include source, attributes, engine
|
|
103
|
+
command, and the resolved transitive context. `--fresh` bypasses reads. A cell
|
|
104
|
+
named by `--cell` always executes; only its dependencies may come from cache.
|
|
105
|
+
Context itself remains scoped to one invocation.
|
|
106
|
+
|
|
107
|
+
## Optional Workbench
|
|
108
|
+
|
|
109
|
+
Run `python server.py` and open `http://localhost:8765`. The local workbench is
|
|
110
|
+
not installed as part of the Python package.
|
|
111
|
+
|
|
112
|
+
## Publishing to PyPI
|
|
113
|
+
|
|
114
|
+
1. Replace package author metadata if desired and choose the final project URL.
|
|
115
|
+
2. Run `python -m pip install -e ".[dev]"`.
|
|
116
|
+
3. Run `pytest` and `python -m build`.
|
|
117
|
+
4. Check artifacts with `python -m twine check dist/*`.
|
|
118
|
+
5. Upload to TestPyPI, install-test the wheel, then upload to PyPI.
|
|
119
|
+
|
|
120
|
+
```console
|
|
121
|
+
python -m twine upload --repository testpypi dist/*
|
|
122
|
+
python -m twine upload dist/*
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
PDF and `.ipynb` are optional PMD render targets and are intentionally not
|
|
126
|
+
implemented. The CLI refuses them clearly instead of silently losing content.
|
|
127
|
+
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Polyglot PMD
|
|
2
|
+
|
|
3
|
+
`polyglot-pmd` is a reusable Python implementation of the PMD 0.1 polyglot
|
|
4
|
+
Markdown notebook specification in [`spec.md`](spec.md). It parses and validates
|
|
5
|
+
plain-text `.pmd` documents, resolves their dependency graph, runs every cell in
|
|
6
|
+
an isolated process, and renders a self-contained HTML report.
|
|
7
|
+
|
|
8
|
+
> PMD cells execute arbitrary code with the privileges of the user running
|
|
9
|
+
> `pmd`. Review a document before running, testing, or rendering it.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
From this checkout:
|
|
14
|
+
|
|
15
|
+
```console
|
|
16
|
+
python -m pip install -e ./pmd-impl
|
|
17
|
+
pmd check pmd-impl/example.pmd --graph
|
|
18
|
+
pmd run pmd-impl/example.pmd --fresh
|
|
19
|
+
pmd test pmd-impl/example.pmd
|
|
20
|
+
pmd render pmd-impl/example.pmd --to html
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Once published:
|
|
24
|
+
|
|
25
|
+
```console
|
|
26
|
+
python -m pip install polyglot-pmd
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Python 3.10 or newer is required. The package depends only on PyYAML and
|
|
30
|
+
markdown-it-py. Language interpreters used by a document must also be installed.
|
|
31
|
+
|
|
32
|
+
## Library API
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from pathlib import Path
|
|
36
|
+
|
|
37
|
+
from pmd_notebook import Runner, load, render_html, validate
|
|
38
|
+
|
|
39
|
+
document = load("analysis.pmd")
|
|
40
|
+
errors = validate(document)
|
|
41
|
+
if errors:
|
|
42
|
+
raise ValueError("\n".join(errors))
|
|
43
|
+
|
|
44
|
+
result = Runner().run(document, fresh=True)
|
|
45
|
+
if not result.ok:
|
|
46
|
+
failed = [cell for cell in result.cells if cell.status == "failed"]
|
|
47
|
+
|
|
48
|
+
page, render_result = render_html(document, result)
|
|
49
|
+
Path("analysis.html").write_text(page, encoding="utf-8")
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The public API exports `parse`, `load`, `validate`, `closure`,
|
|
53
|
+
`topological_order`, `graph_lines`, `Runner`, `Cache`, `execute`, and
|
|
54
|
+
`render_html`, plus the corresponding result dataclasses.
|
|
55
|
+
|
|
56
|
+
## Context Bindings
|
|
57
|
+
|
|
58
|
+
Each cell receives `PMD_CELL_OUT` and `PMD_CTX_FILE`. Built-in engines add these
|
|
59
|
+
bindings:
|
|
60
|
+
|
|
61
|
+
| Engine | Read | Write | Presence check |
|
|
62
|
+
| --- | --- | --- | --- |
|
|
63
|
+
| Python | `ctx.get("key")` or `ctx.key` | `ctx.set("key", value)` or `ctx.key = value` | `ctx.has("key")` |
|
|
64
|
+
| Bash/sh | `ctx_get key` | `ctx_set key 'JSON_VALUE'` | `ctx_has key` |
|
|
65
|
+
| PowerShell | `Get-CtxValue key` | `Set-CtxValue key $value` | `Test-CtxValue key` |
|
|
66
|
+
| SQL | `ctx_get('key')` | `ctx_set('key', 'JSON_VALUE')` | not provided |
|
|
67
|
+
|
|
68
|
+
Shell reads print JSON, so a stored string includes JSON quotes. SQL uses an
|
|
69
|
+
isolated in-memory SQLite database. Override commands under frontmatter
|
|
70
|
+
`engines.<language>.command`; custom engines still receive the two environment
|
|
71
|
+
variables but must provide their own context helpers.
|
|
72
|
+
|
|
73
|
+
Write `.png`, `.jpg`, `.jpeg`, `.svg`, `.csv`, `.md`, or any other attachment
|
|
74
|
+
under `PMD_CELL_OUT`. The HTML renderer embeds all files and makes no network
|
|
75
|
+
requests. Python also receives `display.markdown`, `display.csv`,
|
|
76
|
+
`display.image`, and `display.file` convenience methods.
|
|
77
|
+
|
|
78
|
+
## Caching
|
|
79
|
+
|
|
80
|
+
Successful dependency results are cached under `PMD_CACHE_DIR`, or
|
|
81
|
+
`~/.cache/polyglot-pmd` by default. Keys include source, attributes, engine
|
|
82
|
+
command, and the resolved transitive context. `--fresh` bypasses reads. A cell
|
|
83
|
+
named by `--cell` always executes; only its dependencies may come from cache.
|
|
84
|
+
Context itself remains scoped to one invocation.
|
|
85
|
+
|
|
86
|
+
## Optional Workbench
|
|
87
|
+
|
|
88
|
+
Run `python server.py` and open `http://localhost:8765`. The local workbench is
|
|
89
|
+
not installed as part of the Python package.
|
|
90
|
+
|
|
91
|
+
## Publishing to PyPI
|
|
92
|
+
|
|
93
|
+
1. Replace package author metadata if desired and choose the final project URL.
|
|
94
|
+
2. Run `python -m pip install -e ".[dev]"`.
|
|
95
|
+
3. Run `pytest` and `python -m build`.
|
|
96
|
+
4. Check artifacts with `python -m twine check dist/*`.
|
|
97
|
+
5. Upload to TestPyPI, install-test the wheel, then upload to PyPI.
|
|
98
|
+
|
|
99
|
+
```console
|
|
100
|
+
python -m twine upload --repository testpypi dist/*
|
|
101
|
+
python -m twine upload dist/*
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
PDF and `.ipynb` are optional PMD render targets and are intentionally not
|
|
105
|
+
implemented. The CLI refuses them clearly instead of silently losing content.
|
|
106
|
+
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
pmd: "0.1"
|
|
3
|
+
title: "Signal analysis"
|
|
4
|
+
timeout_default: "30s"
|
|
5
|
+
---
|
|
6
|
+
# Signal analysis
|
|
7
|
+
|
|
8
|
+
A minimal polyglot notebook. Each cell is isolated; data crosses boundaries through ctx.
|
|
9
|
+
|
|
10
|
+
```python {#generate independent=true tags=demo}
|
|
11
|
+
ctx.values = [3, 8, 13, 21, 34]
|
|
12
|
+
values = ctx.values
|
|
13
|
+
print(f"Generated {len(values)} observations")
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
```python {#summarize depends-on=generate}
|
|
19
|
+
values = ctx.values
|
|
20
|
+
average = sum(values) / len(values)
|
|
21
|
+
ctx.average = average
|
|
22
|
+
print(f"Mean signal: {average:.2f}")
|
|
23
|
+
display.markdown(f"## Result\n\nThe mean signal is **{average:.2f}**.", name="summary")
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
```python {#verify role=test test-of=summarize}
|
|
29
|
+
assert ctx.average > 0
|
|
30
|
+
print("Average is positive")
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.25"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "polyglot-pmd"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "A reusable Python implementation of the PMD polyglot Markdown notebook format"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "PMD contributors" }]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Development Status :: 3 - Alpha",
|
|
15
|
+
"Environment :: Console",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Topic :: Text Processing :: Markup",
|
|
19
|
+
]
|
|
20
|
+
dependencies = [
|
|
21
|
+
"markdown-it-py>=3.0,<5",
|
|
22
|
+
"PyYAML>=6.0,<7",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.optional-dependencies]
|
|
26
|
+
dev = ["build>=1.2", "pytest>=8", "twine>=5"]
|
|
27
|
+
|
|
28
|
+
[project.scripts]
|
|
29
|
+
pmd = "pmd_notebook.cli:main"
|
|
30
|
+
|
|
31
|
+
[tool.hatch.build.targets.wheel]
|
|
32
|
+
packages = ["src/pmd_notebook"]
|
|
33
|
+
|
|
34
|
+
[tool.hatch.build.targets.sdist]
|
|
35
|
+
include = [
|
|
36
|
+
"src/pmd_notebook",
|
|
37
|
+
"tests",
|
|
38
|
+
"LICENSE",
|
|
39
|
+
"README.md",
|
|
40
|
+
"pyproject.toml",
|
|
41
|
+
"spec.md",
|
|
42
|
+
"example.pmd",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
[tool.pytest.ini_options]
|
|
46
|
+
addopts = "-q"
|
|
47
|
+
testpaths = ["tests"]
|