afterpython 0.3.5__py3-none-any.whl → 0.3.7__py3-none-any.whl
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/builders/index_md.py +59 -3
- afterpython/builders/metadata.py +21 -0
- afterpython/cli/commands/update.py +10 -2
- afterpython/const.py +1 -0
- afterpython/templates/ci-workflow-template.yml +1 -1
- afterpython/tools/myst.py +16 -6
- {afterpython-0.3.5.dist-info → afterpython-0.3.7.dist-info}/METADATA +1 -1
- {afterpython-0.3.5.dist-info → afterpython-0.3.7.dist-info}/RECORD +10 -10
- {afterpython-0.3.5.dist-info → afterpython-0.3.7.dist-info}/WHEEL +1 -1
- {afterpython-0.3.5.dist-info → afterpython-0.3.7.dist-info}/entry_points.txt +0 -0
afterpython/builders/index_md.py
CHANGED
|
@@ -1,7 +1,50 @@
|
|
|
1
1
|
import click
|
|
2
2
|
|
|
3
3
|
import afterpython as ap
|
|
4
|
-
from afterpython.const import CONTENT_TYPES
|
|
4
|
+
from afterpython.const import CONTENT_TYPES, PLACEHOLDER_INDEX_MARKER
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def _legacy_placeholder_content(content_type: str) -> str:
|
|
8
|
+
return f"""---
|
|
9
|
+
title: ← {content_type.capitalize()}
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
This is a placeholder index page. The actual {content_type} landing page is rendered by SvelteKit.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _legacy_welcome_content(content_type: str) -> str:
|
|
17
|
+
return f"""# Welcome to AfterPython
|
|
18
|
+
|
|
19
|
+
Welcome to your project's {content_type}! This is a starter page to help you get started.
|
|
20
|
+
|
|
21
|
+
## Getting Started
|
|
22
|
+
|
|
23
|
+
Replace this placeholder content with your own. Here's what you can do:
|
|
24
|
+
|
|
25
|
+
- Creating new `.md` or `.ipynb` files in the `afterpython/{content_type}/` directory
|
|
26
|
+
- Writing in MyST Markdown format
|
|
27
|
+
- Adding images to the `afterpython/static/` directory and referencing them
|
|
28
|
+
|
|
29
|
+
## Resources
|
|
30
|
+
|
|
31
|
+
- [AfterPython's Project Website](https://afterpython.afterpython.org)
|
|
32
|
+
- [MyST Markdown Guide](https://mystmd.org)
|
|
33
|
+
|
|
34
|
+
Start building your amazing project! 🚀
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _is_afterpython_placeholder_index(index_md, content_type: str) -> bool:
|
|
39
|
+
"""Return True only for non-doc index.md files generated by AfterPython."""
|
|
40
|
+
content = index_md.read_text(encoding="utf-8", errors="ignore")
|
|
41
|
+
normalized_content = content.strip()
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
PLACEHOLDER_INDEX_MARKER in content
|
|
45
|
+
or normalized_content == _legacy_placeholder_content(content_type).strip()
|
|
46
|
+
or normalized_content == _legacy_welcome_content(content_type).strip()
|
|
47
|
+
)
|
|
5
48
|
|
|
6
49
|
|
|
7
50
|
def create_placeholder_index_md_files():
|
|
@@ -71,10 +114,23 @@ def delete_placeholder_index_md_files():
|
|
|
71
114
|
myst_yml_path = content_path / "myst.yml"
|
|
72
115
|
index_md = content_path / "index.md"
|
|
73
116
|
|
|
74
|
-
# Delete index.md from source
|
|
117
|
+
# Delete index.md from source only when it is an AfterPython-generated placeholder.
|
|
75
118
|
if index_md.exists():
|
|
119
|
+
if not _is_afterpython_placeholder_index(index_md, content_type):
|
|
120
|
+
raise click.ClickException(
|
|
121
|
+
f"Found existing 'afterpython/{content_type}/index.md'.\n"
|
|
122
|
+
f"\n"
|
|
123
|
+
f"'afterpython/{content_type}/index.md' is reserved for internal use by AfterPython.\n"
|
|
124
|
+
f"The '/{content_type}' route is owned by the SvelteKit listing page,\n"
|
|
125
|
+
f"so user-authored non-doc index.md files are not supported.\n"
|
|
126
|
+
f"\n"
|
|
127
|
+
f"Please rename this file to something else "
|
|
128
|
+
f"(e.g., '{content_type}_intro.md') and update the reference in "
|
|
129
|
+
f"afterpython/{content_type}/myst.yml."
|
|
130
|
+
)
|
|
131
|
+
|
|
76
132
|
index_md.unlink()
|
|
77
|
-
click.echo(f"Deleted: {index_md}")
|
|
133
|
+
click.echo(f"Deleted placeholder: {index_md}")
|
|
78
134
|
|
|
79
135
|
# Delete index.html from build output
|
|
80
136
|
index_html = content_path / "_build" / "html" / "index.html"
|
afterpython/builders/metadata.py
CHANGED
|
@@ -57,6 +57,11 @@ def build_metadata():
|
|
|
57
57
|
website = _from_tomlkit(afterpython.get("website", {}))
|
|
58
58
|
metadata_json["announcement"] = str(website.get("announcement", "")).strip()
|
|
59
59
|
metadata_json["readme_py"] = _resolve_readme_py(website)
|
|
60
|
+
# Logos are served from the site root in _website/ (assets copied from
|
|
61
|
+
# afterpython/static/ to _website/static/), so we normalize to a leading-
|
|
62
|
+
# slash form that the Svelte side can hand straight to `asset()`.
|
|
63
|
+
metadata_json["logo"] = _resolve_logo_path(website.get("logo", ""))
|
|
64
|
+
metadata_json["logo_dark"] = _resolve_logo_path(website.get("logo_dark", ""))
|
|
60
65
|
|
|
61
66
|
with open(build_path / "metadata.json", "w") as f:
|
|
62
67
|
json.dump(metadata_json, f, indent=2)
|
|
@@ -64,6 +69,22 @@ def build_metadata():
|
|
|
64
69
|
convert_paths()
|
|
65
70
|
|
|
66
71
|
|
|
72
|
+
def _resolve_logo_path(raw: object) -> str:
|
|
73
|
+
"""Normalize a logo path from afterpython.toml for consumption by _website/.
|
|
74
|
+
|
|
75
|
+
normalize_static_path() returns either a bare filename ("logo.svg") or an
|
|
76
|
+
absolute path ("/some/dir/logo.svg"). The Svelte side passes this to
|
|
77
|
+
`asset()`, which expects a leading slash, so we prepend one when missing.
|
|
78
|
+
Returns "" when unset so the Svelte side can fall back to its default.
|
|
79
|
+
"""
|
|
80
|
+
from afterpython.utils import normalize_static_path
|
|
81
|
+
|
|
82
|
+
path = normalize_static_path(str(raw))
|
|
83
|
+
if not path:
|
|
84
|
+
return ""
|
|
85
|
+
return path if path.startswith("/") else f"/{path}"
|
|
86
|
+
|
|
87
|
+
|
|
67
88
|
def _resolve_readme_py(website_config: dict) -> str:
|
|
68
89
|
"""Resolve the readme_py field for metadata.json.
|
|
69
90
|
|
|
@@ -112,8 +112,6 @@ def dependencies(upgrade: bool, all_: bool, exclude: tuple[str, ...]):
|
|
|
112
112
|
"uv not found. Updated pyproject.toml only (packages not installed)."
|
|
113
113
|
)
|
|
114
114
|
if upgrade and all_:
|
|
115
|
-
subprocess.run(["ap", "pre-commit", "autoupdate"])
|
|
116
|
-
click.echo("All pre-commit hooks updated successfully.")
|
|
117
115
|
if has_pixi():
|
|
118
116
|
click.echo("Upgrading dependencies with pixi...")
|
|
119
117
|
pixi_exclude_args = ["--exclude", "python"]
|
|
@@ -137,6 +135,16 @@ def dependencies(upgrade: bool, all_: bool, exclude: tuple[str, ...]):
|
|
|
137
135
|
bold=True,
|
|
138
136
|
)
|
|
139
137
|
)
|
|
138
|
+
result = subprocess.run(["ap", "pre-commit", "autoupdate"], check=False)
|
|
139
|
+
if result.returncode == 0:
|
|
140
|
+
click.echo("All pre-commit hooks updated successfully.")
|
|
141
|
+
else:
|
|
142
|
+
click.echo(
|
|
143
|
+
click.style(
|
|
144
|
+
"Skipped pre-commit autoupdate (no config or command failed).",
|
|
145
|
+
fg="yellow",
|
|
146
|
+
)
|
|
147
|
+
)
|
|
140
148
|
|
|
141
149
|
|
|
142
150
|
update.add_command(dependencies, name="deps") # alias for "dependencies"
|
afterpython/const.py
CHANGED
afterpython/tools/myst.py
CHANGED
|
@@ -9,8 +9,11 @@ if TYPE_CHECKING:
|
|
|
9
9
|
|
|
10
10
|
import subprocess
|
|
11
11
|
|
|
12
|
+
import click
|
|
13
|
+
|
|
12
14
|
import afterpython as ap
|
|
13
15
|
from afterpython._io.yaml import read_yaml, write_yaml
|
|
16
|
+
from afterpython.const import PLACEHOLDER_INDEX_MARKER
|
|
14
17
|
from afterpython.utils import deep_merge
|
|
15
18
|
|
|
16
19
|
|
|
@@ -113,7 +116,7 @@ def _write_index_file(content_type: tContentType):
|
|
|
113
116
|
Note: This only creates the file. TOC modification is handled by the build process.
|
|
114
117
|
|
|
115
118
|
Raises:
|
|
116
|
-
|
|
119
|
+
click.ClickException: If a non-placeholder index.md already exists.
|
|
117
120
|
"""
|
|
118
121
|
if content_type == "doc":
|
|
119
122
|
return # Doc doesn't need a placeholder index.md
|
|
@@ -123,22 +126,29 @@ def _write_index_file(content_type: tContentType):
|
|
|
123
126
|
|
|
124
127
|
# Check if user created an index.md file
|
|
125
128
|
if index_file.exists():
|
|
126
|
-
|
|
129
|
+
existing_content = index_file.read_text(encoding="utf-8", errors="ignore")
|
|
130
|
+
if PLACEHOLDER_INDEX_MARKER in existing_content:
|
|
131
|
+
return index_file
|
|
132
|
+
|
|
133
|
+
raise click.ClickException(
|
|
127
134
|
f"\n"
|
|
128
|
-
f"Found existing '
|
|
135
|
+
f"Found existing 'afterpython/{content_type}/index.md'\n"
|
|
129
136
|
f"\n"
|
|
130
|
-
f"
|
|
137
|
+
f"'afterpython/{content_type}/index.md' is reserved for internal use by AfterPython.\n"
|
|
131
138
|
f"MyST treats the first file in TOC as index, which would conflict with\n"
|
|
132
|
-
f"SvelteKit
|
|
139
|
+
f"the SvelteKit listing page route '/{content_type}', which is owned by\n"
|
|
140
|
+
f"AfterPython's project website.\n"
|
|
133
141
|
f"\n"
|
|
134
142
|
f"Please rename your file to something else (e.g., '{content_type}_intro.md')\n"
|
|
135
|
-
f"and update the reference in afterpython/{content_type}/myst.yml"
|
|
143
|
+
f"and update the reference in afterpython/{content_type}/myst.yml."
|
|
136
144
|
)
|
|
137
145
|
|
|
138
146
|
index_content = f"""---
|
|
139
147
|
title: ← {content_type.capitalize()}
|
|
140
148
|
---
|
|
141
149
|
|
|
150
|
+
{PLACEHOLDER_INDEX_MARKER}
|
|
151
|
+
|
|
142
152
|
This is a placeholder index page. The actual {content_type} landing page is rendered by SvelteKit.
|
|
143
153
|
"""
|
|
144
154
|
index_file.write_text(index_content)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: afterpython
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.7
|
|
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
|
|
@@ -7,12 +7,12 @@ afterpython/builders/__init__.py,sha256=H7f9mFKXofWOAC3hkrxiFzvW5NziF8wYyduUBykH
|
|
|
7
7
|
afterpython/builders/build_pdoc.py,sha256=rasjCtTah5GsZYokqU--Fp3bvTEf464ievENfOoANOk,2040
|
|
8
8
|
afterpython/builders/content_json.py,sha256=-LTkeA8oA6XEudc2b1H7U0-UwcJlHn7xgICeweMYrG0,4805
|
|
9
9
|
afterpython/builders/faq_json.py,sha256=mMfFepRBL_1QYO0tQ6orf5ESo2LVntk55nfFzencViM,1193
|
|
10
|
-
afterpython/builders/index_md.py,sha256=
|
|
10
|
+
afterpython/builders/index_md.py,sha256=M4TNqrMl9_7HKiu11VOGiYvgffBQp3ZZbgLvlczZAVA,5998
|
|
11
11
|
afterpython/builders/jupyter_notebook.py,sha256=8yjgwWBaHfEzvN90j4biR6-RaTUHeIQ59h4NKethHOk,9693
|
|
12
12
|
afterpython/builders/llms_txt.py,sha256=9x-B1i1buTDJt4zGs8nugyto_pI5QIp7WUBcv-zpcso,9226
|
|
13
13
|
afterpython/builders/marimo_notebook.py,sha256=cIah_ly67tTj4j1y7yL19MRQ9NN6vESmS2JKMsEuaA0,5386
|
|
14
14
|
afterpython/builders/markdown.py,sha256=0ExfRqvOTWsgUkAVaGGNkiNDtNedRr7JR1yTGxpbsmA,8736
|
|
15
|
-
afterpython/builders/metadata.py,sha256=
|
|
15
|
+
afterpython/builders/metadata.py,sha256=_GNXcrVM5mFvRGrPt6Liqy-D2jBzfIZz4nI1kOD2uJ4,3752
|
|
16
16
|
afterpython/builders/url_md.py,sha256=uuW3YCyphd-Qvl9Yopv48utu6y1tyfJHNc25sS-O6Yw,3526
|
|
17
17
|
afterpython/cli/__init__.py,sha256=G4AB-rllhmr7tURFc5cXJfkjZZ2bXtMBg3oy4zUGEFw,84
|
|
18
18
|
afterpython/cli/commands/add.py,sha256=Ppp4msdvOwN9_-fdG5-b0-IV9p0Eef9CiIEU3srUjYk,1792
|
|
@@ -35,13 +35,13 @@ afterpython/cli/commands/remove.py,sha256=Fl79JSI9IdHyzYflocXxcxgBkBPkNFAW98Yuij
|
|
|
35
35
|
afterpython/cli/commands/serve.py,sha256=L0LIhMGByQA_mNTOAGHQTQ8TcBfi5sgmO1_iGI24QgI,822
|
|
36
36
|
afterpython/cli/commands/start.py,sha256=q4rUkIllOO8wJQ9ABtsx-dqkW1yC0vltAtSkiHN_GH4,4002
|
|
37
37
|
afterpython/cli/commands/sync.py,sha256=Av67jsCBxhh1skixihPgNyvZMUsh_j0pQGmG4EoR_A8,6318
|
|
38
|
-
afterpython/cli/commands/update.py,sha256=
|
|
38
|
+
afterpython/cli/commands/update.py,sha256=s84yzIBsG1lQQ61gWkLLP-KzxZ3GIfwosb0Ge2mR7AI,9685
|
|
39
39
|
afterpython/cli/main.py,sha256=-9eQiIrUViSvof-Ic2RHF3AVZharPSQh9sJ7tkhvf6Q,5042
|
|
40
|
-
afterpython/const.py,sha256=
|
|
40
|
+
afterpython/const.py,sha256=pZERFcKA60HsTob9kFCh34M_bZhyphHgLKUHab9pNFg,225
|
|
41
41
|
afterpython/main.py,sha256=w0z6mTib3u4p2HxMrk-tIJlZtur7uRaqsbE0ewlYlSs,490
|
|
42
42
|
afterpython/pcu.py,sha256=EoEhSzFZ49b5qc9KH2RLxIHSzY8YFM5uhtw07chcrr8,6093
|
|
43
43
|
afterpython/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
44
|
-
afterpython/templates/ci-workflow-template.yml,sha256
|
|
44
|
+
afterpython/templates/ci-workflow-template.yml,sha256=-7BVbNArhaUNtJzxdfIX9scCQcba7LoWHPJXLBm-OxM,7115
|
|
45
45
|
afterpython/templates/cz-template.toml,sha256=2qwbQLb0nbZaA63oWXFFzvzPNBsFZHATL1C2rdNdjjs,185
|
|
46
46
|
afterpython/templates/dependabot-template.yml,sha256=CBQEgh8EsXw2X7IqzGtFI7lVT9liF6PW4DvGLB0X2LY,1136
|
|
47
47
|
afterpython/templates/deploy-workflow-template.yml,sha256=o9blTGoM_KLB3wZUQcfdjxSOz08ldNJDfv1hA7FEbp8,2397
|
|
@@ -54,12 +54,12 @@ afterpython/tools/_git.py,sha256=aO-qDEQ4OevD_B74DYKK4nQKYeiaS1BXmYc8paJRfbQ,377
|
|
|
54
54
|
afterpython/tools/branch_rules.py,sha256=ciQ2H2YBnoCZu_plyVeIHzf2FcAILRFhpjzOR2_IfJg,3159
|
|
55
55
|
afterpython/tools/commitizen.py,sha256=ZO1qHmzUU0myd85tncv76WtIR7DB_AoQGSUvaf78Ohg,438
|
|
56
56
|
afterpython/tools/github_actions.py,sha256=0xzOc41QF1PKagD1CW7BAt_Rugy0KCEx_KfcrPKVl3c,3168
|
|
57
|
-
afterpython/tools/myst.py,sha256=
|
|
57
|
+
afterpython/tools/myst.py,sha256=03m1bBKHxcDgruwrNjf7zAu5eH6TVDvsXSd936eIGF4,8586
|
|
58
58
|
afterpython/tools/pre_commit.py,sha256=oNsrUkPI13rSSBSyhyTTKPnQGhDxLIPYhxu6kL0fDmo,1206
|
|
59
59
|
afterpython/tools/pyproject.py,sha256=hz-DOf-pkGBF2m_RqEZipAaO-NDbsLxrrc65LWAIwLA,3698
|
|
60
60
|
afterpython/utils.py,sha256=fVa3jIzCvhn7QA7N0M6d_pvojpPFrN-hae8trUYhPKU,11701
|
|
61
61
|
afterpython/version.py,sha256=hihRV1S-gc1m46OaXD32ikkEkqzs-Gtq7AcAqOQV-wY,1603
|
|
62
|
-
afterpython-0.3.
|
|
63
|
-
afterpython-0.3.
|
|
64
|
-
afterpython-0.3.
|
|
65
|
-
afterpython-0.3.
|
|
62
|
+
afterpython-0.3.7.dist-info/WHEEL,sha256=f5fWSvWsg5Knq5GWa6t1nJIug0Tqo69GqAWD_9LbBKw,81
|
|
63
|
+
afterpython-0.3.7.dist-info/entry_points.txt,sha256=roa0PDgBueM1JPbRG0G2OSxzaN394OUL_oS9iEwVLBc,80
|
|
64
|
+
afterpython-0.3.7.dist-info/METADATA,sha256=838abK-PJzhIAb2gK1tamV9PysHdyrZM5MwdEqFKyrk,6180
|
|
65
|
+
afterpython-0.3.7.dist-info/RECORD,,
|
|
File without changes
|