makeapp 2.3.0__tar.gz → 2.4.0__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 (103) hide show
  1. {makeapp-2.3.0 → makeapp-2.4.0}/.gitignore +1 -0
  2. makeapp-2.4.0/PKG-INFO +85 -0
  3. makeapp-2.4.0/README.md +68 -0
  4. makeapp-2.4.0/src/makeapp/__init__.py +3 -0
  5. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/__default__/.github/workflows/python-package.yml +0 -2
  6. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/__default__/.gitignore +2 -1
  7. makeapp-2.4.0/src/makeapp/app_templates/__default__/INSTALL.md +35 -0
  8. makeapp-2.4.0/src/makeapp/app_templates/__default__/README.md +33 -0
  9. makeapp-2.4.0/src/makeapp/app_templates/__default__/docs/index.md +21 -0
  10. makeapp-2.4.0/src/makeapp/app_templates/__default__/docs/quickstart.md +21 -0
  11. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/__default__/pyproject.toml +4 -0
  12. makeapp-2.4.0/src/makeapp/app_templates/__default__/tests/test_basic.py +11 -0
  13. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/makeappconf.py +10 -12
  14. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/appmaker.py +33 -9
  15. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/apptools.py +84 -61
  16. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/cli.py +8 -1
  17. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/helpers/dist.py +6 -6
  18. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/helpers/files.py +1 -1
  19. makeapp-2.4.0/src/makeapp/helpers/tests.py +177 -0
  20. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/helpers/vcs.py +41 -27
  21. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/utils.py +56 -26
  22. makeapp-2.3.0/PKG-INFO +0 -136
  23. makeapp-2.3.0/README.md +0 -119
  24. makeapp-2.3.0/src/makeapp/__init__.py +0 -3
  25. makeapp-2.3.0/src/makeapp/app_templates/__default__/INSTALL.md +0 -24
  26. makeapp-2.3.0/src/makeapp/app_templates/__default__/README.md +0 -22
  27. makeapp-2.3.0/src/makeapp/app_templates/__default__/docs/index.md +0 -37
  28. makeapp-2.3.0/src/makeapp/app_templates/__default__/docs/quickstart.md +0 -3
  29. makeapp-2.3.0/src/makeapp/app_templates/__default__/tests/test_basic.py +0 -11
  30. makeapp-2.3.0/src/makeapp/helpers/tests.py +0 -129
  31. {makeapp-2.3.0 → makeapp-2.4.0}/LICENSE +0 -0
  32. {makeapp-2.3.0 → makeapp-2.4.0}/pyproject.toml +0 -0
  33. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/__default__/AUTHORS.md +0 -0
  34. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/__default__/CHANGELOG.md +0 -0
  35. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/__default__/CONTRIBUTING.md +0 -0
  36. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/__default__/mkdocs.yml +0 -0
  37. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/__default__/ruff.toml +0 -0
  38. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/__default__/src/__package_name__/__init__.py +0 -0
  39. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/__default__/tests/__init__.py +0 -0
  40. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/click/makeappconf.py +0 -0
  41. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/click/pyproject.toml +0 -0
  42. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/click/src/__package_name__/cli.py +0 -0
  43. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/console/pyproject.toml +0 -0
  44. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/console/src/__package_name__/cli.py +0 -0
  45. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/django/.github/workflows/python-package.yml +0 -0
  46. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/django/makeappconf.py +0 -0
  47. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/django/pyproject.toml +0 -0
  48. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/django/src/__package_name__/__init__.py +0 -0
  49. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/django/src/__package_name__/admin.py +0 -0
  50. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/django/src/__package_name__/apps.py +0 -0
  51. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/django/src/__package_name__/locale/empty +0 -0
  52. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/django/src/__package_name__/management/__init__.py +0 -0
  53. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/django/src/__package_name__/management/commands/__init__.py +0 -0
  54. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/django/src/__package_name__/models.py +0 -0
  55. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/django/src/__package_name__/templates/empty +0 -0
  56. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/django/src/__package_name__/templatetags/empty +0 -0
  57. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/django/src/__package_name__/tests/__init__.py +0 -0
  58. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/django/src/__package_name__/tests/conftest.py +0 -0
  59. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/django/src/__package_name__/tests/test_basic.py +0 -0
  60. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/django/src/__package_name__/views.py +0 -0
  61. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/pytestplugin/pyproject.toml +0 -0
  62. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/pytestplugin/src/__package_name__/entry.py +0 -0
  63. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/pytestplugin/tests/test_basic.py +0 -0
  64. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/.gitignore +0 -0
  65. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/conf/__package_name__-certbot-hook.sh +0 -0
  66. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/conf/__package_name__.service +0 -0
  67. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/conf/env_production.py +0 -0
  68. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/pyproject.toml +0 -0
  69. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/requirements.txt +0 -0
  70. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/src/__package_name__/core/uwsgiinit.py +0 -0
  71. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/src/__package_name__/settings/__init__.py +0 -0
  72. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/src/__package_name__/settings/auto.py +0 -0
  73. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/src/__package_name__/settings/base.py +0 -0
  74. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/src/__package_name__/settings/env_development.py +0 -0
  75. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/src/__package_name__/settings/env_testing.py +0 -0
  76. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/src/__package_name__/settings/sub_paths.py +0 -0
  77. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/src/__package_name__/uwsgicfg.py +0 -0
  78. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/state/certbot/empty +0 -0
  79. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/state/dumps/empty +0 -0
  80. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/state/media/empty +0 -0
  81. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/state/spool/empty +0 -0
  82. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/state/static/empty +0 -0
  83. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/tests/conftest.py +0 -0
  84. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/tests/requirements.txt +0 -0
  85. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/tests/test_module.py +0 -0
  86. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/app_templates/webscaff/wscaff.yml +0 -0
  87. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/appconfig.py +0 -0
  88. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/apptemplate.py +0 -0
  89. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/exceptions.py +0 -0
  90. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/helpers/__init__.py +0 -0
  91. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/helpers/venvs.py +0 -0
  92. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/license_templates/apache2 +0 -0
  93. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/license_templates/apache2_src +0 -0
  94. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/license_templates/bsd2cl +0 -0
  95. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/license_templates/bsd3cl +0 -0
  96. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/license_templates/gpl2 +0 -0
  97. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/license_templates/gpl2_src +0 -0
  98. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/license_templates/gpl3 +0 -0
  99. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/license_templates/gpl3_src +0 -0
  100. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/license_templates/mit +0 -0
  101. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/license_templates/no +0 -0
  102. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/license_templates/no_src +0 -0
  103. {makeapp-2.3.0 → makeapp-2.4.0}/src/makeapp/rendering.py +0 -0
@@ -10,4 +10,5 @@ __pycache__
10
10
  .mypy_cache
11
11
  .ruff_cache
12
12
  .pytest_cache
13
+ .ma-*
13
14
  .env
makeapp-2.4.0/PKG-INFO ADDED
@@ -0,0 +1,85 @@
1
+ Metadata-Version: 2.5
2
+ Name: makeapp
3
+ Version: 2.4.0
4
+ Summary: Simplifies routine Python application development processes.
5
+ Project-URL: Homepage, https://github.com/idlesign/makeapp
6
+ Project-URL: Documentation, https://makeapp.readthedocs.io/
7
+ Author-email: Igor Starikov <idlesign@yandex.ru>
8
+ License-Expression: BSD-3-Clause
9
+ License-File: LICENSE
10
+ Keywords: development,scaffolding
11
+ Requires-Python: >=3.11
12
+ Requires-Dist: click
13
+ Requires-Dist: jinja2~=3.1
14
+ Requires-Dist: pyyaml
15
+ Requires-Dist: requests
16
+ Description-Content-Type: text/markdown
17
+
18
+ # makeapp
19
+
20
+ [![PyPI - Version](https://img.shields.io/pypi/v/makeapp)](https://pypi.org/project/makeapp/)
21
+ [![License](https://img.shields.io/pypi/l/makeapp)](https://pypi.org/project/makeapp/)
22
+ [![Coverage](https://img.shields.io/coverallsCoverage/github/idlesign/makeapp)](https://coveralls.io/github/idlesign/makeapp)
23
+ [![Docs](https://img.shields.io/readthedocs/makeapp)](https://makeapp.readthedocs.io/)
24
+
25
+ `makeapp` scaffolds Python projects and provides one CLI for their common development tasks. It can create a project
26
+ from composable templates, initialize Git and a virtual environment, run a GitHub Actions test matrix locally, maintain
27
+ a changelog, and publish releases.
28
+
29
+ ## Install
30
+
31
+ Python 3.11 or newer and [uv](https://docs.astral.sh/uv/getting-started/installation/) are required.
32
+
33
+ ```bash
34
+ uv tool install makeapp
35
+ ```
36
+
37
+ Both `makeapp` and its short alias `ma` invoke the same command.
38
+
39
+ ## Quick start
40
+
41
+ ```bash
42
+ ma new shiny_app ./shiny-app --description "My app" --author "I am" --no-prompt
43
+ cd shiny-app
44
+ ma tests
45
+ ```
46
+
47
+ The default scaffold contains a `src`-layout package, tests, project metadata, a changelog, and MkDocs documentation.
48
+ The non-interactive command also initializes Git and runs `uv sync` to create `.venv`.
49
+
50
+ Bundled templates can extend the default scaffold:
51
+
52
+ - `console` for an `argparse` command-line application;
53
+ - `click` for a Click command-line application;
54
+ - `django` for a reusable Django application;
55
+ - `pytestplugin` for a pytest plugin;
56
+ - `webscaff` for a Linux-hosted Django/Webscaff project.
57
+
58
+ For example:
59
+
60
+ ```bash
61
+ ma new shiny_cli ./shiny-cli -t click --no-prompt
62
+ ```
63
+
64
+ ## Project workflow
65
+
66
+ ```bash
67
+ ma up # Synchronize the development environment.
68
+ ma style # Run Ruff checks and apply safe fixes.
69
+ ma tests # Run the configured test matrix.
70
+ ma docs --build # Build documentation without starting a server.
71
+ ma change "+ Add a feature" # Update the changelog and commit modified files.
72
+ ma release # Prepare a release and optionally publish it.
73
+ ```
74
+
75
+ Review changes before running `ma change`: it stages and commits modified tracked files together with the changelog.
76
+
77
+ ## Documentation
78
+
79
+ The full user and extension documentation is available at <https://makeapp.readthedocs.io/>.
80
+
81
+ - [Quickstart](https://makeapp.readthedocs.io/en/latest/quickstart/)
82
+ - [CLI reference](https://makeapp.readthedocs.io/en/latest/cli_reference/)
83
+ - [Template authoring](https://makeapp.readthedocs.io/en/latest/template_authoring/)
84
+ - [Publishing](https://makeapp.readthedocs.io/en/latest/publishing/)
85
+ Issues and feature requests are welcome in the [GitHub issue tracker](https://github.com/idlesign/makeapp/issues).
@@ -0,0 +1,68 @@
1
+ # makeapp
2
+
3
+ [![PyPI - Version](https://img.shields.io/pypi/v/makeapp)](https://pypi.org/project/makeapp/)
4
+ [![License](https://img.shields.io/pypi/l/makeapp)](https://pypi.org/project/makeapp/)
5
+ [![Coverage](https://img.shields.io/coverallsCoverage/github/idlesign/makeapp)](https://coveralls.io/github/idlesign/makeapp)
6
+ [![Docs](https://img.shields.io/readthedocs/makeapp)](https://makeapp.readthedocs.io/)
7
+
8
+ `makeapp` scaffolds Python projects and provides one CLI for their common development tasks. It can create a project
9
+ from composable templates, initialize Git and a virtual environment, run a GitHub Actions test matrix locally, maintain
10
+ a changelog, and publish releases.
11
+
12
+ ## Install
13
+
14
+ Python 3.11 or newer and [uv](https://docs.astral.sh/uv/getting-started/installation/) are required.
15
+
16
+ ```bash
17
+ uv tool install makeapp
18
+ ```
19
+
20
+ Both `makeapp` and its short alias `ma` invoke the same command.
21
+
22
+ ## Quick start
23
+
24
+ ```bash
25
+ ma new shiny_app ./shiny-app --description "My app" --author "I am" --no-prompt
26
+ cd shiny-app
27
+ ma tests
28
+ ```
29
+
30
+ The default scaffold contains a `src`-layout package, tests, project metadata, a changelog, and MkDocs documentation.
31
+ The non-interactive command also initializes Git and runs `uv sync` to create `.venv`.
32
+
33
+ Bundled templates can extend the default scaffold:
34
+
35
+ - `console` for an `argparse` command-line application;
36
+ - `click` for a Click command-line application;
37
+ - `django` for a reusable Django application;
38
+ - `pytestplugin` for a pytest plugin;
39
+ - `webscaff` for a Linux-hosted Django/Webscaff project.
40
+
41
+ For example:
42
+
43
+ ```bash
44
+ ma new shiny_cli ./shiny-cli -t click --no-prompt
45
+ ```
46
+
47
+ ## Project workflow
48
+
49
+ ```bash
50
+ ma up # Synchronize the development environment.
51
+ ma style # Run Ruff checks and apply safe fixes.
52
+ ma tests # Run the configured test matrix.
53
+ ma docs --build # Build documentation without starting a server.
54
+ ma change "+ Add a feature" # Update the changelog and commit modified files.
55
+ ma release # Prepare a release and optionally publish it.
56
+ ```
57
+
58
+ Review changes before running `ma change`: it stages and commits modified tracked files together with the changelog.
59
+
60
+ ## Documentation
61
+
62
+ The full user and extension documentation is available at <https://makeapp.readthedocs.io/>.
63
+
64
+ - [Quickstart](https://makeapp.readthedocs.io/en/latest/quickstart/)
65
+ - [CLI reference](https://makeapp.readthedocs.io/en/latest/cli_reference/)
66
+ - [Template authoring](https://makeapp.readthedocs.io/en/latest/template_authoring/)
67
+ - [Publishing](https://makeapp.readthedocs.io/en/latest/publishing/)
68
+ Issues and feature requests are welcome in the [GitHub issue tracker](https://github.com/idlesign/makeapp/issues).
@@ -0,0 +1,3 @@
1
+
2
+ VERSION = '2.4.0'
3
+ """Application version number tuple."""
@@ -2,9 +2,7 @@ name: Python package
2
2
 
3
3
  on:
4
4
  push:
5
- branches: [ master ]
6
5
  pull_request:
7
- branches: [ master ]
8
6
 
9
7
  jobs:
10
8
  build:
@@ -11,5 +11,6 @@ __pycache__
11
11
  .mypy_cache
12
12
  .ruff_cache
13
13
  .pytest_cache
14
+ .ma-*
14
15
  .env
15
- {% endblock %}
16
+ {% endblock %}
@@ -0,0 +1,35 @@
1
+ # Installing {{ app_name }}
2
+
3
+ Python {{ python_version }} or newer and [uv](https://docs.astral.sh/uv/) are required.
4
+
5
+ ## From PyPI
6
+
7
+ Add the package to a project:
8
+
9
+ ```bash
10
+ uv add {{ app_name }}
11
+ ```
12
+
13
+ If the package exposes a command-line application, install it as an isolated tool:
14
+
15
+ ```bash
16
+ uv tool install {{ app_name }}
17
+ ```
18
+
19
+ Upgrade the tool with:
20
+
21
+ ```bash
22
+ uv tool upgrade {{ app_name }}
23
+ ```
24
+
25
+ ## From source
26
+
27
+ Clone the repository and synchronize its development environment:
28
+
29
+ ```bash
30
+ git clone https://example.com/owner/repository.git {{ app_name }}
31
+ cd {{ app_name }}
32
+ uv sync
33
+ ```
34
+
35
+ Replace the example repository URL with the source repository. Run commands in the project environment with `uv run`.
@@ -0,0 +1,33 @@
1
+ # {{ app_name }}
2
+
3
+ [![PyPI - Version](https://img.shields.io/pypi/v/{{ app_name }})](https://pypi.org/project/{{ app_name }}/)
4
+ [![License](https://img.shields.io/pypi/l/{{ app_name }})](https://pypi.org/project/{{ app_name }}/)
5
+ [![Docs](https://img.shields.io/readthedocs/{{ app_name }})](https://{{ app_name }}.readthedocs.io/)
6
+ {% block badges %}
7
+ {% endblock %}
8
+
9
+ *{{ description }}*
10
+
11
+ Project homepage: <{{ url }}>
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ uv add {{ app_name }}
17
+ ```
18
+
19
+ See [INSTALL.md](INSTALL.md) for installation from source and tool installation.
20
+
21
+ ## Development
22
+
23
+ ```bash
24
+ uv sync
25
+ uv run pytest
26
+ uv run mkdocs build --strict
27
+ ```
28
+
29
+ Project documentation is available at <https://{{ app_name }}.readthedocs.io/>.
30
+
31
+ ## Contributing
32
+
33
+ See [CONTRIBUTING.md](CONTRIBUTING.md) before submitting an issue or pull request.
@@ -0,0 +1,21 @@
1
+ # {{ app_name }}
2
+
3
+ *{{ description }}*
4
+
5
+ ## Requirements
6
+
7
+ - Python {{ python_version }} or newer
8
+ - [uv](https://docs.astral.sh/uv/)
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ uv add {{ app_name }}
14
+ ```
15
+
16
+ Continue with the [quickstart](quickstart.md) to verify the installation and run the project checks.
17
+
18
+ ## Project links
19
+
20
+ - [Source and issue tracker]({{ url }})
21
+ - [PyPI](https://pypi.org/project/{{ app_name }}/)
@@ -0,0 +1,21 @@
1
+ # Quickstart
2
+
3
+ Install {{ app_name }} in an existing uv project:
4
+
5
+ ```bash
6
+ uv add {{ app_name }}
7
+ ```
8
+
9
+ To work on the source checkout, synchronize dependencies and run the checks:
10
+
11
+ ```bash
12
+ uv sync
13
+ uv run pytest
14
+ uv run mkdocs build --strict
15
+ ```
16
+
17
+ Start the local documentation server with:
18
+
19
+ ```bash
20
+ uv run mkdocs serve
21
+ ```
@@ -40,11 +40,15 @@ Homepage = "{{ url }}"
40
40
 
41
41
  [dependency-groups]
42
42
  dev = [
43
+ {include-group = "docs"},
43
44
  {include-group = "linters"},
44
45
  {include-group = "tests"},
45
46
  {% block deps_dev %}
46
47
  {% endblock %}
47
48
  ]
49
+ docs = [
50
+ "mkdocs-material",
51
+ ]
48
52
  linters = [
49
53
  {% block deps_linters %}
50
54
  {% endblock %}
@@ -0,0 +1,11 @@
1
+ import pytest
2
+
3
+
4
+ class TestApp:
5
+
6
+ def test_method(self):
7
+
8
+ assert 1 == 1
9
+
10
+ with pytest.raises(ValueError, match='Tested!'):
11
+ raise ValueError('Tested!')
@@ -10,8 +10,6 @@ join = os.path.join # Short alias
10
10
 
11
11
  class WebscaffConfig(Config):
12
12
 
13
- parent_template = ['pytest']
14
-
15
13
  domain = ConfigSetting(title='Domain Name', default='')
16
14
  email = ConfigSetting(title='Admin E-mail')
17
15
  host = ConfigSetting(title='Remote Host IP')
@@ -51,21 +49,21 @@ class WebscaffConfig(Config):
51
49
 
52
50
  # Install into venv the package itself not to conflict
53
51
  # with Django's `startproject` command.
54
- run_command('. venv/bin/activate && pip install -e .')
52
+ run_command(['venv/bin/pip', 'install', '-e', '.'])
55
53
 
56
54
  # Initialize local sqlite DB.
57
- run_command(f'venv/bin/{package_name} makemigrations')
58
- run_command(f'venv/bin/{package_name} migrate')
55
+ run_command([f'venv/bin/{package_name}', 'makemigrations'])
56
+ run_command([f'venv/bin/{package_name}', 'migrate'])
59
57
 
60
58
  def prepare_venv(self):
61
59
  self.logger.info('Bootstrapping virtual environment for project ...')
62
60
 
63
- run_command('python3 -m venv venv/')
61
+ run_command(['python3', '-m', 'venv', 'venv/'])
64
62
 
65
- cmd_install = '. venv/bin/activate && pip install -r '
63
+ cmd_install = ['venv/bin/pip', 'install', '-r']
66
64
 
67
- run_command(cmd_install + 'requirements.txt')
68
- run_command(cmd_install + 'tests/requirements.txt')
65
+ run_command([*cmd_install, 'requirements.txt'])
66
+ run_command([*cmd_install, 'tests/requirements.txt'])
69
67
 
70
68
  def prepare_django_settings_base(self, dir_tmp):
71
69
 
@@ -107,10 +105,10 @@ class WebscaffConfig(Config):
107
105
  dir_package = self.dir_package_root
108
106
  package_name = self.package_name
109
107
 
110
- command_django_admin = './venv/bin/django-admin'
108
+ command_django_admin = 'venv/bin/django-admin'
111
109
 
112
110
  with temp_dir() as dir_tmp:
113
- run_command(f'{command_django_admin} startproject {package_name} {dir_tmp}')
111
+ run_command([command_django_admin, 'startproject', package_name, dir_tmp])
114
112
 
115
113
  # We'd replace settings module paths.
116
114
  replace = partial(
@@ -131,7 +129,7 @@ class WebscaffConfig(Config):
131
129
 
132
130
  # Create basic app.
133
131
  dir_app = join(dir_package, 'core')
134
- run_command(f'{command_django_admin} startapp core {dir_app}')
132
+ run_command([command_django_admin, 'startapp', 'core', dir_app])
135
133
  replace_infile(
136
134
  join(dir_app, 'apps.py'),
137
135
  {
@@ -1,3 +1,4 @@
1
+ import keyword
1
2
  import logging
2
3
  import os
3
4
  import re
@@ -13,7 +14,7 @@ from .exceptions import AppMakerException
13
14
  from .helpers.vcs import VcsHelper
14
15
  from .helpers.venvs import VenvHelper
15
16
  from .rendering import Renderer
16
- from .utils import PYTHON_VERSION, configure_logging, get_user_dir, read_ini
17
+ from .utils import PYTHON_MIN_VERSION, configure_logging, get_user_dir, read_ini
17
18
 
18
19
  RE_UNKNOWN_MARKER = re.compile(r'{{ [^}]+ }}')
19
20
  BASE_PATH = os.path.dirname(__file__)
@@ -68,7 +69,7 @@ class AppMaker:
68
69
  'license_ident': LICENSES[default_license][1],
69
70
  'vcs': default_vcs,
70
71
  'vcs_remote': None,
71
- 'python_version': '.'.join(map(str, PYTHON_VERSION[:2])),
72
+ 'python_version': '.'.join(map(str, PYTHON_MIN_VERSION)),
72
73
  }
73
74
 
74
75
  app_template_default: AppTemplate = None
@@ -225,13 +226,24 @@ class AppMaker:
225
226
  name_available = True
226
227
 
227
228
  for label, url in sites_registry.items():
228
- response = requests.get(url)
229
+ try:
230
+ response = requests.get(url, timeout=5)
231
+ except requests.RequestException as e:
232
+ raise AppMakerException(
233
+ f'Unable to check application name at {label}: {e}.'
234
+ ) from e
229
235
 
230
236
  if response.status_code == 200:
231
237
  self.logger.warning(f'Application name seems to be in use: {label} - {url}')
232
238
  name_available = False
233
239
  break
234
240
 
241
+ if response.status_code != 404:
242
+ raise AppMakerException(
243
+ f'Unable to check application name at {label}: '
244
+ f'HTTP {response.status_code}.'
245
+ )
246
+
235
247
  if name_available:
236
248
  self.logger.info(
237
249
  f"Application name `{self.settings['app_name']}` seems "
@@ -330,8 +342,18 @@ class AppMaker:
330
342
  self._hook_run('rollout_pre')
331
343
 
332
344
  files = self._get_template_files()
345
+ dest_path = Path(dest).resolve()
333
346
  for target, template_file in files.items():
334
- target = os.path.join(dest, target)
347
+ target_path = (dest_path / target).resolve()
348
+
349
+ try:
350
+ target_path.relative_to(dest_path)
351
+ except ValueError as e:
352
+ raise AppMakerException(
353
+ f'Template target path escapes destination: {target}.'
354
+ ) from e
355
+
356
+ target = f'{target_path}'
335
357
 
336
358
  if not os.path.exists(target) or overwrite:
337
359
 
@@ -378,11 +400,7 @@ class AppMaker:
378
400
 
379
401
  """
380
402
  with open(path, 'w') as f:
381
-
382
- f.write(contents)
383
-
384
- if contents.endswith('\n'):
385
- f.write('\n')
403
+ f.write(contents.rstrip('\n') + '\n')
386
404
 
387
405
  def _copy_file(self, src: TemplateFile, dest: str, prepend_data: str = None):
388
406
  """Copies a file from `src` to `dest` replacing settings markers
@@ -580,6 +598,12 @@ class AppMaker:
580
598
  for name, val in settings_base.items():
581
599
  settings_base[name] = self._replace_settings_markers(val, settings=settings_base)
582
600
 
601
+ package_name = settings_base['package_name']
602
+ if not package_name or not package_name.isidentifier() or keyword.iskeyword(package_name):
603
+ raise AppMakerException(
604
+ f'Invalid Python package name: `{package_name}`.'
605
+ )
606
+
583
607
  self._validate_setting('license', list(self.LICENSES), settings_base)
584
608
 
585
609
  license = self.LICENSES[settings_base['license']]