xtr-cli 5.0.0__tar.gz → 5.1.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 (75) hide show
  1. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/PKG-INFO +10 -9
  2. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/README.md +9 -8
  3. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/pyproject.toml +1 -1
  4. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/pyproject.toml.orig +1 -1
  5. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/add_on_catalog.py +7 -11
  6. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/cli/files/README.md.tmpl +3 -1
  7. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/cli/files/app/kernel.py.tmpl +1 -1
  8. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/webapp/files/README.md.tmpl +3 -1
  9. xtr_cli-5.1.0/src/xtr_cli/templates/webapp/files/app/config/__init__.py.tmpl +5 -0
  10. xtr_cli-5.1.0/src/xtr_cli/templates/webapp/files/app/config/packages/__init__.py.tmpl +5 -0
  11. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/webapp/files/app/kernel.py.tmpl +1 -1
  12. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/webapp/template.toml +2 -1
  13. xtr_cli-5.0.0/src/xtr_cli/templates/webapp/files/app/config/__init__.py.tmpl +0 -5
  14. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/LICENSE +0 -0
  15. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/__init__.py +0 -0
  16. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/__main__.py +0 -0
  17. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/add_on.py +0 -0
  18. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/add_on_choice.py +0 -0
  19. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/command/__init__.py +0 -0
  20. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/command/init_command.py +0 -0
  21. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/command/new_command.py +0 -0
  22. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/command/serve_command.py +0 -0
  23. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/command_support.py +0 -0
  24. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/exception/__init__.py +0 -0
  25. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/exception/ambiguous_web_entry_point_error.py +0 -0
  26. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/exception/cli_error.py +0 -0
  27. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/exception/directory_not_empty_error.py +0 -0
  28. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/exception/invalid_project_name_error.py +0 -0
  29. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/exception/invalid_template_error.py +0 -0
  30. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/exception/project_not_found_error.py +0 -0
  31. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/exception/step_failed_error.py +0 -0
  32. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/exception/unknown_add_on_error.py +0 -0
  33. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/exception/unknown_template_error.py +0 -0
  34. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/exception/unsupported_python_error.py +0 -0
  35. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/exception/web_entry_point_not_found_error.py +0 -0
  36. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/process_runner_interface.py +0 -0
  37. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/project_name.py +0 -0
  38. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/project_questions.py +0 -0
  39. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/project_settings.py +0 -0
  40. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/py.typed +0 -0
  41. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/scaffold_plan.py +0 -0
  42. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/scaffolder.py +0 -0
  43. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/subprocess_runner.py +0 -0
  44. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/template.py +0 -0
  45. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/template_catalog.py +0 -0
  46. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/__init__.py +0 -0
  47. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/cli/files/app/__init__.py.tmpl +0 -0
  48. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/cli/files/app/__main__.py.tmpl +0 -0
  49. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/cli/files/app/command/__init__.py.tmpl +0 -0
  50. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/cli/files/app/command/hello_command.py.tmpl +0 -0
  51. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/cli/files/app/py.typed.tmpl +0 -0
  52. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/cli/files/gitignore.tmpl +0 -0
  53. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/cli/files/pyproject.toml.tmpl +0 -0
  54. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/cli/files/python-version.tmpl +0 -0
  55. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/cli/files/tests/__init__.py.tmpl +0 -0
  56. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/cli/files/tests/test_kernel.py.tmpl +0 -0
  57. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/cli/template.toml +0 -0
  58. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/webapp/files/app/__init__.py.tmpl +0 -0
  59. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/webapp/files/app/__main__.py.tmpl +0 -0
  60. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/webapp/files/app/command/__init__.py.tmpl +0 -0
  61. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/webapp/files/app/command/hello_command.py.tmpl +0 -0
  62. {xtr_cli-5.0.0/src/xtr_cli/templates/webapp/files/app/config → xtr_cli-5.1.0/src/xtr_cli/templates/webapp/files/app/config/packages}/http_kernel.py.tmpl +0 -0
  63. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/webapp/files/app/py.typed.tmpl +0 -0
  64. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/webapp/files/app/web/__init__.py.tmpl +0 -0
  65. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/webapp/files/app/web/__main__.py.tmpl +0 -0
  66. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/webapp/files/app/web/app.py.tmpl +0 -0
  67. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/webapp/files/app/web/routes.py.tmpl +0 -0
  68. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/webapp/files/gitignore.tmpl +0 -0
  69. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/webapp/files/pyproject.toml.tmpl +0 -0
  70. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/webapp/files/python-version.tmpl +0 -0
  71. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/webapp/files/tests/__init__.py.tmpl +0 -0
  72. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/webapp/files/tests/test_kernel.py.tmpl +0 -0
  73. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/templates/webapp/files/tests/test_web.py.tmpl +0 -0
  74. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/web_entry_point.py +0 -0
  75. {xtr_cli-5.0.0 → xtr_cli-5.1.0}/src/xtr_cli/web_entry_point_finder.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xtr-cli
3
- Version: 5.0.0
3
+ Version: 5.1.0
4
4
  Summary: Scaffolds a new xtr application — a console application or a web application — in one command, and serves it.
5
5
  Keywords: scaffold,new project,template,console,web,xtr-dependency-injection
6
6
  Author: Xterr
@@ -139,7 +139,7 @@ refused before anything is written.
139
139
  2. `uv add` the template's packages and the add-ons; every unversioned xtr requirement is pinned
140
140
  to this tool's major version, so the files and the packages are from the same release.
141
141
  3. `uv add --dev` the tools: `xtr-recipes`, `pytest`, `ruff`, `basedpyright`, `ty`.
142
- 4. `uv run xtr-recipes recipes:sync` — each package's recipe writes `<app>/bundles.py`, its
142
+ 4. `uv run xtr-recipes recipes:sync` — each package's recipe writes `<app>/config/bundles.py`, its
143
143
  configuration files, its `.env` and `.gitignore` blocks, and `xtr.lock`; the steps it cannot
144
144
  make are printed.
145
145
  5. `git init`; nothing is committed.
@@ -229,13 +229,13 @@ way it would for a package added later with `xtr-recipes recipes:add`.
229
229
 
230
230
  | Add-on | Installs | Variants |
231
231
  |---|---|---|
232
- | `orm` | `xtr-orm` | `sqlite` (default), `postgres`, `mysql` |
233
- | `messenger` | `xtr-messenger` | `amqp`, `pydantic` |
232
+ | `orm` | `xtr-orm` | `postgres` (default), `sqlite`, `mysql` |
233
+ | `messenger` | `xtr-messenger` | `amqp` (default), `pydantic` |
234
234
  | `scheduler` | `xtr-scheduler[cron]` | |
235
235
  | `event-dispatcher` | `xtr-event-dispatcher` | |
236
236
  | `cache` | `xtr-cache` | `redis` |
237
237
  | `lock` | `xtr-lock` | `redis` |
238
- | `rate-limiter` | `xtr-rate-limiter` | `redis` |
238
+ | `rate-limiter` | `xtr-rate-limiter` | |
239
239
  | `storage` | `xtr-storage` | `s3`, `gcs` |
240
240
  | `http-client` | `xtr-http-client` | `http2` |
241
241
  | `security` | `xtr-security` — `webapp` only | |
@@ -247,10 +247,11 @@ Variants only pick third-party backends. Integrations between xtr packages turn
247
247
  installed: choose `orm` beside `oauth2` to keep its clients in a database, `http-client` beside
248
248
  `webhook` to send webhooks, `rate-limiter` beside `http-client` to pace requests.
249
249
 
250
- `jwt` boots without a key and signs nothing until one is there: run
251
- `uv run <name> jwt:generate-keypair --kid jwt --output-dir secrets` for development, and mount
252
- the deployment's own key in production. No key is ever minted for you.
253
- `oauth2` likewise issues nothing until its key pair, encryption key and issuer are configured.
250
+ `jwt` and `oauth2` each have their recipe mint a development signing key under `secrets/`,
251
+ encrypted with a pass phrase it generates in `.env` — and, for `oauth2`, the encryption key too.
252
+ The keys are ignored: another checkout runs `uv run xtr-recipes recipes:install <package>` to
253
+ mint its own, and production mounts the deployment's own key and sets its own secrets. `oauth2`
254
+ still issues nothing until its issuer is configured.
254
255
 
255
256
  Variants follow the name after `:`, joined with `+`: `orm:sqlite+postgres`. A name alone takes
256
257
  the defaults; `messenger:` picks none. Asked interactively, an add-on with variants is followed by
@@ -118,7 +118,7 @@ refused before anything is written.
118
118
  2. `uv add` the template's packages and the add-ons; every unversioned xtr requirement is pinned
119
119
  to this tool's major version, so the files and the packages are from the same release.
120
120
  3. `uv add --dev` the tools: `xtr-recipes`, `pytest`, `ruff`, `basedpyright`, `ty`.
121
- 4. `uv run xtr-recipes recipes:sync` — each package's recipe writes `<app>/bundles.py`, its
121
+ 4. `uv run xtr-recipes recipes:sync` — each package's recipe writes `<app>/config/bundles.py`, its
122
122
  configuration files, its `.env` and `.gitignore` blocks, and `xtr.lock`; the steps it cannot
123
123
  make are printed.
124
124
  5. `git init`; nothing is committed.
@@ -208,13 +208,13 @@ way it would for a package added later with `xtr-recipes recipes:add`.
208
208
 
209
209
  | Add-on | Installs | Variants |
210
210
  |---|---|---|
211
- | `orm` | `xtr-orm` | `sqlite` (default), `postgres`, `mysql` |
212
- | `messenger` | `xtr-messenger` | `amqp`, `pydantic` |
211
+ | `orm` | `xtr-orm` | `postgres` (default), `sqlite`, `mysql` |
212
+ | `messenger` | `xtr-messenger` | `amqp` (default), `pydantic` |
213
213
  | `scheduler` | `xtr-scheduler[cron]` | |
214
214
  | `event-dispatcher` | `xtr-event-dispatcher` | |
215
215
  | `cache` | `xtr-cache` | `redis` |
216
216
  | `lock` | `xtr-lock` | `redis` |
217
- | `rate-limiter` | `xtr-rate-limiter` | `redis` |
217
+ | `rate-limiter` | `xtr-rate-limiter` | |
218
218
  | `storage` | `xtr-storage` | `s3`, `gcs` |
219
219
  | `http-client` | `xtr-http-client` | `http2` |
220
220
  | `security` | `xtr-security` — `webapp` only | |
@@ -226,10 +226,11 @@ Variants only pick third-party backends. Integrations between xtr packages turn
226
226
  installed: choose `orm` beside `oauth2` to keep its clients in a database, `http-client` beside
227
227
  `webhook` to send webhooks, `rate-limiter` beside `http-client` to pace requests.
228
228
 
229
- `jwt` boots without a key and signs nothing until one is there: run
230
- `uv run <name> jwt:generate-keypair --kid jwt --output-dir secrets` for development, and mount
231
- the deployment's own key in production. No key is ever minted for you.
232
- `oauth2` likewise issues nothing until its key pair, encryption key and issuer are configured.
229
+ `jwt` and `oauth2` each have their recipe mint a development signing key under `secrets/`,
230
+ encrypted with a pass phrase it generates in `.env` — and, for `oauth2`, the encryption key too.
231
+ The keys are ignored: another checkout runs `uv run xtr-recipes recipes:install <package>` to
232
+ mint its own, and production mounts the deployment's own key and sets its own secrets. `oauth2`
233
+ still issues nothing until its issuer is configured.
233
234
 
234
235
  Variants follow the name after `:`, joined with `+`: `orm:sqlite+postgres`. A name alone takes
235
236
  the defaults; `messenger:` picks none. Asked interactively, an add-on with variants is followed by
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "xtr-cli"
3
- version = "5.0.0"
3
+ version = "5.1.0"
4
4
  description = "Scaffolds a new xtr application — a console application or a web application — in one command, and serves it."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "xtr-cli"
3
- version = "5.0.0"
3
+ version = "5.1.0"
4
4
  description = "Scaffolds a new xtr application — a console application or a web application — in one command, and serves it."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -22,7 +22,8 @@ _SHIPPED = (
22
22
  "xtr-orm",
23
23
  (),
24
24
  ("sqlite", "postgres", "mysql"),
25
- ("sqlite",),
25
+ # The recipe's DATABASE_URL is a PostgreSQL one, so its driver is the default.
26
+ ("postgres",),
26
27
  "database drivers",
27
28
  ),
28
29
  AddOn(
@@ -31,7 +32,8 @@ _SHIPPED = (
31
32
  "xtr-messenger",
32
33
  (),
33
34
  ("amqp", "pydantic"),
34
- (),
35
+ # The recipe's MESSENGER_DSN is a RabbitMQ one, so its transport is the default.
36
+ ("amqp",),
35
37
  "transports and serializers",
36
38
  ),
37
39
  AddOn(
@@ -55,15 +57,9 @@ _SHIPPED = (
55
57
  "backends",
56
58
  ),
57
59
  AddOn("lock", "Locks around shared resources.", "xtr-lock", (), ("redis",), (), "stores"),
58
- AddOn(
59
- "rate-limiter",
60
- "Limits on how often anything may happen.",
61
- "xtr-rate-limiter",
62
- (),
63
- ("redis",),
64
- (),
65
- "stores",
66
- ),
60
+ # No store is asked for: the recipe writes no configuration that would use
61
+ # one, so a project picks its store where it names its limiters.
62
+ AddOn("rate-limiter", "Limits on how often anything may happen.", "xtr-rate-limiter"),
67
63
  AddOn(
68
64
  "storage",
69
65
  "Files on local disk, in memory or in object stores.",
@@ -20,7 +20,9 @@ The environment is read from `.env`, then `.env.local`, then `.env.<APP_ENV>` an
20
20
  src/${app}/
21
21
  ├── __main__.py the console entry point
22
22
  ├── kernel.py the kernel every entry point builds, and the environment loader
23
- ├── bundles.py the active bundles — written by xtr-recipes
23
+ ├── config/
24
+ │ ├── bundles.py the active bundles — written by xtr-recipes
25
+ │ └── packages/ one @configure module per bundle
24
26
  └── command/ the console commands
25
27
  ```
26
28
 
@@ -19,7 +19,7 @@ PROJECT_DIR: Final = Path(__file__).resolve().parents[2]
19
19
 
20
20
  kernel: Final = Kernel(
21
21
  "${app}",
22
- # The bundles are read from ${app}.bundles.BUNDLES; the environment from APP_ENV.
22
+ # The bundles are read from ${app}.config.bundles.BUNDLES; the environment from APP_ENV.
23
23
  allowed_envs=("dev", "test", "prod"),
24
24
  )
25
25
 
@@ -21,7 +21,9 @@ The environment is read from `.env`, then `.env.local`, then `.env.<APP_ENV>` an
21
21
  src/${app}/
22
22
  ├── __main__.py the console entry point
23
23
  ├── kernel.py the kernel every entry point builds, and the environment loader
24
- ├── bundles.py the active bundles — written by xtr-recipes
24
+ ├── config/
25
+ │ ├── bundles.py the active bundles — written by xtr-recipes
26
+ │ └── packages/ one @configure module per bundle
25
27
  ├── command/ the console commands
26
28
  └── web/
27
29
  ├── __main__.py the web entry point
@@ -0,0 +1,5 @@
1
+ """The application's configuration: the bundle list, each bundle's configuration, the routes."""
2
+
3
+ from __future__ import annotations
4
+
5
+ __all__: list[str] = []
@@ -0,0 +1,5 @@
1
+ """Configuration modules: one ``@configure`` function per bundle the application changes."""
2
+
3
+ from __future__ import annotations
4
+
5
+ __all__: list[str] = []
@@ -19,7 +19,7 @@ PROJECT_DIR: Final = Path(__file__).resolve().parents[2]
19
19
 
20
20
  kernel: Final = Kernel(
21
21
  "${app}",
22
- # The bundles are read from ${app}.bundles.BUNDLES; the environment from APP_ENV.
22
+ # The bundles are read from ${app}.config.bundles.BUNDLES; the environment from APP_ENV.
23
23
  allowed_envs=("dev", "test", "prod"),
24
24
  # ${app}.web.app builds the web application as it is imported, and that application is
25
25
  # served from this very kernel: scanning it would import it while the kernel builds.
@@ -28,7 +28,8 @@ dev = ["xtr-recipes", "pytest", "httpx", "ruff", "basedpyright", "ty"]
28
28
  "src/${app}/command/__init__.py" = "files/app/command/__init__.py.tmpl"
29
29
  "src/${app}/command/hello_command.py" = "files/app/command/hello_command.py.tmpl"
30
30
  "src/${app}/config/__init__.py" = "files/app/config/__init__.py.tmpl"
31
- "src/${app}/config/http_kernel.py" = "files/app/config/http_kernel.py.tmpl"
31
+ "src/${app}/config/packages/__init__.py" = "files/app/config/packages/__init__.py.tmpl"
32
+ "src/${app}/config/packages/http_kernel.py" = "files/app/config/packages/http_kernel.py.tmpl"
32
33
  "src/${app}/web/__init__.py" = "files/app/web/__init__.py.tmpl"
33
34
  "src/${app}/web/__main__.py" = "files/app/web/__main__.py.tmpl"
34
35
  "src/${app}/web/app.py" = "files/app/web/app.py.tmpl"
@@ -1,5 +0,0 @@
1
- """The application's bundle configuration: one ``@configure`` function per bundle it changes."""
2
-
3
- from __future__ import annotations
4
-
5
- __all__: list[str] = []
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes