afterpython 0.4.0__tar.gz → 0.4.2__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.
- {afterpython-0.4.0 → afterpython-0.4.2}/PKG-INFO +18 -16
- {afterpython-0.4.0 → afterpython-0.4.2}/README.md +3 -2
- {afterpython-0.4.0 → afterpython-0.4.2}/pyproject.toml +16 -15
- {afterpython-0.4.0 → afterpython-0.4.2}/pyproject.toml.orig +16 -16
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/builders/__init__.py +4 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/builders/build_pdoc.py +7 -0
- afterpython-0.4.2/src/afterpython/builders/comments_json.py +107 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/builders/jupyter_notebook.py +23 -7
- afterpython-0.4.2/src/afterpython/builders/marimo_content.py +467 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/builders/marimo_notebook.py +7 -6
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/commands/build.py +74 -55
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/commands/clean.py +6 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/commands/dev.py +19 -1
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/commands/init.py +113 -51
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/main.py +3 -1
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/const.py +1 -1
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/templates/afterpython-template.toml +6 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/templates/ci-workflow-template.yml +10 -10
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/templates/deploy-workflow-template.yml +2 -2
- afterpython-0.4.2/src/afterpython/templates/pdoc/custom.css +37 -0
- afterpython-0.4.2/src/afterpython/templates/pdoc/frame.html.jinja2 +21 -0
- afterpython-0.4.2/src/afterpython/templates/pdoc/syntax-highlighting.css +155 -0
- afterpython-0.4.2/src/afterpython/templates/pdoc/theme.css +44 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/templates/release-workflow-template.yml +1 -1
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/templates/ruff-template.toml +1 -1
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/tools/myst.py +36 -19
- afterpython-0.4.0/src/afterpython/templates/pdoc/frame.html.jinja2 +0 -7
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/__init__.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/_io/toml.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/_io/yaml.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/_paths.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/_typing.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/builders/content_json.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/builders/faq_json.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/builders/index_md.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/builders/llms_txt.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/builders/markdown.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/builders/metadata.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/builders/url_md.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/__init__.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/commands/add.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/commands/bump.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/commands/changelog.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/commands/check.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/commands/commit_msg.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/commands/format.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/commands/init_branch_rules.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/commands/install.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/commands/lint.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/commands/lock.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/commands/prek.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/commands/preview.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/commands/release.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/commands/remove.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/commands/serve.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/commands/start.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/commands/sync.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/cli/commands/update.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/main.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/pcu.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/py.typed +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/templates/cliff-template.toml +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/templates/dependabot-template.yml +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/templates/pre-commit-config-template.yaml +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/templates/ty-template.toml +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/tools/_afterpython.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/tools/_git.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/tools/branch_rules.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/tools/github_actions.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/tools/prek.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/tools/pyproject.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/utils.py +0 -0
- {afterpython-0.4.0 → afterpython-0.4.2}/src/afterpython/version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: afterpython
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: CLI tool to streamline Python package maintenance and generate a dedicated project website
|
|
5
5
|
Keywords: package-maintenance,project-website,static-site-generator,developer-tools,documentation,cli-tool,ci/cd,mystmd,semantic-release,python-packaging
|
|
6
6
|
Author: Stephen Yau
|
|
@@ -11,26 +11,27 @@ Classifier: Intended Audience :: Developers
|
|
|
11
11
|
Classifier: Topic :: Software Development :: Build Tools
|
|
12
12
|
Classifier: Topic :: Software Development :: Documentation
|
|
13
13
|
Classifier: Typing :: Typed
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.13
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
-
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
17
|
+
Requires-Dist: click>=8.5.1
|
|
18
18
|
Requires-Dist: trogon>=0.6.0
|
|
19
|
-
Requires-Dist: httpx2>=2.
|
|
20
|
-
Requires-Dist: tomlkit>=0.15.
|
|
19
|
+
Requires-Dist: httpx2>=2.16.0
|
|
20
|
+
Requires-Dist: tomlkit>=0.15.2
|
|
21
21
|
Requires-Dist: ruamel-yaml>=0.19.1
|
|
22
|
-
Requires-Dist: gitpython>=3.2.
|
|
23
|
-
Requires-Dist: python-dotenv>=1.2.
|
|
22
|
+
Requires-Dist: gitpython>=3.2.1
|
|
23
|
+
Requires-Dist: python-dotenv>=1.2.4
|
|
24
24
|
Requires-Dist: pyproject-metadata>=0.12.1
|
|
25
|
-
Requires-Dist: jupytext>=1.19.
|
|
26
|
-
Requires-Dist: mystmd>=1.
|
|
25
|
+
Requires-Dist: jupytext>=1.19.6
|
|
26
|
+
Requires-Dist: mystmd>=1.12.0
|
|
27
27
|
Requires-Dist: pdoc>=16.0.0
|
|
28
|
-
Requires-Dist: ruff>=0.
|
|
29
|
-
Requires-Dist: prek>=0.5.
|
|
30
|
-
Requires-Dist: ty>=0.0.
|
|
28
|
+
Requires-Dist: ruff>=0.17.4
|
|
29
|
+
Requires-Dist: prek>=0.5.10
|
|
30
|
+
Requires-Dist: ty>=0.0.99
|
|
31
31
|
Requires-Dist: git-cliff>=2.14.2
|
|
32
|
-
Requires-Dist:
|
|
33
|
-
Requires-
|
|
32
|
+
Requires-Dist: questionary>=2.1.1
|
|
33
|
+
Requires-Dist: marimo[recommended,lsp]>=0.25.2 ; extra == 'marimo'
|
|
34
|
+
Requires-Python: >=3.13
|
|
34
35
|
Project-URL: homepage, https://afterpython.afterpython.org
|
|
35
36
|
Project-URL: repository, https://github.com/AfterPythonOrg/afterpython
|
|
36
37
|
Project-URL: documentation, https://afterpython.afterpython.org/doc
|
|
@@ -44,8 +45,8 @@ Description-Content-Type: text/markdown
|
|
|
44
45
|
[](https://pypi.org/project/afterpython)
|
|
45
46
|

|
|
46
47
|
[](https://github.com/AfterPythonOrg/afterpython/discussions)
|
|
47
|
-
[](https://deepwiki.com/AfterPythonOrg/afterpython)
|
|
48
48
|
[](https://codewiki.google/github.com/afterpythonorg/afterpython?utm_source=badge&utm_medium=github&utm_campaign=github.com/afterpythonorg/afterpython)
|
|
49
|
+
<!--[](https://deepwiki.com/AfterPythonOrg/afterpython)-->
|
|
49
50
|
<!--  -->
|
|
50
51
|
<!-- [](https://pixi.sh) -->
|
|
51
52
|
|
|
@@ -53,6 +54,7 @@ Description-Content-Type: text/markdown
|
|
|
53
54
|
[MyST]: https://mystmd.org
|
|
54
55
|
[MyST Markdown]: https://mystmd.org/spec/
|
|
55
56
|
[Jupyter Notebook]: https://jupyter.org
|
|
57
|
+
[marimo]: https://marimo.io
|
|
56
58
|
[pre-commit]: https://pre-commit.com
|
|
57
59
|
[pagefind]: https://pagefind.app
|
|
58
60
|
[SemVer]: https://semver.org
|
|
@@ -80,7 +82,7 @@ First-time maintainers must learn multiple tools and concepts, e.g. [MyST], [Sem
|
|
|
80
82
|
|
|
81
83
|
|
|
82
84
|
## Core Features
|
|
83
|
-
- [x] Write content directly in [MyST Markdown]
|
|
85
|
+
- [x] Write content directly in [MyST Markdown], [Jupyter Notebook] or [marimo] notebooks, with reproducible outputs for marimo
|
|
84
86
|
- [x] Go from writing to **website deployment in minutes** — no need to learn any of the underlying tools
|
|
85
87
|
- [x] Centralize all your content in a modern, **unified project website** — from documentation to blog posts
|
|
86
88
|
- [x] Zero-config orchestration — Pre-configured modern tooling with sane defaults (see [Tech Stack](#tech-stack)), so you can start maintaining packages immediately **without learning each tool**
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
[](https://pypi.org/project/afterpython)
|
|
6
6
|

|
|
7
7
|
[](https://github.com/AfterPythonOrg/afterpython/discussions)
|
|
8
|
-
[](https://deepwiki.com/AfterPythonOrg/afterpython)
|
|
9
8
|
[](https://codewiki.google/github.com/afterpythonorg/afterpython?utm_source=badge&utm_medium=github&utm_campaign=github.com/afterpythonorg/afterpython)
|
|
9
|
+
<!--[](https://deepwiki.com/AfterPythonOrg/afterpython)-->
|
|
10
10
|
<!--  -->
|
|
11
11
|
<!-- [](https://pixi.sh) -->
|
|
12
12
|
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
[MyST]: https://mystmd.org
|
|
15
15
|
[MyST Markdown]: https://mystmd.org/spec/
|
|
16
16
|
[Jupyter Notebook]: https://jupyter.org
|
|
17
|
+
[marimo]: https://marimo.io
|
|
17
18
|
[pre-commit]: https://pre-commit.com
|
|
18
19
|
[pagefind]: https://pagefind.app
|
|
19
20
|
[SemVer]: https://semver.org
|
|
@@ -41,7 +42,7 @@ First-time maintainers must learn multiple tools and concepts, e.g. [MyST], [Sem
|
|
|
41
42
|
|
|
42
43
|
|
|
43
44
|
## Core Features
|
|
44
|
-
- [x] Write content directly in [MyST Markdown]
|
|
45
|
+
- [x] Write content directly in [MyST Markdown], [Jupyter Notebook] or [marimo] notebooks, with reproducible outputs for marimo
|
|
45
46
|
- [x] Go from writing to **website deployment in minutes** — no need to learn any of the underlying tools
|
|
46
47
|
- [x] Centralize all your content in a modern, **unified project website** — from documentation to blog posts
|
|
47
48
|
- [x] Zero-config orchestration — Pre-configured modern tooling with sane defaults (see [Tech Stack](#tech-stack)), so you can start maintaining packages immediately **without learning each tool**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "afterpython"
|
|
3
|
-
version = "0.4.
|
|
3
|
+
version = "0.4.2"
|
|
4
4
|
description = "CLI tool to streamline Python package maintenance and generate a dedicated project website"
|
|
5
5
|
license = "Apache-2.0"
|
|
6
6
|
readme = "README.md"
|
|
@@ -22,27 +22,28 @@ classifiers = [
|
|
|
22
22
|
"Topic :: Software Development :: Build Tools",
|
|
23
23
|
"Topic :: Software Development :: Documentation",
|
|
24
24
|
"Typing :: Typed",
|
|
25
|
-
"Programming Language :: Python :: 3.12",
|
|
26
25
|
"Programming Language :: Python :: 3.13",
|
|
27
26
|
"Programming Language :: Python :: 3.14",
|
|
27
|
+
"Programming Language :: Python :: 3.15",
|
|
28
28
|
]
|
|
29
|
-
requires-python = ">=3.
|
|
29
|
+
requires-python = ">=3.13"
|
|
30
30
|
dependencies = [
|
|
31
|
-
"click>=8.5.
|
|
31
|
+
"click>=8.5.1",
|
|
32
32
|
"trogon>=0.6.0",
|
|
33
|
-
"httpx2>=2.
|
|
34
|
-
"tomlkit>=0.15.
|
|
33
|
+
"httpx2>=2.16.0",
|
|
34
|
+
"tomlkit>=0.15.2",
|
|
35
35
|
"ruamel-yaml>=0.19.1",
|
|
36
|
-
"gitpython>=3.2.
|
|
37
|
-
"python-dotenv>=1.2.
|
|
36
|
+
"gitpython>=3.2.1",
|
|
37
|
+
"python-dotenv>=1.2.4",
|
|
38
38
|
"pyproject-metadata>=0.12.1",
|
|
39
|
-
"jupytext>=1.19.
|
|
40
|
-
"mystmd>=1.
|
|
39
|
+
"jupytext>=1.19.6",
|
|
40
|
+
"mystmd>=1.12.0",
|
|
41
41
|
"pdoc>=16.0.0",
|
|
42
|
-
"ruff>=0.
|
|
43
|
-
"prek>=0.5.
|
|
44
|
-
"ty>=0.0.
|
|
42
|
+
"ruff>=0.17.4",
|
|
43
|
+
"prek>=0.5.10",
|
|
44
|
+
"ty>=0.0.99",
|
|
45
45
|
"git-cliff>=2.14.2",
|
|
46
|
+
"questionary>=2.1.1",
|
|
46
47
|
]
|
|
47
48
|
|
|
48
49
|
[[project.authors]]
|
|
@@ -50,7 +51,7 @@ name = "Stephen Yau"
|
|
|
50
51
|
email = "softwareentrepreneer+afterpython@gmail.com"
|
|
51
52
|
|
|
52
53
|
[project.optional-dependencies]
|
|
53
|
-
marimo = ["marimo[recommended,lsp]>=0.25.
|
|
54
|
+
marimo = ["marimo[recommended,lsp]>=0.25.2"]
|
|
54
55
|
|
|
55
56
|
[project.urls]
|
|
56
57
|
homepage = "https://afterpython.afterpython.org"
|
|
@@ -62,7 +63,7 @@ ap = "afterpython.main:run_cli"
|
|
|
62
63
|
pcu = "afterpython.main:run_pcu"
|
|
63
64
|
|
|
64
65
|
[build-system]
|
|
65
|
-
requires = ["uv_build>=0.
|
|
66
|
+
requires = ["uv_build>=0.13.7,<0.14.0"]
|
|
66
67
|
build-backend = "uv_build"
|
|
67
68
|
|
|
68
69
|
[tool.uv.build-backend]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "afterpython"
|
|
3
|
-
version = "0.4.
|
|
3
|
+
version = "0.4.2"
|
|
4
4
|
description = "CLI tool to streamline Python package maintenance and generate a dedicated project website"
|
|
5
5
|
license = "Apache-2.0"
|
|
6
6
|
authors = [
|
|
@@ -25,32 +25,32 @@ classifiers = [
|
|
|
25
25
|
"Topic :: Software Development :: Build Tools",
|
|
26
26
|
"Topic :: Software Development :: Documentation",
|
|
27
27
|
"Typing :: Typed",
|
|
28
|
-
"Programming Language :: Python :: 3.12",
|
|
29
28
|
"Programming Language :: Python :: 3.13",
|
|
30
29
|
"Programming Language :: Python :: 3.14",
|
|
31
|
-
|
|
30
|
+
"Programming Language :: Python :: 3.15",
|
|
32
31
|
]
|
|
33
|
-
requires-python = ">=3.
|
|
32
|
+
requires-python = ">=3.13"
|
|
34
33
|
dependencies = [
|
|
35
|
-
"click>=8.5.
|
|
34
|
+
"click>=8.5.1",
|
|
36
35
|
"trogon>=0.6.0",
|
|
37
|
-
"httpx2>=2.
|
|
38
|
-
"tomlkit>=0.15.
|
|
36
|
+
"httpx2>=2.16.0",
|
|
37
|
+
"tomlkit>=0.15.2",
|
|
39
38
|
"ruamel-yaml>=0.19.1",
|
|
40
|
-
"gitpython>=3.2.
|
|
41
|
-
"python-dotenv>=1.2.
|
|
39
|
+
"gitpython>=3.2.1",
|
|
40
|
+
"python-dotenv>=1.2.4",
|
|
42
41
|
"pyproject-metadata>=0.12.1",
|
|
43
|
-
"jupytext>=1.19.
|
|
44
|
-
"mystmd>=1.
|
|
42
|
+
"jupytext>=1.19.6",
|
|
43
|
+
"mystmd>=1.12.0",
|
|
45
44
|
"pdoc>=16.0.0",
|
|
46
|
-
"ruff>=0.
|
|
47
|
-
"prek>=0.5.
|
|
48
|
-
"ty>=0.0.
|
|
45
|
+
"ruff>=0.17.4",
|
|
46
|
+
"prek>=0.5.10",
|
|
47
|
+
"ty>=0.0.99",
|
|
49
48
|
"git-cliff>=2.14.2",
|
|
49
|
+
"questionary>=2.1.1",
|
|
50
50
|
]
|
|
51
51
|
|
|
52
52
|
[project.optional-dependencies]
|
|
53
|
-
marimo = ["marimo[recommended,lsp]>=0.25.
|
|
53
|
+
marimo = ["marimo[recommended,lsp]>=0.25.2"]
|
|
54
54
|
|
|
55
55
|
[project.urls]
|
|
56
56
|
homepage = "https://afterpython.afterpython.org"
|
|
@@ -62,7 +62,7 @@ ap = "afterpython.main:run_cli"
|
|
|
62
62
|
pcu = "afterpython.main:run_pcu"
|
|
63
63
|
|
|
64
64
|
[build-system]
|
|
65
|
-
requires = ["uv_build>=0.
|
|
65
|
+
requires = ["uv_build>=0.13.7,<0.14.0"]
|
|
66
66
|
build-backend = "uv_build"
|
|
67
67
|
|
|
68
68
|
[tool.uv]
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from afterpython.builders.build_pdoc import build_pdoc
|
|
2
|
+
from afterpython.builders.comments_json import build_comments_json
|
|
2
3
|
from afterpython.builders.content_json import build_content_json
|
|
3
4
|
from afterpython.builders.faq_json import build_faq_json
|
|
4
5
|
from afterpython.builders.index_md import (
|
|
@@ -7,16 +8,19 @@ from afterpython.builders.index_md import (
|
|
|
7
8
|
)
|
|
8
9
|
from afterpython.builders.jupyter_notebook import build_jupyter_notebooks
|
|
9
10
|
from afterpython.builders.llms_txt import build_llms_txt
|
|
11
|
+
from afterpython.builders.marimo_content import build_marimo_content
|
|
10
12
|
from afterpython.builders.marimo_notebook import build_marimo_readme
|
|
11
13
|
from afterpython.builders.markdown import build_markdown
|
|
12
14
|
from afterpython.builders.metadata import build_metadata
|
|
13
15
|
from afterpython.builders.url_md import build_url_md
|
|
14
16
|
|
|
15
17
|
__all__ = (
|
|
18
|
+
"build_comments_json",
|
|
16
19
|
"build_content_json",
|
|
17
20
|
"build_faq_json",
|
|
18
21
|
"build_jupyter_notebooks",
|
|
19
22
|
"build_llms_txt",
|
|
23
|
+
"build_marimo_content",
|
|
20
24
|
"build_marimo_readme",
|
|
21
25
|
"build_markdown",
|
|
22
26
|
"build_metadata",
|
|
@@ -19,9 +19,15 @@ def build_pdoc(base_path: str) -> None:
|
|
|
19
19
|
project logo appears in the top-left of every API page and links
|
|
20
20
|
back to the project website root (matches MyST's UX).
|
|
21
21
|
"""
|
|
22
|
+
from afterpython._io.toml import _from_tomlkit
|
|
23
|
+
from afterpython.tools._afterpython import read_afterpython
|
|
24
|
+
|
|
22
25
|
package_dir = find_package_directory()
|
|
23
26
|
output_dir = ap.paths.build_path / "api_reference"
|
|
24
27
|
template_dir = ap.paths.templates_path / "pdoc"
|
|
28
|
+
# e.g. "google"; unset leaves it to pdoc (a module's __docformat__, else restructuredtext)
|
|
29
|
+
website = _from_tomlkit(read_afterpython().get("website", {}))
|
|
30
|
+
docformat = website.get("api_reference_docformat")
|
|
25
31
|
|
|
26
32
|
click.echo("Building api_reference/...")
|
|
27
33
|
|
|
@@ -45,6 +51,7 @@ def build_pdoc(base_path: str) -> None:
|
|
|
45
51
|
f"{base_path}/",
|
|
46
52
|
"--template-directory",
|
|
47
53
|
str(template_dir),
|
|
54
|
+
*(["--docformat", str(docformat)] if docformat else []),
|
|
48
55
|
str(package_dir),
|
|
49
56
|
],
|
|
50
57
|
env=env,
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import re
|
|
5
|
+
|
|
6
|
+
import click
|
|
7
|
+
|
|
8
|
+
import afterpython as ap
|
|
9
|
+
|
|
10
|
+
GISCUS_API = "https://giscus.app/api/discussions/categories"
|
|
11
|
+
DEFAULT_CATEGORY = "Announcements"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _read_comments_config() -> dict:
|
|
15
|
+
from afterpython._io.toml import _from_tomlkit
|
|
16
|
+
from afterpython.tools._afterpython import read_afterpython
|
|
17
|
+
|
|
18
|
+
website = _from_tomlkit(read_afterpython().get("website", {}))
|
|
19
|
+
return dict(website.get("comments", {}))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _get_github_repo() -> str | None:
|
|
23
|
+
"""Return "owner/repo" from pyproject.toml's repository URL, or the git remote."""
|
|
24
|
+
from afterpython.tools._git import get_github_url
|
|
25
|
+
from afterpython.tools.pyproject import read_metadata
|
|
26
|
+
|
|
27
|
+
url = str(read_metadata().urls.get("repository", "")) or get_github_url() or ""
|
|
28
|
+
match = re.search(r"github\.com[/:]([^/]+)/([^/]+?)(?:\.git)?/?$", url)
|
|
29
|
+
return f"{match[1]}/{match[2]}" if match else None
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _fetch_giscus_categories(repo: str) -> dict:
|
|
33
|
+
"""Fetch the repo and category IDs giscus needs. Raises click.ClickException on failure."""
|
|
34
|
+
import httpx2
|
|
35
|
+
|
|
36
|
+
try:
|
|
37
|
+
response = httpx2.get(GISCUS_API, params={"repo": repo}, timeout=10.0)
|
|
38
|
+
except httpx2.HTTPError as e:
|
|
39
|
+
raise click.ClickException(f"could not reach giscus.app ({e})") from e
|
|
40
|
+
try:
|
|
41
|
+
data = response.json()
|
|
42
|
+
except ValueError:
|
|
43
|
+
data = {}
|
|
44
|
+
if response.status_code != 200 or "repositoryId" not in data:
|
|
45
|
+
error = data.get("error") or f"HTTP {response.status_code}"
|
|
46
|
+
raise click.ClickException(error)
|
|
47
|
+
return data
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def build_comments_json():
|
|
51
|
+
"""Build comments.json for the giscus comment section on content pages.
|
|
52
|
+
|
|
53
|
+
Reads [website.comments] in afterpython.toml. The website template only
|
|
54
|
+
shows comments when comments.json exists, so a disabled or failed setup
|
|
55
|
+
just leaves it out. Never fails the build.
|
|
56
|
+
"""
|
|
57
|
+
stale = ap.paths.website_path / "static" / "comments.json"
|
|
58
|
+
stale.unlink(missing_ok=True)
|
|
59
|
+
|
|
60
|
+
config = _read_comments_config()
|
|
61
|
+
if not config.get("enabled", False):
|
|
62
|
+
click.echo("Comments are disabled, skip building comments.json")
|
|
63
|
+
return
|
|
64
|
+
|
|
65
|
+
def warn(reason: str):
|
|
66
|
+
click.secho(f"Warning: skip comments, {reason}", fg="yellow")
|
|
67
|
+
|
|
68
|
+
repo = _get_github_repo()
|
|
69
|
+
if not repo:
|
|
70
|
+
warn(
|
|
71
|
+
"no GitHub repository found "
|
|
72
|
+
"(set [project.urls] repository in pyproject.toml)"
|
|
73
|
+
)
|
|
74
|
+
return
|
|
75
|
+
|
|
76
|
+
category = str(config.get("category") or DEFAULT_CATEGORY)
|
|
77
|
+
try:
|
|
78
|
+
data = _fetch_giscus_categories(repo)
|
|
79
|
+
except click.ClickException as e:
|
|
80
|
+
warn(
|
|
81
|
+
f"giscus is not ready for {repo}: {e.message}\n"
|
|
82
|
+
f" 1. Enable Discussions: https://github.com/{repo}/settings\n"
|
|
83
|
+
" 2. Install the giscus app: https://github.com/apps/giscus\n"
|
|
84
|
+
" Or set [website.comments] enabled = false in afterpython.toml"
|
|
85
|
+
)
|
|
86
|
+
return
|
|
87
|
+
|
|
88
|
+
category_id = next(
|
|
89
|
+
(c["id"] for c in data.get("categories", []) if c["name"] == category), None
|
|
90
|
+
)
|
|
91
|
+
if not category_id:
|
|
92
|
+
names = ", ".join(c["name"] for c in data.get("categories", []))
|
|
93
|
+
warn(
|
|
94
|
+
f'Discussions category "{category}" not found in {repo} '
|
|
95
|
+
f"(available: {names or 'none'})"
|
|
96
|
+
)
|
|
97
|
+
return
|
|
98
|
+
|
|
99
|
+
click.echo(f"Building comments.json ({repo}, {category})...")
|
|
100
|
+
comments = {
|
|
101
|
+
"repo": repo,
|
|
102
|
+
"repoId": data["repositoryId"],
|
|
103
|
+
"category": category,
|
|
104
|
+
"categoryId": category_id,
|
|
105
|
+
}
|
|
106
|
+
with open(ap.paths.build_path / "comments.json", "w") as f:
|
|
107
|
+
json.dump(comments, f, indent=2)
|
|
@@ -17,7 +17,7 @@ def _read_notebook(notebook_path: Path, content_path: Path) -> dict | None:
|
|
|
17
17
|
Notebook dict if valid, None if invalid or error occurred
|
|
18
18
|
"""
|
|
19
19
|
try:
|
|
20
|
-
with open(notebook_path) as f:
|
|
20
|
+
with open(notebook_path, encoding="utf-8") as f:
|
|
21
21
|
notebook = json.load(f)
|
|
22
22
|
except json.JSONDecodeError:
|
|
23
23
|
click.echo(f"✗ Skipping {content_path} - invalid or empty JSON")
|
|
@@ -36,8 +36,11 @@ def _read_notebook(notebook_path: Path, content_path: Path) -> dict | None:
|
|
|
36
36
|
|
|
37
37
|
def _write_notebook(notebook: dict, notebook_path: Path):
|
|
38
38
|
"""Write a notebook dict to file."""
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
# match Jupyter's own formatting (unescaped unicode, trailing newline) so
|
|
40
|
+
# rewriting a committed notebook doesn't produce a noisy diff
|
|
41
|
+
with open(notebook_path, "w", encoding="utf-8") as f:
|
|
42
|
+
json.dump(notebook, f, indent=1, ensure_ascii=False)
|
|
43
|
+
f.write("\n")
|
|
41
44
|
|
|
42
45
|
|
|
43
46
|
def _has_frontmatter(notebook: dict) -> bool:
|
|
@@ -243,8 +246,10 @@ def build_jupyter_notebooks():
|
|
|
243
246
|
|
|
244
247
|
# Iterate over all .ipynb files once
|
|
245
248
|
for notebook_path in path.rglob("*.ipynb"):
|
|
246
|
-
# Skip
|
|
247
|
-
|
|
249
|
+
# Skip MyST output and hidden tool dirs (.ipynb_checkpoints/,
|
|
250
|
+
# .virtual_documents/), which aren't content
|
|
251
|
+
rel_parts = notebook_path.relative_to(path).parts
|
|
252
|
+
if "_build" in rel_parts or any(p.startswith(".") for p in rel_parts):
|
|
248
253
|
continue
|
|
249
254
|
|
|
250
255
|
# Get path relative to afterpython/
|
|
@@ -264,9 +269,20 @@ def build_jupyter_notebooks():
|
|
|
264
269
|
# Track if notebook was modified
|
|
265
270
|
modified = False
|
|
266
271
|
|
|
267
|
-
# Add molab badge if enabled
|
|
272
|
+
# Add molab badge if enabled. A notebook generated from a marimo .py
|
|
273
|
+
# isn't committed, so the badge must open the .py instead.
|
|
268
274
|
if add_molab_badge and github_url:
|
|
269
|
-
|
|
275
|
+
generated_from = (
|
|
276
|
+
notebook.get("metadata", {})
|
|
277
|
+
.get("afterpython", {})
|
|
278
|
+
.get("generated_from")
|
|
279
|
+
)
|
|
280
|
+
molab_path = (
|
|
281
|
+
content_path.with_name(generated_from)
|
|
282
|
+
if generated_from
|
|
283
|
+
else content_path
|
|
284
|
+
)
|
|
285
|
+
_add_molab_badge_to_notebook(notebook, github_url, molab_path)
|
|
270
286
|
modified = True
|
|
271
287
|
|
|
272
288
|
# Add thumbnail to frontmatter
|