afterpython 0.3.11__tar.gz → 0.3.13__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.3.11 → afterpython-0.3.13}/PKG-INFO +1 -1
- {afterpython-0.3.11 → afterpython-0.3.13}/pyproject.toml +1 -1
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/commands/init.py +69 -39
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/tools/myst.py +55 -28
- {afterpython-0.3.11 → afterpython-0.3.13}/README.md +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/__init__.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/_io/toml.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/_io/yaml.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/_paths.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/_typing.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/builders/__init__.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/builders/build_pdoc.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/builders/content_json.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/builders/faq_json.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/builders/index_md.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/builders/jupyter_notebook.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/builders/llms_txt.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/builders/marimo_notebook.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/builders/markdown.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/builders/metadata.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/builders/url_md.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/__init__.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/commands/add.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/commands/build.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/commands/bump.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/commands/check.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/commands/clean.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/commands/commit.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/commands/commitizen.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/commands/dev.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/commands/format.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/commands/init_branch_rules.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/commands/install.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/commands/lock.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/commands/pre_commit.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/commands/preview.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/commands/release.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/commands/remove.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/commands/serve.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/commands/start.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/commands/sync.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/commands/update.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/cli/main.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/const.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/main.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/pcu.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/py.typed +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/templates/ci-workflow-template.yml +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/templates/cz-template.toml +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/templates/dependabot-template.yml +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/templates/deploy-workflow-template.yml +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/templates/pdoc/frame.html.jinja2 +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/templates/pre-commit-config-template.yaml +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/templates/release-workflow-template.yml +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/templates/ruff-template.toml +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/tools/_afterpython.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/tools/_git.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/tools/branch_rules.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/tools/commitizen.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/tools/github_actions.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/tools/pre_commit.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/tools/pyproject.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/utils.py +0 -0
- {afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: afterpython
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.13
|
|
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
|
|
@@ -43,6 +43,16 @@ def init_py_typed():
|
|
|
43
43
|
click.echo(f"Created {py_typed_path}")
|
|
44
44
|
|
|
45
45
|
|
|
46
|
+
def _preflight_init(skip_website: bool) -> None:
|
|
47
|
+
"""Validate external prerequisites before any filesystem writes, so a
|
|
48
|
+
failure aborts cleanly instead of leaving a half-initialized project."""
|
|
49
|
+
if not skip_website:
|
|
50
|
+
from afterpython.tools.myst import ensure_pnpm_11
|
|
51
|
+
from afterpython.utils import find_node_env
|
|
52
|
+
|
|
53
|
+
ensure_pnpm_11(find_node_env())
|
|
54
|
+
|
|
55
|
+
|
|
46
56
|
@click.group(invoke_without_command=True)
|
|
47
57
|
@click.option(
|
|
48
58
|
"--yes",
|
|
@@ -70,48 +80,60 @@ def init(ctx, yes, skip_website: bool):
|
|
|
70
80
|
from afterpython.tools.pre_commit import init_pre_commit
|
|
71
81
|
from afterpython.tools.pyproject import init_pyproject
|
|
72
82
|
|
|
83
|
+
_preflight_init(skip_website)
|
|
84
|
+
|
|
73
85
|
paths = ctx.obj["paths"]
|
|
74
86
|
click.echo("Initializing afterpython...")
|
|
75
87
|
afterpython_path = paths.afterpython_path
|
|
76
88
|
static_path = paths.static_path
|
|
77
89
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
90
|
+
try:
|
|
91
|
+
afterpython_path.mkdir(parents=True, exist_ok=True)
|
|
92
|
+
static_path.mkdir(parents=True, exist_ok=True)
|
|
93
|
+
|
|
94
|
+
init_pyproject()
|
|
95
|
+
|
|
96
|
+
init_afterpython()
|
|
97
|
+
|
|
98
|
+
if not skip_website:
|
|
99
|
+
# check=True so a failure inside `ap init website` aborts the parent
|
|
100
|
+
# run instead of silently continuing to write more files.
|
|
101
|
+
subprocess.run(["ap", "init", "website"], check=True)
|
|
102
|
+
|
|
103
|
+
# TODO: add type checking related stuff here
|
|
104
|
+
init_py_typed()
|
|
105
|
+
|
|
106
|
+
create_workflow("ci")
|
|
107
|
+
|
|
108
|
+
if yes or click.confirm(
|
|
109
|
+
f"\nCreate .pre-commit-config.yaml in {afterpython_path}?", default=True
|
|
110
|
+
):
|
|
111
|
+
init_pre_commit()
|
|
112
|
+
|
|
113
|
+
if yes or click.confirm(
|
|
114
|
+
f"\nCreate ruff.toml in {afterpython_path}?", default=True
|
|
115
|
+
):
|
|
116
|
+
init_ruff_toml()
|
|
117
|
+
|
|
118
|
+
if yes or click.confirm(
|
|
119
|
+
f"\nCreate commitizen configuration (cz.toml) in {afterpython_path} "
|
|
120
|
+
f"and release workflow in .github/workflows/release.yml?",
|
|
121
|
+
default=True,
|
|
122
|
+
):
|
|
123
|
+
init_commitizen()
|
|
124
|
+
create_workflow("release")
|
|
125
|
+
|
|
126
|
+
if yes or click.confirm(
|
|
127
|
+
"\nCreate Dependabot configuration (.github/dependabot.yml) "
|
|
128
|
+
"to auto-update GitHub Actions versions?",
|
|
129
|
+
default=True,
|
|
130
|
+
):
|
|
131
|
+
create_dependabot()
|
|
132
|
+
except BaseException:
|
|
133
|
+
if afterpython_path.exists():
|
|
134
|
+
click.echo(f"ap init failed — removing {afterpython_path}", err=True)
|
|
135
|
+
shutil.rmtree(afterpython_path, ignore_errors=True)
|
|
136
|
+
raise
|
|
115
137
|
|
|
116
138
|
|
|
117
139
|
@init.command("website")
|
|
@@ -122,10 +144,18 @@ def init_website_subcommand():
|
|
|
122
144
|
the website to an existing AfterPython project.
|
|
123
145
|
"""
|
|
124
146
|
from afterpython.tools.github_actions import create_workflow
|
|
125
|
-
from afterpython.tools.myst import init_myst
|
|
147
|
+
from afterpython.tools.myst import ensure_pnpm_11, init_myst
|
|
148
|
+
from afterpython.utils import find_node_env
|
|
149
|
+
|
|
150
|
+
# Pre-flight: same rationale as `ap init` — guard the standalone entry too,
|
|
151
|
+
# since this subcommand can be invoked directly via `ap init website`.
|
|
152
|
+
ensure_pnpm_11(find_node_env())
|
|
126
153
|
|
|
127
154
|
init_faq()
|
|
128
155
|
init_myst()
|
|
129
156
|
click.echo(f"Initializing project website template in {ap.paths.website_path}...")
|
|
130
|
-
|
|
157
|
+
# check=True so a network/pnpm failure inside `ap update website` aborts
|
|
158
|
+
# the subcommand instead of silently dropping the deploy workflow on top
|
|
159
|
+
# of a broken website install.
|
|
160
|
+
subprocess.run(["ap", "update", "website"], check=True)
|
|
131
161
|
create_workflow("deploy")
|
|
@@ -152,31 +152,54 @@ def _write_index_file(content_type: tContentType):
|
|
|
152
152
|
return index_file
|
|
153
153
|
|
|
154
154
|
|
|
155
|
-
def
|
|
156
|
-
|
|
157
|
-
|
|
155
|
+
def ensure_pnpm_11(node_env: NodeEnv) -> None:
|
|
156
|
+
"""Ensure pnpm 11.x is available on `node_env`'s PATH. No-op if already satisfied.
|
|
157
|
+
|
|
158
|
+
Pinned to major 11 because an unpinned `npm install -g pnpm` previously did
|
|
159
|
+
a silent 9→10 jump that broke `ap init` via ERR_PNPM_IGNORED_BUILDS. We
|
|
160
|
+
pre-check the installed version so we don't redundantly invoke `npm install
|
|
161
|
+
-g`, which fails with EEXIST when pnpm was installed by a different package
|
|
162
|
+
manager (e.g. Homebrew) that owns the shim filenames npm wants to write.
|
|
163
|
+
"""
|
|
164
|
+
current: str | None = None
|
|
165
|
+
try:
|
|
166
|
+
result = subprocess.run(
|
|
167
|
+
["pnpm", "--version"],
|
|
168
|
+
env=node_env,
|
|
169
|
+
capture_output=True,
|
|
170
|
+
text=True,
|
|
171
|
+
check=False,
|
|
172
|
+
)
|
|
173
|
+
if result.returncode == 0:
|
|
174
|
+
current = result.stdout.strip()
|
|
175
|
+
if current.startswith("11."):
|
|
176
|
+
return
|
|
177
|
+
except FileNotFoundError:
|
|
178
|
+
pass
|
|
179
|
+
|
|
180
|
+
install = subprocess.run(
|
|
181
|
+
["npm", "install", "-g", "pnpm@11"],
|
|
182
|
+
env=node_env,
|
|
183
|
+
capture_output=True,
|
|
184
|
+
text=True,
|
|
185
|
+
check=False,
|
|
186
|
+
)
|
|
187
|
+
if install.returncode == 0:
|
|
158
188
|
return
|
|
159
|
-
welcome_content = f"""# Welcome to AfterPython
|
|
160
|
-
|
|
161
|
-
Welcome to your project's {content_type}! This is a starter page to help you get started.
|
|
162
|
-
|
|
163
|
-
## Getting Started
|
|
164
|
-
|
|
165
|
-
Replace this placeholder content with your own. Here's what you can do:
|
|
166
189
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
190
|
+
msg = ["Failed to install pnpm@11 via npm."]
|
|
191
|
+
if current:
|
|
192
|
+
msg.append(f"Detected existing pnpm version: {current}")
|
|
193
|
+
msg.append(
|
|
194
|
+
"If pnpm is already installed via another package manager "
|
|
195
|
+
"(e.g. Homebrew: `brew install pnpm`), npm refuses to overwrite "
|
|
196
|
+
"its shims. Please either:\n"
|
|
197
|
+
" - upgrade your existing pnpm to major version 11, or\n"
|
|
198
|
+
" - uninstall it and let afterpython manage pnpm via npm."
|
|
199
|
+
)
|
|
200
|
+
if install.stderr:
|
|
201
|
+
msg.append(f"\nnpm stderr:\n{install.stderr}")
|
|
202
|
+
raise RuntimeError("\n".join(msg))
|
|
180
203
|
|
|
181
204
|
|
|
182
205
|
def init_myst():
|
|
@@ -189,14 +212,19 @@ def init_myst():
|
|
|
189
212
|
|
|
190
213
|
# find any existing node.js version and use it, if no, install the Node.js version specified in NODEENV_VERSION
|
|
191
214
|
node_env: NodeEnv = find_node_env()
|
|
192
|
-
|
|
193
|
-
# silent 9→10 jump that broke `ap init` via ERR_PNPM_IGNORED_BUILDS.
|
|
194
|
-
subprocess.run(["npm", "install", "-g", "pnpm@11"], env=node_env, check=True)
|
|
215
|
+
ensure_pnpm_11(node_env)
|
|
195
216
|
for content_type in CONTENT_TYPES:
|
|
196
217
|
path = ap.paths.afterpython_path / content_type
|
|
197
218
|
print(f"Initializing MyST Markdown (mystmd) in {path.name}/ directory ...")
|
|
198
219
|
path.mkdir(parents=True, exist_ok=True)
|
|
199
|
-
subprocess.run(
|
|
220
|
+
subprocess.run(
|
|
221
|
+
["myst", "init"],
|
|
222
|
+
cwd=path,
|
|
223
|
+
input="n\n",
|
|
224
|
+
text=True,
|
|
225
|
+
env=node_env,
|
|
226
|
+
check=True,
|
|
227
|
+
)
|
|
200
228
|
myst_yml_defaults = {
|
|
201
229
|
"extends": "../authors.yml",
|
|
202
230
|
"project": {
|
|
@@ -213,5 +241,4 @@ def init_myst():
|
|
|
213
241
|
},
|
|
214
242
|
}
|
|
215
243
|
update_myst_yml(myst_yml_defaults, path, add_comments=True)
|
|
216
|
-
_write_welcome_file(content_type)
|
|
217
244
|
subprocess.run(["ap", "sync"])
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/templates/ci-workflow-template.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/templates/deploy-workflow-template.yml
RENAMED
|
File without changes
|
|
File without changes
|
{afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/templates/pre-commit-config-template.yaml
RENAMED
|
File without changes
|
{afterpython-0.3.11 → afterpython-0.3.13}/src/afterpython/templates/release-workflow-template.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|