afterpython 0.3.1__tar.gz → 0.3.3__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.
Files changed (64) hide show
  1. {afterpython-0.3.1 → afterpython-0.3.3}/PKG-INFO +5 -5
  2. {afterpython-0.3.1 → afterpython-0.3.3}/README.md +2 -2
  3. {afterpython-0.3.1 → afterpython-0.3.3}/pyproject.toml +4 -4
  4. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/builders/__init__.py +2 -0
  5. afterpython-0.3.3/src/afterpython/builders/build_pdoc.py +57 -0
  6. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/commands/build.py +38 -3
  7. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/commands/bump.py +1 -1
  8. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/commands/update.py +4 -1
  9. afterpython-0.3.3/src/afterpython/templates/pdoc/frame.html.jinja2 +7 -0
  10. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/templates/pre-commit-config-template.yaml +2 -2
  11. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/tools/_afterpython.py +2 -1
  12. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/tools/myst.py +3 -1
  13. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/__init__.py +0 -0
  14. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/_io/toml.py +0 -0
  15. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/_io/yaml.py +0 -0
  16. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/_paths.py +0 -0
  17. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/_typing.py +0 -0
  18. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/builders/content_json.py +0 -0
  19. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/builders/faq_json.py +0 -0
  20. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/builders/index_md.py +0 -0
  21. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/builders/jupyter_notebook.py +0 -0
  22. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/builders/llms_txt.py +0 -0
  23. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/builders/marimo_notebook.py +0 -0
  24. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/builders/markdown.py +0 -0
  25. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/builders/metadata.py +0 -0
  26. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/builders/url_md.py +0 -0
  27. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/__init__.py +0 -0
  28. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/commands/add.py +0 -0
  29. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/commands/check.py +0 -0
  30. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/commands/clean.py +0 -0
  31. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/commands/commit.py +0 -0
  32. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/commands/commitizen.py +0 -0
  33. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/commands/dev.py +0 -0
  34. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/commands/format.py +0 -0
  35. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/commands/init.py +0 -0
  36. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/commands/init_branch_rules.py +0 -0
  37. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/commands/install.py +0 -0
  38. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/commands/lock.py +0 -0
  39. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/commands/pre_commit.py +0 -0
  40. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/commands/preview.py +0 -0
  41. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/commands/release.py +0 -0
  42. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/commands/remove.py +0 -0
  43. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/commands/serve.py +0 -0
  44. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/commands/start.py +0 -0
  45. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/commands/sync.py +0 -0
  46. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/cli/main.py +0 -0
  47. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/const.py +0 -0
  48. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/main.py +0 -0
  49. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/pcu.py +0 -0
  50. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/py.typed +0 -0
  51. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/templates/ci-workflow-template.yml +0 -0
  52. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/templates/cz-template.toml +0 -0
  53. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/templates/dependabot-template.yml +0 -0
  54. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/templates/deploy-workflow-template.yml +0 -0
  55. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/templates/release-workflow-template.yml +0 -0
  56. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/templates/ruff-template.toml +0 -0
  57. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/tools/_git.py +0 -0
  58. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/tools/branch_rules.py +0 -0
  59. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/tools/commitizen.py +0 -0
  60. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/tools/github_actions.py +0 -0
  61. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/tools/pre_commit.py +0 -0
  62. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/tools/pyproject.py +0 -0
  63. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/utils.py +0 -0
  64. {afterpython-0.3.1 → afterpython-0.3.3}/src/afterpython/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: afterpython
3
- Version: 0.3.1
3
+ Version: 0.3.3
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
@@ -19,12 +19,12 @@ Requires-Dist: trogon>=0.6.0
19
19
  Requires-Dist: httpx>=0.28.1
20
20
  Requires-Dist: tomlkit>=0.14.0
21
21
  Requires-Dist: ruamel-yaml>=0.19.1
22
- Requires-Dist: gitpython>=3.1.49
22
+ Requires-Dist: gitpython>=3.1.50
23
23
  Requires-Dist: python-dotenv>=1.2.2
24
24
  Requires-Dist: pyproject-metadata>=0.11.0
25
25
  Requires-Dist: jupytext>=1.19.1
26
26
  Requires-Dist: mystmd>=1.9.0
27
- Requires-Dist: great-docs>=0.9
27
+ Requires-Dist: pdoc>=16.0.0
28
28
  Requires-Dist: ruff>=0.15.12
29
29
  Requires-Dist: pre-commit>=4.6.0
30
30
  Requires-Dist: commitizen>=4.13.10
@@ -53,7 +53,7 @@ Description-Content-Type: text/markdown
53
53
  [pre-commit]: https://pre-commit.com
54
54
  [pagefind]: https://pagefind.app
55
55
  [SemVer]: https://semver.org
56
- [great-docs]: https://posit-dev.github.io/great-docs/
56
+ [pdoc]: https://pdoc.dev/
57
57
  [GitHub Actions]: https://github.com/features/actions
58
58
  [PyTorch]: https://pytorch.org
59
59
  [Scikit-Learn]: https://scikit-learn.org
@@ -124,7 +124,7 @@ ap tui
124
124
  - [project-website-template]
125
125
  - [pre-commit]
126
126
  - [GitHub Actions]
127
- - [great-docs]
127
+ - [pdoc]
128
128
  - [commitizen]
129
129
  - [uv]
130
130
  - [ruff]
@@ -17,7 +17,7 @@
17
17
  [pre-commit]: https://pre-commit.com
18
18
  [pagefind]: https://pagefind.app
19
19
  [SemVer]: https://semver.org
20
- [great-docs]: https://posit-dev.github.io/great-docs/
20
+ [pdoc]: https://pdoc.dev/
21
21
  [GitHub Actions]: https://github.com/features/actions
22
22
  [PyTorch]: https://pytorch.org
23
23
  [Scikit-Learn]: https://scikit-learn.org
@@ -88,7 +88,7 @@ ap tui
88
88
  - [project-website-template]
89
89
  - [pre-commit]
90
90
  - [GitHub Actions]
91
- - [great-docs]
91
+ - [pdoc]
92
92
  - [commitizen]
93
93
  - [uv]
94
94
  - [ruff]
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "afterpython"
3
- version = "0.3.1"
3
+ version = "0.3.3"
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 = [
@@ -37,14 +37,14 @@ dependencies = [
37
37
  "httpx>=0.28.1",
38
38
  "tomlkit>=0.14.0",
39
39
  "ruamel-yaml>=0.19.1",
40
- "gitpython>=3.1.49",
40
+ "gitpython>=3.1.50",
41
41
  # "pygithub>=2.8.1",
42
42
  "python-dotenv>=1.2.2",
43
43
  "pyproject-metadata>=0.11.0",
44
44
  "jupytext>=1.19.1",
45
45
  # "jinja2>=3.1.6",
46
46
  "mystmd>=1.9.0",
47
- "great-docs>=0.9",
47
+ "pdoc>=16.0.0",
48
48
  "ruff>=0.15.12",
49
49
  "pre-commit>=4.6.0",
50
50
  "commitizen>=4.13.10",
@@ -64,7 +64,7 @@ pcu = "afterpython.main:run_pcu"
64
64
  # override-dependencies = ["platformdirs>=4.5.0", "nodeenv>=1.9.1"]
65
65
 
66
66
  [build-system]
67
- requires = ["uv_build>=0.11.8,<0.12.0"]
67
+ requires = ["uv_build>=0.11.12,<0.12.0"]
68
68
  build-backend = "uv_build"
69
69
 
70
70
  [tool.uv.build-backend]
@@ -1,3 +1,4 @@
1
+ from afterpython.builders.build_pdoc import build_pdoc
1
2
  from afterpython.builders.content_json import build_content_json
2
3
  from afterpython.builders.faq_json import build_faq_json
3
4
  from afterpython.builders.index_md import (
@@ -19,6 +20,7 @@ __all__ = (
19
20
  "build_marimo_readme",
20
21
  "build_markdown",
21
22
  "build_metadata",
23
+ "build_pdoc",
22
24
  "build_url_md",
23
25
  "create_placeholder_index_md_files",
24
26
  "delete_placeholder_index_md_files",
@@ -0,0 +1,57 @@
1
+ import os
2
+ import subprocess
3
+
4
+ import click
5
+
6
+ import afterpython as ap
7
+ from afterpython.tools.pyproject import find_package_directory
8
+
9
+
10
+ def build_pdoc(base_path: str) -> None:
11
+ """Generate API reference HTML from the user's package via pdoc.
12
+
13
+ Output goes to `_build/api_reference/` (the standard staging dir);
14
+ the build command is responsible for copying it into the website's
15
+ static dir.
16
+
17
+ `base_path` is "" for custom domains and "/{repo-name}" for GitHub
18
+ Pages — used to wire pdoc's logo + logo-link flags so that the
19
+ project logo appears in the top-left of every API page and links
20
+ back to the project website root (matches MyST's UX).
21
+ """
22
+ package_dir = find_package_directory()
23
+ output_dir = ap.paths.build_path / "api_reference"
24
+ template_dir = ap.paths.templates_path / "pdoc"
25
+
26
+ click.echo("Building api_reference/...")
27
+
28
+ # PDOC_ALLOW_EXEC=1 lets module-level subprocess calls run during pdoc's
29
+ # introspection import. Required because some deps (e.g. jupytext) shell
30
+ # out to `pandoc --version` at import time. Safe here: pdoc imports the
31
+ # user's own package, whose import-time behavior the user already trusts.
32
+ env = {**os.environ, "PDOC_ALLOW_EXEC": "1"}
33
+
34
+ # logo.svg is a project-website-template convention (always present in
35
+ # `_website/static/`); served at `{base_path}/logo.svg` once the site
36
+ # is built. logo-link points back to the project website root.
37
+ result = subprocess.run(
38
+ [
39
+ "pdoc",
40
+ "-o",
41
+ str(output_dir),
42
+ "--logo",
43
+ f"{base_path}/logo.svg",
44
+ "--logo-link",
45
+ f"{base_path}/",
46
+ "--template-directory",
47
+ str(template_dir),
48
+ str(package_dir),
49
+ ],
50
+ env=env,
51
+ check=False,
52
+ )
53
+ if result.returncode != 0:
54
+ raise click.ClickException(
55
+ f"pdoc failed with exit code {result.returncode}. "
56
+ f"Re-run `ap build --skip-api` to skip API reference generation."
57
+ )
@@ -24,6 +24,7 @@ from afterpython.builders import (
24
24
  build_marimo_readme,
25
25
  build_markdown,
26
26
  build_metadata,
27
+ build_pdoc,
27
28
  build_url_md,
28
29
  create_placeholder_index_md_files,
29
30
  delete_placeholder_index_md_files,
@@ -66,6 +67,22 @@ def determine_base_path() -> str:
66
67
  return f"/{repo_name}"
67
68
 
68
69
 
70
+ def _read_api_reference() -> bool:
71
+ """Read `[website].api_reference` from afterpython.toml. Defaults to False.
72
+
73
+ Off-by-default means freshly `ap init`'d projects don't blow up on
74
+ `ap build` before their package is import-ready or has docstrings —
75
+ pdoc errors are opt-in surface. Users enable the API reference by
76
+ setting the field to true.
77
+ """
78
+ from afterpython._io.toml import _from_tomlkit
79
+ from afterpython.tools._afterpython import read_afterpython
80
+
81
+ afterpython = read_afterpython()
82
+ website = _from_tomlkit(afterpython.get("website", {}))
83
+ return bool(website.get("api_reference", False))
84
+
85
+
69
86
  def prebuild():
70
87
  def _check_initialized():
71
88
  # Check if 'ap init' has been run
@@ -85,7 +102,15 @@ def prebuild():
85
102
  content_build_paths = [
86
103
  website_static_path / content_type for content_type in CONTENT_TYPES
87
104
  ]
88
- for path in [build_path, website_build_path, *content_build_paths]:
105
+ # Also wipe the API reference static dir so a `--skip-api` build doesn't
106
+ # leave stale pages from a prior run live on the deployed site.
107
+ api_static_path = website_static_path / "api_reference"
108
+ for path in [
109
+ build_path,
110
+ website_build_path,
111
+ api_static_path,
112
+ *content_build_paths,
113
+ ]:
89
114
  if path.exists():
90
115
  shutil.rmtree(path)
91
116
  build_path.mkdir(parents=True, exist_ok=True)
@@ -209,7 +234,11 @@ def postbuild(dev_build: bool = False):
209
234
  def build(ctx: click.Context, execute: bool):
210
235
  """Build the project website and all contents for production.
211
236
 
212
- This command builds MyST content (doc/blog/tutorial/example/guide) and the SvelteKit website.
237
+ This command builds MyST content (doc/blog/tutorial/example/guide), the API
238
+ reference (via pdoc), and the SvelteKit website.
239
+
240
+ The API reference is opt-in via `[website].api_reference = true` in
241
+ afterpython.toml — by default it is skipped.
213
242
 
214
243
  Any extra arguments are passed to the 'myst build --html' command for each content type.
215
244
  See "myst build --help" for more details.
@@ -240,12 +269,18 @@ def build(ctx: click.Context, execute: bool):
240
269
  paths = ctx.obj["paths"]
241
270
  prebuild()
242
271
 
243
- # Determine BASE_PATH based on website URL configuration
272
+ # Determine BASE_PATH based on website URL configuration. Computed
273
+ # before build_pdoc() so it can wire pdoc's logo-link back to the
274
+ # project website root.
244
275
  base_path = determine_base_path()
245
276
  if base_path:
246
277
  click.echo(f"Using BASE_PATH: {base_path}")
247
278
  else:
248
279
  click.echo("Using BASE_PATH: (empty - custom domain)")
280
+
281
+ if _read_api_reference():
282
+ build_pdoc(base_path=base_path)
283
+
249
284
  node_env: NodeEnv = find_node_env()
250
285
 
251
286
  # myst's production build
@@ -75,7 +75,7 @@ def bump(ctx, release: bool, pre: bool):
75
75
 
76
76
  # by default, bump dev-release version
77
77
  if version.is_devrelease and not pre:
78
- devrelease_number = int(version.dev)
78
+ devrelease_number = int(version.dev) if version.dev is not None else 0
79
79
  if "--devrelease" not in ctx.args:
80
80
  args = ["--devrelease", str(devrelease_number + 1), *ctx.args]
81
81
  # exclude e.g. 0.1.0.dev1 which is both dev-release and pre-release (with version.pre = None)
@@ -251,7 +251,10 @@ def website(ctx, no_backup: bool):
251
251
  ensure_website_gitignore_rules()
252
252
  except Exception as e:
253
253
  click.echo(f"✗ Error updating project website template: {e}", err=True)
254
- if not no_backup:
254
+ # On a fresh `ap init`, website_path didn't exist beforehand, so no backup
255
+ # was created — skip restore in that case rather than crashing with
256
+ # FileNotFoundError, which would mask the real error above.
257
+ if not no_backup and backup_path.exists():
255
258
  click.echo("Restoring from backup...")
256
259
  if website_path.exists():
257
260
  shutil.rmtree(website_path)
@@ -0,0 +1,7 @@
1
+ {% extends "default/frame.html.jinja2" %}
2
+ {# Override pdoc's default 35vh logo height — too dominant in the sidebar. #}
3
+ {% block head %}
4
+ <style>
5
+ nav.pdoc img.logo { max-height: 5rem; margin-bottom: 1.5rem; }
6
+ </style>
7
+ {% endblock %}
@@ -23,7 +23,7 @@ repos:
23
23
  stages:
24
24
  - pre-commit
25
25
  - repo: https://github.com/astral-sh/ruff-pre-commit
26
- rev: v0.14.8
26
+ rev: v0.15.12
27
27
  hooks:
28
28
  - id: ruff-check
29
29
  stages:
@@ -38,7 +38,7 @@ repos:
38
38
  - --config
39
39
  - ./afterpython/ruff.toml
40
40
  - repo: https://github.com/commitizen-tools/commitizen
41
- rev: v4.10.0
41
+ rev: v4.13.10
42
42
  hooks:
43
43
  - id: commitizen
44
44
  stages:
@@ -119,12 +119,13 @@ def init_afterpython():
119
119
  },
120
120
  "website": {
121
121
  "url": "",
122
- "favicon": "favicon.svg",
122
+ "favicon": "favicon.ico",
123
123
  "logo": "logo.svg",
124
124
  "logo_dark": "logo.svg",
125
125
  "thumbnail": "thumbnail.png",
126
126
  "announcement": "",
127
127
  "readme_py": "wasm",
128
+ "api_reference": False,
128
129
  },
129
130
  }
130
131
  update_afterpython(default_data)
@@ -182,7 +182,9 @@ def init_myst():
182
182
 
183
183
  # find any existing node.js version and use it, if no, install the Node.js version specified in NODEENV_VERSION
184
184
  node_env: NodeEnv = find_node_env()
185
- subprocess.run(["npm", "install", "-g", "pnpm"], env=node_env, check=True)
185
+ # Pin to pnpm major version — `npm install -g pnpm` (unpinned) caused a
186
+ # silent 9→10 jump that broke `ap init` via ERR_PNPM_IGNORED_BUILDS.
187
+ subprocess.run(["npm", "install", "-g", "pnpm@11"], env=node_env, check=True)
186
188
  for content_type in CONTENT_TYPES:
187
189
  path = ap.paths.afterpython_path / content_type
188
190
  print(f"Initializing MyST Markdown (mystmd) in {path.name}/ directory ...")