afterpython 0.1.0__py3-none-any.whl → 0.1.0.dev6__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.
Files changed (55) hide show
  1. afterpython/{templates/pre-commit-config-template.yaml → .pre-commit-config.yaml} +1 -1
  2. afterpython/_io/toml.py +3 -5
  3. afterpython/_paths.py +1 -1
  4. afterpython/_typing.py +2 -1
  5. afterpython/builders/__init__.py +3 -12
  6. afterpython/builders/metadata.py +3 -7
  7. afterpython/builders/molab.py +99 -0
  8. afterpython/cli/__init__.py +1 -0
  9. afterpython/cli/commands/build.py +68 -97
  10. afterpython/cli/commands/bump.py +0 -30
  11. afterpython/cli/commands/check.py +1 -1
  12. afterpython/cli/commands/clean.py +3 -4
  13. afterpython/cli/commands/commit.py +3 -21
  14. afterpython/cli/commands/commitizen.py +1 -1
  15. afterpython/cli/commands/dev.py +9 -13
  16. afterpython/cli/commands/format.py +1 -1
  17. afterpython/cli/commands/init.py +39 -48
  18. afterpython/cli/commands/install.py +2 -8
  19. afterpython/cli/commands/pre_commit.py +1 -1
  20. afterpython/cli/commands/preview.py +1 -1
  21. afterpython/cli/commands/start.py +4 -7
  22. afterpython/cli/commands/sync.py +21 -53
  23. afterpython/cli/commands/update.py +8 -31
  24. afterpython/cli/main.py +14 -75
  25. afterpython/const.py +1 -0
  26. afterpython/cz.toml +27 -0
  27. afterpython/pcu.py +1 -3
  28. afterpython/templates/deploy-workflow-template.yml +5 -5
  29. afterpython/templates/release-workflow-template.yml +3 -3
  30. afterpython/templates/ruff-template.toml +1 -1
  31. afterpython/tools/_afterpython.py +10 -73
  32. afterpython/tools/_git.py +2 -28
  33. afterpython/tools/commitizen.py +45 -5
  34. afterpython/tools/github_actions.py +53 -23
  35. afterpython/tools/myst.py +5 -46
  36. afterpython/tools/pre_commit.py +31 -6
  37. afterpython/tools/pyproject.py +2 -40
  38. afterpython/utils.py +0 -82
  39. {afterpython-0.1.0.dist-info → afterpython-0.1.0.dev6.dist-info}/METADATA +10 -34
  40. afterpython-0.1.0.dev6.dist-info/RECORD +47 -0
  41. {afterpython-0.1.0.dist-info → afterpython-0.1.0.dev6.dist-info}/WHEEL +1 -1
  42. afterpython/builders/content_json.py +0 -131
  43. afterpython/builders/index_md.py +0 -94
  44. afterpython/builders/jupyter_notebook.py +0 -293
  45. afterpython/builders/markdown.py +0 -271
  46. afterpython/cli/commands/add.py +0 -67
  47. afterpython/cli/commands/init_branch_rules.py +0 -9
  48. afterpython/cli/commands/lock.py +0 -23
  49. afterpython/cli/commands/remove.py +0 -67
  50. afterpython/templates/ci-workflow-template.yml +0 -197
  51. afterpython/templates/cz-template.toml +0 -7
  52. afterpython/templates/dependabot-template.yml +0 -30
  53. afterpython/tools/branch_rules.py +0 -106
  54. afterpython-0.1.0.dist-info/RECORD +0 -57
  55. {afterpython-0.1.0.dist-info → afterpython-0.1.0.dev6.dist-info}/entry_points.txt +0 -0
@@ -7,13 +7,38 @@ import afterpython as ap
7
7
 
8
8
 
9
9
  def init_ruff_toml():
10
- ruff_toml_path = ap.paths.afterpython_path / "ruff.toml"
10
+ from afterpython.tools.pre_commit import update_pre_commit
11
+
12
+ afterpython_path = ap.paths.afterpython_path
13
+ ruff_toml_path = afterpython_path / "ruff.toml"
11
14
  if ruff_toml_path.exists():
12
15
  click.echo(f"Ruff configuration file {ruff_toml_path} already exists")
13
16
  return
14
17
  ruff_template_path = ap.paths.templates_path / "ruff-template.toml"
15
18
  shutil.copy(ruff_template_path, ruff_toml_path)
16
19
  click.echo(f"Created {ruff_toml_path}")
20
+ # add ruff-pre-commit hook to .pre-commit-config.yaml
21
+ data_update = {
22
+ "repos": [
23
+ {
24
+ "repo": "https://github.com/astral-sh/ruff-pre-commit",
25
+ "rev": "v0.14.5",
26
+ "hooks": [
27
+ {
28
+ "id": "ruff-check",
29
+ "stages": ["pre-commit"],
30
+ "args": ["--config", "./afterpython/ruff.toml"],
31
+ },
32
+ {
33
+ "id": "ruff-format",
34
+ "stages": ["pre-commit"],
35
+ "args": ["--config", "./afterpython/ruff.toml"],
36
+ },
37
+ ],
38
+ },
39
+ ]
40
+ }
41
+ update_pre_commit(data_update)
17
42
 
18
43
 
19
44
  def init_website():
@@ -21,43 +46,19 @@ def init_website():
21
46
  subprocess.run(["ap", "update", "website"])
22
47
 
23
48
 
24
- def init_py_typed():
25
- from afterpython.tools.pyproject import find_package_directory
26
-
27
- try:
28
- package_dir = find_package_directory()
29
- except FileNotFoundError:
30
- click.echo(
31
- "Could not find package directory (__init__.py not found), skipping py-typed initialization"
32
- )
33
- return
34
- py_typed_path = package_dir / "py.typed"
35
- if py_typed_path.exists():
36
- click.echo(f"py.typed file already exists at {py_typed_path}")
37
- return
38
- py_typed_path.touch()
39
- click.echo(f"Created {py_typed_path}")
40
-
41
-
42
49
  @click.command()
43
- @click.option(
44
- "--yes",
45
- "-y",
46
- is_flag=True,
47
- help="Automatically answer yes to all prompts",
48
- )
49
50
  @click.pass_context
50
- def init(ctx, yes):
51
- """Initialize AfterPython project structure and website template"""
51
+ def init(ctx):
52
+ """Initialize afterpython with MyST Markdown (by default) and project website template"""
53
+ from afterpython.tools.pyproject import init_pyproject
52
54
  from afterpython.tools._afterpython import init_afterpython
55
+ from afterpython.tools.myst import init_myst
56
+ from afterpython.tools.pre_commit import init_pre_commit
53
57
  from afterpython.tools.commitizen import init_commitizen
54
58
  from afterpython.tools.github_actions import (
55
- create_dependabot,
56
- create_workflow,
59
+ init_release_workflow,
60
+ init_deploy_workflow,
57
61
  )
58
- from afterpython.tools.myst import init_myst
59
- from afterpython.tools.pre_commit import init_pre_commit
60
- from afterpython.tools.pyproject import init_pyproject
61
62
 
62
63
  paths = ctx.obj["paths"]
63
64
  click.echo("Initializing afterpython...")
@@ -66,6 +67,7 @@ def init(ctx, yes):
66
67
 
67
68
  afterpython_path.mkdir(parents=True, exist_ok=True)
68
69
  static_path.mkdir(parents=True, exist_ok=True)
70
+ afterpython_path.joinpath("afterpython.toml").touch()
69
71
 
70
72
  init_pyproject()
71
73
 
@@ -77,31 +79,20 @@ def init(ctx, yes):
77
79
 
78
80
  init_website()
79
81
 
80
- # TODO: add type checking related stuff here
81
- init_py_typed()
82
-
83
- create_workflow("deploy")
84
- create_workflow("ci")
85
-
86
- if yes or click.confirm(
82
+ if click.confirm(
87
83
  f"\nCreate .pre-commit-config.yaml in {afterpython_path}?", default=True
88
84
  ):
89
85
  init_pre_commit()
90
86
 
91
- if yes or click.confirm(f"\nCreate ruff.toml in {afterpython_path}?", default=True):
87
+ if click.confirm(f"\nCreate ruff.toml in {afterpython_path}?", default=True):
92
88
  init_ruff_toml()
93
89
 
94
- if yes or click.confirm(
90
+ if click.confirm(
95
91
  f"\nCreate commitizen configuration (cz.toml) in {afterpython_path} "
96
92
  f"and release workflow in .github/workflows/release.yml?",
97
93
  default=True,
98
94
  ):
99
95
  init_commitizen()
100
- create_workflow("release")
96
+ init_release_workflow()
101
97
 
102
- if yes or click.confirm(
103
- "\nCreate Dependabot configuration (.github/dependabot.yml) "
104
- "to auto-update GitHub Actions versions?",
105
- default=True,
106
- ):
107
- create_dependabot()
98
+ init_deploy_workflow()
@@ -3,7 +3,7 @@ import subprocess
3
3
  import click
4
4
  from click.exceptions import Exit
5
5
 
6
- from afterpython.utils import has_pixi, has_uv
6
+ from afterpython.utils import has_uv
7
7
 
8
8
 
9
9
  @click.command(
@@ -13,16 +13,10 @@ from afterpython.utils import has_pixi, has_uv
13
13
  )
14
14
  )
15
15
  def install():
16
- """Install all project dependencies (manages both uv and pixi if present)"""
16
+ """Run 'uv sync --all-extras --all-groups' to install all dependencies"""
17
17
  if not has_uv():
18
18
  click.echo("uv not found. Please install uv first.")
19
19
  return
20
-
21
20
  result = subprocess.run(["uv", "sync", "--all-extras", "--all-groups"], check=False)
22
21
  if result.returncode != 0:
23
22
  raise Exit(result.returncode)
24
-
25
- if has_pixi():
26
- result = subprocess.run(["pixi", "install"], check=False)
27
- if result.returncode != 0:
28
- raise Exit(result.returncode)
@@ -27,7 +27,7 @@ def _command_supports_config(command: str) -> bool:
27
27
  )
28
28
  @click.pass_context
29
29
  def pre_commit(ctx):
30
- """Run pre-commit hooks (uses afterpython/.pre-commit-config.yaml if available)"""
30
+ """Run pre-commit, always use the afterpython/.pre-commit-config.yaml if it exists"""
31
31
  from afterpython.utils import handle_passthrough_help
32
32
 
33
33
  # Show both our options and pre-commit's help and exit
@@ -7,7 +7,7 @@ from click.exceptions import Exit
7
7
  @click.command()
8
8
  @click.pass_context
9
9
  def preview(ctx):
10
- """Preview the production build of the project website"""
10
+ """Preview the production build of the project website (including myst's builds)"""
11
11
  from afterpython.utils import find_node_env
12
12
 
13
13
  paths = ctx.obj["paths"]
@@ -1,5 +1,4 @@
1
1
  from __future__ import annotations
2
-
3
2
  from typing import TYPE_CHECKING
4
3
 
5
4
  if TYPE_CHECKING:
@@ -10,6 +9,7 @@ import subprocess
10
9
  import click
11
10
  from click.exceptions import Exit
12
11
 
12
+
13
13
  command_kwargs = {
14
14
  "add_help_option": False, # disable click's --help option so that myst start --help can work
15
15
  "context_settings": dict(
@@ -42,13 +42,10 @@ command_kwargs = {
42
42
  "--guide", is_flag=True, help="Start the development server for guide/ directory"
43
43
  )
44
44
  def start(ctx, doc: bool, blog: bool, tutorial: bool, example: bool, guide: bool):
45
- """Start MyST development server for a specific content type"""
45
+ """Simple wrapper for `myst start` for convenience"""
46
+ from afterpython.utils import find_node_env, has_content_for_myst
46
47
  from afterpython.const import CONTENT_TYPES
47
- from afterpython.utils import (
48
- find_node_env,
49
- handle_passthrough_help,
50
- has_content_for_myst,
51
- )
48
+ from afterpython.utils import handle_passthrough_help
52
49
 
53
50
  # Show both our options and myst's help and exit
54
51
  handle_passthrough_help(
@@ -5,13 +5,13 @@ from pyproject_metadata import StandardMetadata
5
5
  from tomlkit.toml_document import TOMLDocument
6
6
 
7
7
  import afterpython as ap
8
- from afterpython.utils import convert_author_name_to_id, normalize_static_path
8
+ from afterpython.utils import convert_author_name_to_id
9
9
 
10
10
 
11
11
  def _sync_authors_yml(authors: list[tuple[str, str | None]]):
12
12
  """Sync authors.yml with authors in pyproject.toml"""
13
- from afterpython._io.yaml import read_yaml
14
13
  from afterpython.tools.myst import update_authors_yml
14
+ from afterpython._io.yaml import read_yaml
15
15
 
16
16
  # read myst.yml from docs path to get "version"
17
17
  doc_myst_yml = read_yaml(ap.paths.afterpython_path / "doc" / "myst.yml")
@@ -36,56 +36,34 @@ def _sync_authors_yml(authors: list[tuple[str, str | None]]):
36
36
 
37
37
  @click.command()
38
38
  def sync():
39
- """Sync configuration between pyproject.toml/afterpython.toml and authors.yml/myst.yml"""
40
- from afterpython._io.toml import _from_tomlkit
39
+ """Sync between pyproject.toml+afterpython.toml and authors.yml+myst.yml files"""
41
40
  from afterpython.const import CONTENT_TYPES
42
41
  from afterpython.tools._afterpython import read_afterpython
43
- from afterpython.tools.myst import update_myst_yml
44
42
  from afterpython.tools.pyproject import (
45
43
  read_metadata,
46
44
  read_pyproject,
47
45
  write_pyproject,
48
46
  )
47
+ from afterpython._io.toml import _from_tomlkit
48
+ from afterpython.tools.myst import update_myst_yml
49
49
 
50
50
  pyproject: StandardMetadata = read_metadata()
51
51
  project_name = str(pyproject.name)
52
52
  afterpython = read_afterpython()
53
53
  github_url = str(pyproject.urls.get("repository", ""))
54
- company_name = str(_from_tomlkit(afterpython.get("company", {})).get("name", ""))
55
- company_url = str(_from_tomlkit(afterpython.get("company", {})).get("url", ""))
56
- website_url = str(_from_tomlkit(afterpython.get("website", {})).get("url", ""))
57
- try:
58
- website_favicon = normalize_static_path(
59
- str(_from_tomlkit(afterpython.get("website", {})).get("favicon", ""))
60
- )
61
- website_logo = normalize_static_path(
62
- str(_from_tomlkit(afterpython.get("website", {})).get("logo", ""))
63
- )
64
- website_logo_dark = normalize_static_path(
65
- str(_from_tomlkit(afterpython.get("website", {})).get("logo_dark", ""))
66
- )
67
- website_thumbnail = normalize_static_path(
68
- str(_from_tomlkit(afterpython.get("website", {})).get("thumbnail", ""))
69
- )
70
- except ValueError as e:
71
- click.echo(f"Error in reading afterpython.toml: {e}")
72
- return
73
-
54
+ company_name = str(_from_tomlkit(afterpython["company"]).get("name", ""))
55
+ company_url = str(_from_tomlkit(afterpython["company"]).get("url", ""))
56
+ website_url = str(_from_tomlkit(afterpython["website"]).get("url", ""))
74
57
  authors = pyproject.authors
75
- if company_name and company_url:
76
- nav_bar = [{"title": company_name, "url": company_url}]
77
- else:
78
- nav_bar = []
79
- if website_url:
80
- nav_bar.extend(
81
- [
82
- {
83
- "title": content_type.capitalize() + "s",
84
- "url": f"{website_url}/{content_type}",
85
- }
86
- for content_type in CONTENT_TYPES
87
- ]
88
- )
58
+ nav_bar = [
59
+ {
60
+ "title": content_type.capitalize() + "s",
61
+ "url": f"{website_url}/{content_type}",
62
+ }
63
+ if website_url
64
+ else ""
65
+ for content_type in CONTENT_TYPES
66
+ ]
89
67
 
90
68
  _sync_authors_yml(authors)
91
69
 
@@ -100,9 +78,9 @@ def sync():
100
78
  # based on the current values in pyproject.toml and afterpython.toml
101
79
  for content_type in CONTENT_TYPES:
102
80
  path = ap.paths.afterpython_path / content_type
103
- # nav_bar_per_content_type = [
104
- # item for item in nav_bar if item["title"] != content_type.capitalize() + "s"
105
- # ]
81
+ nav_bar_per_content_type = [
82
+ item for item in nav_bar if item["title"] != content_type.capitalize() + "s"
83
+ ]
106
84
  title = project_name + f"'s {content_type.capitalize()}"
107
85
  data = {
108
86
  "project": {
@@ -120,24 +98,14 @@ def sync():
120
98
  "description": str(pyproject.description),
121
99
  "keywords": list(map(str, pyproject.keywords)),
122
100
  "github": github_url,
123
- "thumbnail": "../static" + website_thumbnail
124
- if website_thumbnail
125
- else "",
126
101
  },
127
102
  "site": {
128
103
  "title": title,
129
104
  "options": {
130
- "favicon": "../static" + website_favicon if website_favicon else "",
131
- "logo": "../static" + website_logo if website_logo else "",
132
- "logo_dark": "../static" + website_logo_dark
133
- if website_logo_dark
134
- else "",
135
105
  "logo_text": project_name,
136
106
  "logo_url": website_url,
137
107
  },
138
- # FIXME: disable nav bar for now until myst fixes the issue with the nav bar
139
- # the current issue is they prepend the BASE_URL to the nav bar links even they are external
140
- # "nav": nav_bar_per_content_type,
108
+ "nav": nav_bar_per_content_type,
141
109
  "actions": [
142
110
  {
143
111
  "title": "⭐ Star",
@@ -1,13 +1,12 @@
1
1
  from __future__ import annotations
2
-
3
2
  from typing import TYPE_CHECKING
4
3
 
5
4
  if TYPE_CHECKING:
6
5
  from afterpython._typing import NodeEnv
7
6
  from afterpython.pcu import Dependencies
8
7
 
9
- import shutil
10
8
  import subprocess
9
+ import shutil
11
10
 
12
11
  import click
13
12
  from click.exceptions import Exit
@@ -24,17 +23,17 @@ def update():
24
23
  "-u",
25
24
  "--upgrade",
26
25
  is_flag=True,
27
- help="Upgrade dependencies to their latest versions",
26
+ help="if enabled, the dependencies will be upgraded to the latest version",
28
27
  )
29
28
  @click.option(
30
29
  "--all",
31
30
  is_flag=True,
32
- help="Also update pre-commit hooks and pixi dependencies",
31
+ help="update all versions in dependencies and tool configurations (e.g. pre-commit-config.yaml)",
33
32
  )
34
33
  def dependencies(upgrade: bool, all: bool):
35
- """Check and update project dependencies to latest versions"""
34
+ """Update pyproject.toml dependencies to the latest version"""
36
35
  from afterpython.pcu import get_dependencies, update_dependencies
37
- from afterpython.utils import has_pixi, has_uv
36
+ from afterpython.utils import has_uv
38
37
 
39
38
  dependencies: Dependencies = get_dependencies()
40
39
  has_at_least_one_update = False
@@ -80,9 +79,7 @@ def dependencies(upgrade: bool, all: bool):
80
79
  raise Exit(result.returncode)
81
80
  click.echo(
82
81
  click.style(
83
- "✓ All dependencies in pyproject.toml upgraded successfully 🎉",
84
- fg="green",
85
- bold=True,
82
+ "✓ All dependencies upgraded successfully 🎉", fg="green", bold=True
86
83
  )
87
84
  )
88
85
  else:
@@ -92,26 +89,6 @@ def dependencies(upgrade: bool, all: bool):
92
89
  if all:
93
90
  subprocess.run(["ap", "pre-commit", "autoupdate"])
94
91
  click.echo("All pre-commit hooks updated successfully.")
95
- if has_pixi():
96
- click.echo("Upgrading dependencies with pixi...")
97
- result = subprocess.run(
98
- ["pixi", "upgrade", "--exclude", "python"], check=False
99
- )
100
- if result.returncode != 0:
101
- raise Exit(result.returncode)
102
- result = subprocess.run(["pixi", "lock"], check=False)
103
- if result.returncode != 0:
104
- raise Exit(result.returncode)
105
- result = subprocess.run(["pixi", "install"], check=False)
106
- if result.returncode != 0:
107
- raise Exit(result.returncode)
108
- click.echo(
109
- click.style(
110
- "✓ All dependencies in pixi.toml upgraded successfully 🎉",
111
- fg="green",
112
- bold=True,
113
- )
114
- )
115
92
 
116
93
 
117
94
  update.add_command(dependencies, name="deps") # alias for "dependencies"
@@ -122,10 +99,10 @@ update.add_command(dependencies, name="deps") # alias for "dependencies"
122
99
  @click.option(
123
100
  "--no-backup",
124
101
  is_flag=True,
125
- help="Skip creating a backup of the existing website template",
102
+ help="if enabled, the existing project website template will not be backed up",
126
103
  )
127
104
  def website(ctx, no_backup: bool):
128
- """Update project website template to the latest version"""
105
+ """Update the project website template to the latest version"""
129
106
  from afterpython.utils import find_node_env
130
107
 
131
108
  website_template_repo = "AfterPythonOrg/project-website-template"
afterpython/cli/main.py CHANGED
@@ -1,89 +1,32 @@
1
1
  import os
2
2
  import subprocess
3
- from collections import defaultdict
4
3
 
5
4
  import click
6
- from dotenv import find_dotenv, load_dotenv
7
5
  from trogon import tui
6
+ from dotenv import load_dotenv, find_dotenv
8
7
 
9
8
  import afterpython as ap
10
9
  from afterpython import __version__
11
- from afterpython.cli.commands.add import add
10
+ from afterpython.cli.commands.init import init
12
11
  from afterpython.cli.commands.build import build
13
- from afterpython.cli.commands.bump import bump
14
- from afterpython.cli.commands.check import check
15
- from afterpython.cli.commands.clean import clean
16
- from afterpython.cli.commands.commit import commit
17
- from afterpython.cli.commands.commitizen import commitizen
18
12
  from afterpython.cli.commands.dev import dev
19
- from afterpython.cli.commands.format import format
20
- from afterpython.cli.commands.init import init
21
- from afterpython.cli.commands.init_branch_rules import init_branch_rules
13
+ from afterpython.cli.commands.update import update
14
+ from afterpython.cli.commands.check import check
22
15
  from afterpython.cli.commands.install import install
23
- from afterpython.cli.commands.lock import lock
24
- from afterpython.cli.commands.pre_commit import pre_commit
16
+ from afterpython.cli.commands.format import format
17
+ from afterpython.cli.commands.sync import sync
18
+ from afterpython.cli.commands.start import start, doc, blog, tutorial, example, guide
25
19
  from afterpython.cli.commands.preview import preview
20
+ from afterpython.cli.commands.clean import clean
21
+ from afterpython.cli.commands.pre_commit import pre_commit
22
+ from afterpython.cli.commands.commitizen import commitizen
23
+ from afterpython.cli.commands.commit import commit
24
+ from afterpython.cli.commands.bump import bump
26
25
  from afterpython.cli.commands.release import release
27
- from afterpython.cli.commands.remove import remove
28
- from afterpython.cli.commands.start import blog, doc, example, guide, start, tutorial
29
- from afterpython.cli.commands.sync import sync
30
- from afterpython.cli.commands.update import update
31
-
32
-
33
- class AliasGroup(click.Group):
34
- """Custom group that displays command aliases together."""
35
-
36
- def __init__(self, *args, **kwargs):
37
- super().__init__(*args, **kwargs)
38
- self._aliases = defaultdict(list) # Maps primary command -> list of aliases
39
- self._alias_to_primary = {} # Maps alias -> primary command name
40
-
41
- def add_command(self, cmd, name=None):
42
- """Track aliases when the same command is added with different names."""
43
- name = name or cmd.name
44
-
45
- # Check if this command object was already added under a different name
46
- for existing_name, existing_cmd in self.commands.items():
47
- if existing_cmd is cmd and existing_name != name:
48
- # This is an alias
49
- self._aliases[existing_name].append(name)
50
- self._alias_to_primary[name] = existing_name
51
- break
52
-
53
- super().add_command(cmd, name)
54
-
55
- def format_commands(self, ctx, formatter):
56
- """Format commands with aliases shown together."""
57
- commands = []
58
- for subcommand in self.list_commands(ctx):
59
- # Skip aliases - they'll be shown with their primary command
60
- if subcommand in self._alias_to_primary:
61
- continue
62
-
63
- cmd = self.get_command(ctx, subcommand)
64
- if cmd is None:
65
- continue
66
-
67
- # Skip hidden commands
68
- if cmd.hidden:
69
- continue
70
-
71
- help_text = cmd.get_short_help_str(limit=formatter.width)
72
-
73
- # Build command name with aliases
74
- aliases = self._aliases.get(subcommand, [])
75
- if aliases:
76
- subcommand = f"{subcommand}, {', '.join(aliases)}"
77
-
78
- commands.append((subcommand, help_text))
79
-
80
- if commands:
81
- with formatter.section("Commands"):
82
- formatter.write_dl(commands)
83
26
 
84
27
 
85
28
  @tui(command="tui", help="Open terminal UI")
86
- @click.group(cls=AliasGroup, context_settings={"help_option_names": ["-h", "--help"]})
29
+ @click.group(context_settings={"help_option_names": ["-h", "--help"]})
87
30
  @click.pass_context
88
31
  @click.version_option(version=__version__)
89
32
  def afterpython_group(ctx):
@@ -107,7 +50,6 @@ afterpython_group.add_command(build)
107
50
  afterpython_group.add_command(dev)
108
51
  afterpython_group.add_command(update)
109
52
  afterpython_group.add_command(check)
110
- afterpython_group.add_command(check, name="lint")
111
53
  afterpython_group.add_command(format)
112
54
  afterpython_group.add_command(sync)
113
55
  afterpython_group.add_command(start)
@@ -121,12 +63,9 @@ afterpython_group.add_command(preview)
121
63
  afterpython_group.add_command(clean)
122
64
  afterpython_group.add_command(pre_commit)
123
65
  afterpython_group.add_command(pre_commit, name="pc")
66
+ afterpython_group.add_command(pre_commit, name="precommit")
124
67
  afterpython_group.add_command(commitizen)
125
68
  afterpython_group.add_command(commitizen, name="cz")
126
69
  afterpython_group.add_command(commit)
127
70
  afterpython_group.add_command(bump)
128
71
  afterpython_group.add_command(release)
129
- afterpython_group.add_command(init_branch_rules)
130
- afterpython_group.add_command(add)
131
- afterpython_group.add_command(remove)
132
- afterpython_group.add_command(lock)
afterpython/const.py CHANGED
@@ -1,4 +1,5 @@
1
1
  from afterpython._typing import tContentType
2
2
 
3
+
3
4
  NODEENV_VERSION = "24.11.0"
4
5
  CONTENT_TYPES: set[tContentType] = {"doc", "blog", "tutorial", "example", "guide"}
afterpython/cz.toml ADDED
@@ -0,0 +1,27 @@
1
+ [tool.commitizen]
2
+ name = "cz_conventional_commits"
3
+ # name = "cz_customize"
4
+ tag_format = "v$version"
5
+ version_scheme = "pep440"
6
+ version_provider = "uv"
7
+ update_changelog_on_bump = false
8
+ major_version_zero = true
9
+
10
+ # FIXME: commitizen can't even add a few custom types like "chore" and "wip", skip it for now
11
+ # [[tool.commitizen.customize.questions]]
12
+ # type = "list"
13
+ # name = "change_type"
14
+ # choices = [
15
+ # {value = "fix", name = "fix: A bug fix. Correlates with PATCH in SemVer"},
16
+ # {value = "feat", name = "feat: A new feature. Correlates with MINOR in SemVer"},
17
+ # {value = "docs", name = "docs: Documentation only changes"},
18
+ # {value = "style", name = "style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)"},
19
+ # {value = "refactor", name = "refactor: A code change that neither fixes a bug nor adds a feature"},
20
+ # {value = "perf", name = "perf: A code change that improves performance"},
21
+ # {value = "test", name = "test: Adding missing or correcting existing tests"},
22
+ # {value = "build", name = "build: Changes that affect the build system or external dependencies (example scopes: pip, docker, npm)"},
23
+ # {value = "ci", name = "ci: Changes to CI configuration files and scripts (example scopes: GitLabCI)"},
24
+ # {value = "chore", name = "chore: Other changes that don't modify src or test files"},
25
+ # {value = "wip", name = "wip: Work in progress"}
26
+ # ]
27
+ # message = "Select the type of change you are committing"
afterpython/pcu.py CHANGED
@@ -3,8 +3,7 @@ pcu = "pip check updates", similar to ncu (npm check updates in Node.js)
3
3
  """
4
4
 
5
5
  from __future__ import annotations
6
-
7
- from typing import TYPE_CHECKING, NamedTuple, TypeAlias, TypedDict
6
+ from typing import TYPE_CHECKING, TypedDict, NamedTuple, TypeAlias
8
7
 
9
8
  if TYPE_CHECKING:
10
9
  from tomlkit.toml_document import TOMLDocument
@@ -61,7 +60,6 @@ async def get_latest_versions(
61
60
  ) -> dict[str, Version | None]:
62
61
  """Get latest versions for a list of dependencies from PyPI."""
63
62
  import httpx
64
-
65
63
  from afterpython.utils import fetch_pypi_json
66
64
 
67
65
  async def fetch_version(
@@ -35,7 +35,7 @@ jobs:
35
35
  runs-on: ubuntu-latest
36
36
  steps:
37
37
  - name: Checkout code
38
- uses: actions/checkout@v6
38
+ uses: actions/checkout@v4
39
39
 
40
40
  - name: Install pnpm
41
41
  uses: pnpm/action-setup@v4
@@ -43,19 +43,19 @@ jobs:
43
43
  version: 10
44
44
 
45
45
  - name: Set up Node.js
46
- uses: actions/setup-node@v6
46
+ uses: actions/setup-node@v4
47
47
  with:
48
48
  node-version: '24'
49
49
  cache: 'pnpm'
50
50
  cache-dependency-path: './afterpython/_website/pnpm-lock.yaml'
51
51
 
52
52
  - name: Set up Python
53
- uses: actions/setup-python@v6
53
+ uses: actions/setup-python@v5
54
54
  with:
55
55
  python-version: '3.11'
56
56
 
57
57
  - name: Install uv
58
- uses: astral-sh/setup-uv@v7
58
+ uses: astral-sh/setup-uv@v5
59
59
  with:
60
60
  version: "latest"
61
61
 
@@ -71,7 +71,7 @@ jobs:
71
71
  ap build
72
72
 
73
73
  - name: Upload artifact
74
- uses: actions/upload-pages-artifact@v4
74
+ uses: actions/upload-pages-artifact@v3
75
75
  with:
76
76
  path: './afterpython/_website/build'
77
77
 
@@ -14,15 +14,15 @@ jobs:
14
14
 
15
15
  steps:
16
16
  - name: Checkout code
17
- uses: actions/checkout@v6
17
+ uses: actions/checkout@v4
18
18
 
19
19
  - name: Set up Python
20
- uses: actions/setup-python@v6
20
+ uses: actions/setup-python@v5
21
21
  with:
22
22
  python-version: '3.11'
23
23
 
24
24
  - name: Install uv
25
- uses: astral-sh/setup-uv@v7
25
+ uses: astral-sh/setup-uv@v5
26
26
  with:
27
27
  version: "latest"
28
28