pachifast 0.15.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 (198) hide show
  1. pachifast-0.15.0/.gitignore +17 -0
  2. pachifast-0.15.0/CHANGELOG.md +25 -0
  3. pachifast-0.15.0/LICENSE +21 -0
  4. pachifast-0.15.0/PKG-INFO +158 -0
  5. pachifast-0.15.0/README.it.md +95 -0
  6. pachifast-0.15.0/README.md +103 -0
  7. pachifast-0.15.0/examples/demo/.env.example +3 -0
  8. pachifast-0.15.0/examples/demo/.gitignore +12 -0
  9. pachifast-0.15.0/examples/demo/README.md +36 -0
  10. pachifast-0.15.0/examples/demo/apps/__init__.py +0 -0
  11. pachifast-0.15.0/examples/demo/apps/demo/__init__.py +0 -0
  12. pachifast-0.15.0/examples/demo/apps/demo/admin.py +42 -0
  13. pachifast-0.15.0/examples/demo/apps/demo/data.py +62 -0
  14. pachifast-0.15.0/examples/demo/apps/demo/files.py +116 -0
  15. pachifast-0.15.0/examples/demo/apps/demo/items.py +137 -0
  16. pachifast-0.15.0/examples/demo/apps/demo/lab.py +110 -0
  17. pachifast-0.15.0/examples/demo/apps/demo/locale/__init__.py +0 -0
  18. pachifast-0.15.0/examples/demo/apps/demo/locale/en.py +20 -0
  19. pachifast-0.15.0/examples/demo/apps/demo/locale/it.py +20 -0
  20. pachifast-0.15.0/examples/demo/apps/demo/lookups.py +38 -0
  21. pachifast-0.15.0/examples/demo/apps/demo/models.py +41 -0
  22. pachifast-0.15.0/examples/demo/apps/demo/module.py +18 -0
  23. pachifast-0.15.0/examples/demo/apps/demo/seed.py +39 -0
  24. pachifast-0.15.0/examples/demo/apps/demo/settings.py +32 -0
  25. pachifast-0.15.0/examples/demo/apps/demo/user_settings.py +16 -0
  26. pachifast-0.15.0/examples/demo/common/__init__.py +0 -0
  27. pachifast-0.15.0/examples/demo/main.py +11 -0
  28. pachifast-0.15.0/examples/demo/migrations/auth/env.py +11 -0
  29. pachifast-0.15.0/examples/demo/migrations/auth/script.py.mako +20 -0
  30. pachifast-0.15.0/examples/demo/migrations/auth/versions/.gitkeep +0 -0
  31. pachifast-0.15.0/examples/demo/migrations/auth/versions/5b4eb75fc01a_init.py +88 -0
  32. pachifast-0.15.0/examples/demo/migrations/auth/versions/762aa2acf6e7_foreign_keys_of_the_association_tables.py +55 -0
  33. pachifast-0.15.0/examples/demo/migrations/auth/versions/90c0a092913c_totp_last_step.py +28 -0
  34. pachifast-0.15.0/examples/demo/migrations/auth/versions/92c7372f20a8_activity_log_and_mfa_tables.py +69 -0
  35. pachifast-0.15.0/examples/demo/migrations/auth/versions/c41d7e2a9b10_totp_secret_encrypted.py +26 -0
  36. pachifast-0.15.0/examples/demo/migrations/auth/versions/e48e7d24fc99_refresh_tokens.py +43 -0
  37. pachifast-0.15.0/examples/demo/migrations/auth/versions/e7d9031f255a_ws_tickets.py +32 -0
  38. pachifast-0.15.0/examples/demo/migrations/demo/env.py +11 -0
  39. pachifast-0.15.0/examples/demo/migrations/demo/script.py.mako +20 -0
  40. pachifast-0.15.0/examples/demo/migrations/demo/versions/.gitkeep +0 -0
  41. pachifast-0.15.0/examples/demo/migrations/demo/versions/fe109b1b386b_demo_tables.py +53 -0
  42. pachifast-0.15.0/examples/demo/pachifast.schema.json +450 -0
  43. pachifast-0.15.0/examples/demo/pachifast.yaml +6 -0
  44. pachifast-0.15.0/examples/demo/project_modules.py +12 -0
  45. pachifast-0.15.0/examples/demo/pyproject.toml +13 -0
  46. pachifast-0.15.0/pyproject.toml +109 -0
  47. pachifast-0.15.0/src/pachifast/__init__.py +13 -0
  48. pachifast-0.15.0/src/pachifast/admin/__init__.py +28 -0
  49. pachifast-0.15.0/src/pachifast/admin/fields.py +293 -0
  50. pachifast-0.15.0/src/pachifast/admin/generic.py +436 -0
  51. pachifast-0.15.0/src/pachifast/admin/history.py +43 -0
  52. pachifast-0.15.0/src/pachifast/admin/models.py +35 -0
  53. pachifast-0.15.0/src/pachifast/admin/permissions.py +157 -0
  54. pachifast-0.15.0/src/pachifast/admin/permissions_sync.py +58 -0
  55. pachifast-0.15.0/src/pachifast/admin/registry.py +178 -0
  56. pachifast-0.15.0/src/pachifast/admin/schema.py +196 -0
  57. pachifast-0.15.0/src/pachifast/admin/schemas.py +18 -0
  58. pachifast-0.15.0/src/pachifast/admin/user.py +116 -0
  59. pachifast-0.15.0/src/pachifast/app_factory.py +187 -0
  60. pachifast-0.15.0/src/pachifast/audit/__init__.py +0 -0
  61. pachifast-0.15.0/src/pachifast/audit/middleware.py +207 -0
  62. pachifast-0.15.0/src/pachifast/audit/models.py +33 -0
  63. pachifast-0.15.0/src/pachifast/audit/root.py +128 -0
  64. pachifast-0.15.0/src/pachifast/auth/__init__.py +1 -0
  65. pachifast-0.15.0/src/pachifast/auth/cruds.py +507 -0
  66. pachifast-0.15.0/src/pachifast/auth/dependencies.py +240 -0
  67. pachifast-0.15.0/src/pachifast/auth/labels.py +73 -0
  68. pachifast-0.15.0/src/pachifast/auth/models.py +142 -0
  69. pachifast-0.15.0/src/pachifast/auth/permission_provider.py +43 -0
  70. pachifast-0.15.0/src/pachifast/auth/profile.py +116 -0
  71. pachifast-0.15.0/src/pachifast/auth/root.py +173 -0
  72. pachifast-0.15.0/src/pachifast/auth/schemas.py +146 -0
  73. pachifast-0.15.0/src/pachifast/auth/security.py +474 -0
  74. pachifast-0.15.0/src/pachifast/auth/user.py +157 -0
  75. pachifast-0.15.0/src/pachifast/auth/user_settings.py +0 -0
  76. pachifast-0.15.0/src/pachifast/auth/user_settings_discover.py +491 -0
  77. pachifast-0.15.0/src/pachifast/cache/__init__.py +8 -0
  78. pachifast-0.15.0/src/pachifast/cache/base.py +35 -0
  79. pachifast-0.15.0/src/pachifast/cache/factory.py +27 -0
  80. pachifast-0.15.0/src/pachifast/cache/memory.py +70 -0
  81. pachifast-0.15.0/src/pachifast/cache/redis_backend.py +59 -0
  82. pachifast-0.15.0/src/pachifast/cli/__init__.py +5 -0
  83. pachifast-0.15.0/src/pachifast/cli/app.py +51 -0
  84. pachifast-0.15.0/src/pachifast/cli/commands/__init__.py +1 -0
  85. pachifast-0.15.0/src/pachifast/cli/commands/audit.py +29 -0
  86. pachifast-0.15.0/src/pachifast/cli/commands/completion.py +5 -0
  87. pachifast-0.15.0/src/pachifast/cli/commands/config.py +30 -0
  88. pachifast-0.15.0/src/pachifast/cli/commands/dev.py +20 -0
  89. pachifast-0.15.0/src/pachifast/cli/commands/init.py +56 -0
  90. pachifast-0.15.0/src/pachifast/cli/commands/locale.py +201 -0
  91. pachifast-0.15.0/src/pachifast/cli/commands/migrations.py +87 -0
  92. pachifast-0.15.0/src/pachifast/cli/commands/new.py +298 -0
  93. pachifast-0.15.0/src/pachifast/cli/commands/serve.py +51 -0
  94. pachifast-0.15.0/src/pachifast/cli/commands/users.py +137 -0
  95. pachifast-0.15.0/src/pachifast/cli/helpers/__init__.py +21 -0
  96. pachifast-0.15.0/src/pachifast/cli/helpers/console.py +32 -0
  97. pachifast-0.15.0/src/pachifast/cli/helpers/git.py +72 -0
  98. pachifast-0.15.0/src/pachifast/cli/helpers/project.py +55 -0
  99. pachifast-0.15.0/src/pachifast/cli/helpers/prompt.py +18 -0
  100. pachifast-0.15.0/src/pachifast/cli/helpers/version.py +11 -0
  101. pachifast-0.15.0/src/pachifast/cli/services/__init__.py +1 -0
  102. pachifast-0.15.0/src/pachifast/cli/services/audit.py +46 -0
  103. pachifast-0.15.0/src/pachifast/cli/services/dev.py +75 -0
  104. pachifast-0.15.0/src/pachifast/cli/services/init.py +239 -0
  105. pachifast-0.15.0/src/pachifast/cli/services/locale.py +117 -0
  106. pachifast-0.15.0/src/pachifast/cli/services/serve.py +85 -0
  107. pachifast-0.15.0/src/pachifast/cli/services/users.py +264 -0
  108. pachifast-0.15.0/src/pachifast/config/__init__.py +19 -0
  109. pachifast-0.15.0/src/pachifast/config/helpers.py +26 -0
  110. pachifast-0.15.0/src/pachifast/config/schema.py +126 -0
  111. pachifast-0.15.0/src/pachifast/config/settings.py +307 -0
  112. pachifast-0.15.0/src/pachifast/config/settings_discovery.py +44 -0
  113. pachifast-0.15.0/src/pachifast/config/yaml_source.py +92 -0
  114. pachifast-0.15.0/src/pachifast/database/__init__.py +55 -0
  115. pachifast-0.15.0/src/pachifast/database/aliased_models.py +5 -0
  116. pachifast-0.15.0/src/pachifast/database/base.py +23 -0
  117. pachifast-0.15.0/src/pachifast/database/encrypted.py +79 -0
  118. pachifast-0.15.0/src/pachifast/database/engine.py +198 -0
  119. pachifast-0.15.0/src/pachifast/database/helpers.py +80 -0
  120. pachifast-0.15.0/src/pachifast/database/model_discovery.py +53 -0
  121. pachifast-0.15.0/src/pachifast/database/pagination.py +137 -0
  122. pachifast-0.15.0/src/pachifast/database/sync.py +76 -0
  123. pachifast-0.15.0/src/pachifast/database/types.py +11 -0
  124. pachifast-0.15.0/src/pachifast/database/utils.py +51 -0
  125. pachifast-0.15.0/src/pachifast/dependencies.py +31 -0
  126. pachifast-0.15.0/src/pachifast/errors.py +87 -0
  127. pachifast-0.15.0/src/pachifast/events/__init__.py +3 -0
  128. pachifast-0.15.0/src/pachifast/events/broadcaster.py +137 -0
  129. pachifast-0.15.0/src/pachifast/events/models.py +26 -0
  130. pachifast-0.15.0/src/pachifast/events/root.py +224 -0
  131. pachifast-0.15.0/src/pachifast/events/tickets.py +94 -0
  132. pachifast-0.15.0/src/pachifast/health/__init__.py +0 -0
  133. pachifast-0.15.0/src/pachifast/health/health.py +70 -0
  134. pachifast-0.15.0/src/pachifast/health/schemas.py +12 -0
  135. pachifast-0.15.0/src/pachifast/i18n/__init__.py +29 -0
  136. pachifast-0.15.0/src/pachifast/i18n/catalogs.py +40 -0
  137. pachifast-0.15.0/src/pachifast/i18n/exporter.py +156 -0
  138. pachifast-0.15.0/src/pachifast/i18n/loader.py +202 -0
  139. pachifast-0.15.0/src/pachifast/i18n/locale/__init__.py +1 -0
  140. pachifast-0.15.0/src/pachifast/i18n/locale/en.py +94 -0
  141. pachifast-0.15.0/src/pachifast/i18n/locale/it.py +94 -0
  142. pachifast-0.15.0/src/pachifast/i18n/middleware.py +30 -0
  143. pachifast-0.15.0/src/pachifast/i18n/translator.py +156 -0
  144. pachifast-0.15.0/src/pachifast/infos/__init__.py +1 -0
  145. pachifast-0.15.0/src/pachifast/infos/engine/__init__.py +4 -0
  146. pachifast-0.15.0/src/pachifast/infos/engine/engine_helper.py +58 -0
  147. pachifast-0.15.0/src/pachifast/infos/engine/schemas.py +17 -0
  148. pachifast-0.15.0/src/pachifast/infos/root.py +16 -0
  149. pachifast-0.15.0/src/pachifast/logging/__init__.py +0 -0
  150. pachifast-0.15.0/src/pachifast/logging/customformatter.py +31 -0
  151. pachifast-0.15.0/src/pachifast/logging/jsonformatter.py +22 -0
  152. pachifast-0.15.0/src/pachifast/logging/request_id.py +61 -0
  153. pachifast-0.15.0/src/pachifast/mfa/__init__.py +47 -0
  154. pachifast-0.15.0/src/pachifast/mfa/cruds.py +210 -0
  155. pachifast-0.15.0/src/pachifast/mfa/models.py +54 -0
  156. pachifast-0.15.0/src/pachifast/mfa/root.py +435 -0
  157. pachifast-0.15.0/src/pachifast/mfa/schemas.py +89 -0
  158. pachifast-0.15.0/src/pachifast/mfa/security.py +218 -0
  159. pachifast-0.15.0/src/pachifast/mfa/sender.py +58 -0
  160. pachifast-0.15.0/src/pachifast/migrations/__init__.py +21 -0
  161. pachifast-0.15.0/src/pachifast/migrations/manager.py +165 -0
  162. pachifast-0.15.0/src/pachifast/migrations/runtime.py +285 -0
  163. pachifast-0.15.0/src/pachifast/module.py +30 -0
  164. pachifast-0.15.0/src/pachifast/modules.py +276 -0
  165. pachifast-0.15.0/src/pachifast/openapi/__init__.py +1 -0
  166. pachifast-0.15.0/src/pachifast/openapi/openapi_setup.py +162 -0
  167. pachifast-0.15.0/src/pachifast/presets.py +5 -0
  168. pachifast-0.15.0/src/pachifast/py.typed +0 -0
  169. pachifast-0.15.0/src/pachifast/ratelimit.py +61 -0
  170. pachifast-0.15.0/src/pachifast/router_factory.py +5 -0
  171. pachifast-0.15.0/src/pachifast/routing/__init__.py +0 -0
  172. pachifast-0.15.0/src/pachifast/routing/auto_response_router.py +16 -0
  173. pachifast-0.15.0/src/pachifast/routing/core_filters.py +160 -0
  174. pachifast-0.15.0/src/pachifast/routing/discover.py +46 -0
  175. pachifast-0.15.0/src/pachifast/routing/envelope_route.py +73 -0
  176. pachifast-0.15.0/src/pachifast/routing/file_discover.py +44 -0
  177. pachifast-0.15.0/src/pachifast/routing/permissioned_router.py +238 -0
  178. pachifast-0.15.0/src/pachifast/routing/router_factory.py +81 -0
  179. pachifast-0.15.0/src/pachifast/scaffold/__init__.py +21 -0
  180. pachifast-0.15.0/src/pachifast/scaffold/generators.py +262 -0
  181. pachifast-0.15.0/src/pachifast/scaffold/helpers.py +35 -0
  182. pachifast-0.15.0/src/pachifast/scaffold/metadata.py +132 -0
  183. pachifast-0.15.0/src/pachifast/scaffold/pipelines.py +365 -0
  184. pachifast-0.15.0/src/pachifast/scaffold/templates.py +309 -0
  185. pachifast-0.15.0/src/pachifast/schemas/__init__.py +1 -0
  186. pachifast-0.15.0/src/pachifast/schemas/aliased.py +16 -0
  187. pachifast-0.15.0/src/pachifast/schemas/responses.py +123 -0
  188. pachifast-0.15.0/src/pachifast/signals.py +85 -0
  189. pachifast-0.15.0/src/pachifast/startup.py +41 -0
  190. pachifast-0.15.0/src/pachifast/udp/__init__.py +13 -0
  191. pachifast-0.15.0/src/pachifast/udp/protocol.py +49 -0
  192. pachifast-0.15.0/src/pachifast/udp/registry.py +98 -0
  193. pachifast-0.15.0/src/pachifast/utils/__init__.py +3 -0
  194. pachifast-0.15.0/src/pachifast/utils/commands.py +48 -0
  195. pachifast-0.15.0/src/pachifast/utils/helpers.py +44 -0
  196. pachifast-0.15.0/src/pachifast/utils/tasks.py +21 -0
  197. pachifast-0.15.0/src/pachifast/version/__init__.py +1 -0
  198. pachifast-0.15.0/src/pachifast/version/root.py +13 -0
@@ -0,0 +1,17 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.pyc
4
+ dist/
5
+ site/
6
+ .coverage
7
+ *.egg-info/
8
+ .env
9
+ *.env
10
+ .pytest_cache/
11
+ .ruff_cache/
12
+ *.db
13
+ *.sqlite3
14
+ .idea/
15
+ .vscode/
16
+ .DS_Store
17
+ uploads/
@@ -0,0 +1,25 @@
1
+ # Changelog
2
+
3
+ All notable changes to pachifast are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses [semantic versioning](https://semver.org/)
5
+ (while the major version is 0, minor releases may contain breaking changes).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.15.0] - 2026-10-14
10
+
11
+ First public release. pachifast is alpha software: see [Stability and support](https://pachifast.ilpachi.it/guides/stability/).
12
+
13
+ ### Added
14
+
15
+ - **Application factory and modules**: `create_app`, an explicit module registry (`project_modules.py`) and `AppModule`, with routers, settings, migrations, startup and setup hooks, message catalogs, and `requires_pachifast` to declare the pachifast versions a module works with.
16
+ - **Authentication and authorization**: JWT access and refresh tokens, Argon2id passwords, login lockout and rate limiting, users, groups and permissions, a pluggable permission provider, optional MFA (TOTP, email and SMS codes), per-user settings with a UI schema, and a one-to-one user profile for your own columns (`register_profile`).
17
+ - **A uniform API contract**: the response envelope `{success, message, data}`, errors as `{"detail": [{loc, msg, type, code, params?}]}` with stable message codes, camelCase JSON and built-in pagination.
18
+ - **Localized messages**: catalogs per module and per project, and an exporter that produces the JSON files a vue-i18n frontend needs, with a check-only mode for CI.
19
+ - **Generic model admin**, an **activity log** with an index and a retention command (`pachifast audit purge`), lifecycle **signals** (`pachifast.signals`), and live **events** over an authenticated WebSocket with one-time tickets.
20
+ - **Database and migrations**: SQLAlchemy 2.0 with SQLite and PostgreSQL, one Alembic target per database declared by the modules, and a configurable connection pool (`db_pool_*`).
21
+ - **Operations**: `serve` for production, health endpoints (`/`, `/live`, `/ready`), request ids, JSON logs, an optional Redis cache, UDP listeners, and a generated Dockerfile and CI/CD pipelines for GitHub, GitLab and Gitea.
22
+ - **Scaffolding CLI**: `pachifast new` for projects, modules and pipelines, plus commands for migrations, users, settings, i18n and the audit log.
23
+ - **Configuration**: environment variables, `.env` and a `pachifast.yaml` with a JSON Schema.
24
+ - **Extensions**: separate packages named `pachifast-<name>` that export an `AppModule` (for example `pachifast-metrics`).
25
+ - Documentation site with generated reference pages for the CLI, the settings and the message codes.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ilPachi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,158 @@
1
+ Metadata-Version: 2.5
2
+ Name: pachifast
3
+ Version: 0.15.0
4
+ Summary: Modular FastAPI core and scaffolding CLI: projects, apps, auth, migrations.
5
+ Project-URL: Homepage, https://pachifast.ilpachi.it/
6
+ Project-URL: Documentation, https://pachifast.ilpachi.it/
7
+ Project-URL: Repository, https://github.com/ellethee/pachifast
8
+ Project-URL: Source, https://github.com/ellethee/pachifast
9
+ Project-URL: Issues, https://github.com/ellethee/pachifast/issues
10
+ Project-URL: Changelog, https://github.com/ellethee/pachifast/blob/main/CHANGELOG.md
11
+ Author: ilPachi
12
+ Maintainer: ilPachi
13
+ License-Expression: MIT
14
+ License-File: LICENSE
15
+ Keywords: alembic,cli,fastapi,framework,scaffolding,sqlalchemy
16
+ Classifier: Development Status :: 3 - Alpha
17
+ Classifier: Environment :: Web Environment
18
+ Classifier: Framework :: FastAPI
19
+ Classifier: Intended Audience :: Developers
20
+ Classifier: Operating System :: OS Independent
21
+ Classifier: Programming Language :: Python :: 3
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Programming Language :: Python :: 3.14
26
+ Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
27
+ Classifier: Topic :: Software Development :: Code Generators
28
+ Classifier: Typing :: Typed
29
+ Requires-Python: >=3.11
30
+ Requires-Dist: aiosqlite>=0.20.0
31
+ Requires-Dist: alembic<2.0.0,>=1.14.1
32
+ Requires-Dist: cryptography>=43.0.0
33
+ Requires-Dist: fastapi-pagination<1.0.0,>=0.13.0
34
+ Requires-Dist: fastapi[standard]<1.0.0,>=0.133.0
35
+ Requires-Dist: packaging>=23.0
36
+ Requires-Dist: pwdlib[argon2]>=0.2.1
37
+ Requires-Dist: pydantic-settings<3.0.0,>=2.7.1
38
+ Requires-Dist: pydantic<3.0.0,>=2.11.0
39
+ Requires-Dist: pyjwt<3.0.0,>=2.15.0
40
+ Requires-Dist: pyotp<3.0.0,>=2.9.0
41
+ Requires-Dist: python-multipart>=0.0.31
42
+ Requires-Dist: pyyaml>=6.0
43
+ Requires-Dist: rich>=13.0.0
44
+ Requires-Dist: sqlalchemy[asyncio]<3.0.0,>=2.0.40
45
+ Requires-Dist: starlette<2.0.0,>=1.3.1
46
+ Requires-Dist: typer<1.0.0,>=0.15.0
47
+ Requires-Dist: uvicorn<1.0.0,>=0.34.0
48
+ Provides-Extra: postgres
49
+ Requires-Dist: asyncpg<0.32.0,>=0.30.0; extra == 'postgres'
50
+ Provides-Extra: postgres-sync
51
+ Requires-Dist: psycopg[binary]>=3.2; extra == 'postgres-sync'
52
+ Provides-Extra: redis
53
+ Requires-Dist: redis>=5.0.0; extra == 'redis'
54
+ Description-Content-Type: text/markdown
55
+
56
+ <p align="center"><img src="https://raw.githubusercontent.com/ellethee/pachifast/main/docs/assets/logo.svg" alt="pachifast" width="160"></p>
57
+
58
+ # pachifast
59
+
60
+ [Italiano](https://github.com/ellethee/pachifast/blob/main/README.it.md)
61
+
62
+ An open-source framework for building [FastAPI](https://fastapi.tiangolo.com/) services with a modular structure, a CLI
63
+ that scaffolds projects and modules, built-in authentication with roles and permissions, and multi-database Alembic
64
+ migrations.
65
+
66
+ Version: **<!-- version -->0.15.0<!-- /version -->** - Author: **ilPachi** - License: **MIT** - Status: **alpha** (0.x: minor releases may contain breaking changes).
67
+
68
+ ## Features
69
+
70
+ - **Modular by design**: an explicit registry of modules (`project_modules.py`), `apps/` for application modules and
71
+ `common/` for shared ones; each module brings its routers, settings, migrations, hooks and message catalogs.
72
+ - **Authentication and authorization**: JWT access and refresh tokens, Argon2id passwords, login lockout, users, groups
73
+ and permissions, optional MFA (TOTP, email and SMS codes), per-user settings with a UI schema.
74
+ - **A uniform API contract**: every success is `{success, message, data}`, every error is a non-2xx response with
75
+ `{"detail": [{loc, msg, type, code, params?}]}` and a stable `code`; camelCase JSON; pagination built in.
76
+ - **Localized messages**: stable message codes, catalogs per module and per project, and an exporter that produces the
77
+ JSON files a vue-i18n frontend needs (with a check-only mode for CI).
78
+ - **Live events**: an authenticated WebSocket with one-time tickets, an activity log, and automatic disconnection of
79
+ users who are deleted, deactivated or demoted.
80
+ - **Migrations**: one Alembic target per database declared by the modules.
81
+ - **Operations**: `serve` for production, generated Dockerfile and CI/CD pipelines (GitHub, GitLab, Gitea), health and
82
+ version endpoints, optional Redis cache.
83
+ - **Editor-friendly configuration**: environment variables, `.env` and a `pachifast.yaml` with a JSON Schema.
84
+
85
+ ## Install
86
+
87
+ Python 3.11 or later and [uv](https://docs.astral.sh/uv/) are required:
88
+
89
+ ```bash
90
+ uv tool install pachifast
91
+ pachifast --version
92
+ ```
93
+
94
+ In a project, `uv add pachifast` does the same. To install a specific version from PyPI (replace `X.Y.Z`):
95
+
96
+ ```bash
97
+ uv tool install pachifast==X.Y.Z
98
+ ```
99
+
100
+ Redis cache support is an extra: `pachifast[redis]`; PostgreSQL is `pachifast[postgres]`. Supported databases: SQLite and
101
+ PostgreSQL. See [Getting started](https://pachifast.ilpachi.it/getting-started/) for more installation options.
102
+
103
+ ## Stability
104
+
105
+ pachifast is **alpha**: the API contract (response envelope, message codes) is protected by tests, but settings, CLI and
106
+ the database schema of the core may change in any 0.x minor release, always announced in the [changelog](https://github.com/ellethee/pachifast/blob/main/CHANGELOG.md)
107
+ and in [Upgrading](https://pachifast.ilpachi.it/guides/upgrading/). Details and the deprecation policy: [Stability](https://pachifast.ilpachi.it/guides/stability/).
108
+
109
+ ## Quick start
110
+
111
+ ```bash
112
+ pachifast new project demo && cd demo # scaffold a project
113
+ pachifast new app hello # add an application module
114
+ pachifast init # .env with a secret key, SQLite database, migrations, first superuser
115
+ pachifast dev # run with auto-reload
116
+ ```
117
+
118
+ Then open <http://127.0.0.1:8000/docs> (application endpoints) or <http://127.0.0.1:8000/docs/core> (authentication,
119
+ administration, health, version). Application routes require a bearer token by default: log in at
120
+ `POST /api/auth/token`.
121
+
122
+ Want to see a complete project first? [`examples/demo`](https://github.com/ellethee/pachifast/tree/main/examples/demo) is a working backend (MFA, model admin, a module with
123
+ tables, uploads, bulk actions and per-user settings) that runs on SQLite with no external services.
124
+
125
+ A project looks like this:
126
+
127
+ ```text
128
+ demo/
129
+ apps/ # application modules
130
+ common/ # shared modules
131
+ main.py # the ASGI app
132
+ project_modules.py
133
+ pachifast.yaml # optional configuration (with a JSON Schema for editors)
134
+ pyproject.toml
135
+ ```
136
+
137
+ ## Documentation
138
+
139
+ The documentation is published at <https://pachifast.ilpachi.it/> and lives in [`docs/`](https://github.com/ellethee/pachifast/tree/main/docs):
140
+
141
+ - [Getting started](https://pachifast.ilpachi.it/getting-started/)
142
+ - Guides: [configuration](https://pachifast.ilpachi.it/guides/configuration/), [modules](https://pachifast.ilpachi.it/guides/modules/),
143
+ [authentication](https://pachifast.ilpachi.it/guides/authentication/), [routing and responses](https://pachifast.ilpachi.it/guides/routing-and-responses/),
144
+ [errors and i18n](https://pachifast.ilpachi.it/guides/errors-and-i18n/), [events](https://pachifast.ilpachi.it/guides/events/), [cache](https://pachifast.ilpachi.it/guides/cache/),
145
+ [database and migrations](https://pachifast.ilpachi.it/guides/database-and-migrations/), [operations](https://pachifast.ilpachi.it/guides/operations/),
146
+ [deployment](https://pachifast.ilpachi.it/guides/deployment/), [publishing](https://pachifast.ilpachi.it/guides/publishing/),
147
+ [frontend integration](https://pachifast.ilpachi.it/guides/frontend-integration/)
148
+ - Reference: [CLI](https://pachifast.ilpachi.it/reference/cli/), [settings](https://pachifast.ilpachi.it/reference/settings/),
149
+ [message codes](https://pachifast.ilpachi.it/reference/error-codes/)
150
+ - [Changelog](https://github.com/ellethee/pachifast/blob/main/CHANGELOG.md) and [contributing](https://pachifast.ilpachi.it/contributing/)
151
+
152
+ ## License
153
+
154
+ MIT, see [LICENSE](https://github.com/ellethee/pachifast/blob/main/LICENSE).
155
+
156
+ **Disclaimer.** pachifast is provided "as is", without warranty of any kind. It is alpha software: it can contain bugs
157
+ and change incompatibly between minor releases. You are responsible for reviewing, testing and securing the
158
+ applications you build with it before using them in production. See the [stability policy](https://pachifast.ilpachi.it/guides/stability/).
@@ -0,0 +1,95 @@
1
+ <p align="center"><img src="https://raw.githubusercontent.com/ellethee/pachifast/main/docs/assets/logo.svg" alt="pachifast" width="160"></p>
2
+
3
+ # pachifast
4
+
5
+ [English](https://github.com/ellethee/pachifast/blob/main/README.md)
6
+
7
+ Framework open source per costruire servizi [FastAPI](https://fastapi.tiangolo.com/) con una struttura modulare, una CLI
8
+ che genera progetti e moduli, autenticazione integrata con ruoli e permessi e migrazioni Alembic su più database.
9
+
10
+ Versione: **<!-- version -->0.15.0<!-- /version -->** - Autore: **ilPachi** - Licenza: **MIT** - Stato: **alpha** (0.x: le versioni minori possono contenere modifiche incompatibili).
11
+
12
+ ## Cosa offre
13
+
14
+ - **Modulare**: registro esplicito dei moduli (`project_modules.py`), `apps/` per i moduli applicativi e `common/` per
15
+ quelli condivisi; ogni modulo porta router, impostazioni, migrazioni, hook e cataloghi di messaggi.
16
+ - **Autenticazione e autorizzazione**: token JWT di accesso e refresh, password Argon2id, blocco dopo tentativi falliti,
17
+ utenti, gruppi e permessi, MFA opzionale (TOTP, codici via email e SMS), impostazioni per utente con schema UI.
18
+ - **Un contratto API uniforme**: ogni successo è `{success, message, data}`, ogni errore è una risposta non-2xx con
19
+ `{"detail": [{loc, msg, type, code, params?}]}` e un `code` stabile; JSON in camelCase; paginazione integrata.
20
+ - **Messaggi localizzati**: codici stabili, cataloghi per modulo e per progetto, ed esportazione dei file JSON per un
21
+ frontend vue-i18n (con modalità di sola verifica per la CI).
22
+ - **Eventi in tempo reale**: WebSocket autenticato con ticket monouso, activity log e disconnessione automatica degli
23
+ utenti eliminati, disattivati o declassati.
24
+ - **Migrazioni**: un target Alembic per ogni database dichiarato dai moduli.
25
+ - **Operatività**: `serve` per la produzione, Dockerfile e pipeline CI/CD generati (GitHub, GitLab, Gitea), endpoint di
26
+ health e versione, cache Redis opzionale.
27
+ - **Configurazione comoda da editor**: variabili d'ambiente, `.env` e un `pachifast.yaml` con JSON Schema.
28
+
29
+ ## Installazione
30
+
31
+ Servono Python 3.11 o successivo e [uv](https://docs.astral.sh/uv/):
32
+
33
+ ```bash
34
+ uv tool install pachifast
35
+ pachifast --version
36
+ ```
37
+
38
+ In un progetto, `uv add pachifast` fa lo stesso. Per installare una versione specifica da PyPI (sostituisci `X.Y.Z`):
39
+
40
+ ```bash
41
+ uv tool install pachifast==X.Y.Z
42
+ ```
43
+
44
+ La cache Redis è un extra: `pachifast[redis]`; PostgreSQL è `pachifast[postgres]`. Database supportati: SQLite e
45
+ PostgreSQL. Per altre opzioni di installazione vedi [Getting started](https://pachifast.ilpachi.it/getting-started/)
46
+ (in inglese).
47
+
48
+ ## Stabilità
49
+
50
+ pachifast è in **alpha**: il contratto dell'API (envelope di risposta, codici dei messaggi) è protetto da test, ma
51
+ impostazioni, CLI e schema del database del core possono cambiare in ogni versione minore 0.x, sempre annunciate nel
52
+ [changelog](https://github.com/ellethee/pachifast/blob/main/CHANGELOG.md) e in [Upgrading](https://pachifast.ilpachi.it/guides/upgrading/). Dettagli e politica di deprecazione:
53
+ [Stability](https://pachifast.ilpachi.it/guides/stability/) (in inglese).
54
+
55
+ ## Avvio rapido
56
+
57
+ ```bash
58
+ pachifast new project demo && cd demo # crea un progetto
59
+ pachifast new app hello # aggiunge un modulo applicativo
60
+ pachifast init # .env con chiave segreta, database SQLite, migrazioni, primo superuser
61
+ pachifast dev # avvio con ricarica automatica
62
+ ```
63
+
64
+ Poi apri <http://127.0.0.1:8000/docs> (endpoint dell'applicazione) o <http://127.0.0.1:8000/docs/core> (autenticazione,
65
+ amministrazione, health, versione). Le rotte dell'applicazione richiedono un token: accedi con `POST /api/auth/token`.
66
+
67
+ Vuoi vedere prima un progetto completo? [`examples/demo`](https://github.com/ellethee/pachifast/tree/main/examples/demo) è un backend funzionante (MFA, model admin, un modulo con
68
+ tabelle, upload, azioni di massa e impostazioni per utente) che gira su SQLite, senza servizi esterni.
69
+
70
+ Un progetto ha questa struttura:
71
+
72
+ ```text
73
+ demo/
74
+ apps/ # moduli applicativi
75
+ common/ # moduli condivisi
76
+ main.py # l'app ASGI
77
+ project_modules.py
78
+ pachifast.yaml # configurazione opzionale (con JSON Schema per gli editor)
79
+ pyproject.toml
80
+ ```
81
+
82
+ ## Documentazione
83
+
84
+ La documentazione completa (in inglese) è pubblicata su <https://pachifast.ilpachi.it/> e si trova in [`docs/`](https://github.com/ellethee/pachifast/tree/main/docs): guida introduttiva, guide per argomento,
85
+ riferimenti generati dal codice (CLI, impostazioni, codici dei messaggi), [changelog](https://github.com/ellethee/pachifast/blob/main/CHANGELOG.md) e
86
+ [contributi](https://pachifast.ilpachi.it/contributing/).
87
+
88
+ ## Licenza
89
+
90
+ MIT, vedi [LICENSE](https://github.com/ellethee/pachifast/blob/main/LICENSE).
91
+
92
+ **Esclusione di garanzia.** pachifast è fornito "così com'è" ("as is"), senza garanzie di alcun tipo. È software alpha:
93
+ può contenere errori e cambiare in modo incompatibile tra versioni minori. Sei responsabile di verificare, testare e
94
+ mettere in sicurezza le applicazioni che costruisci con pachifast prima di usarle in produzione. Vedi la
95
+ [politica di stabilità](https://pachifast.ilpachi.it/guides/stability/).
@@ -0,0 +1,103 @@
1
+ <p align="center"><img src="https://raw.githubusercontent.com/ellethee/pachifast/main/docs/assets/logo.svg" alt="pachifast" width="160"></p>
2
+
3
+ # pachifast
4
+
5
+ [Italiano](https://github.com/ellethee/pachifast/blob/main/README.it.md)
6
+
7
+ An open-source framework for building [FastAPI](https://fastapi.tiangolo.com/) services with a modular structure, a CLI
8
+ that scaffolds projects and modules, built-in authentication with roles and permissions, and multi-database Alembic
9
+ migrations.
10
+
11
+ Version: **<!-- version -->0.15.0<!-- /version -->** - Author: **ilPachi** - License: **MIT** - Status: **alpha** (0.x: minor releases may contain breaking changes).
12
+
13
+ ## Features
14
+
15
+ - **Modular by design**: an explicit registry of modules (`project_modules.py`), `apps/` for application modules and
16
+ `common/` for shared ones; each module brings its routers, settings, migrations, hooks and message catalogs.
17
+ - **Authentication and authorization**: JWT access and refresh tokens, Argon2id passwords, login lockout, users, groups
18
+ and permissions, optional MFA (TOTP, email and SMS codes), per-user settings with a UI schema.
19
+ - **A uniform API contract**: every success is `{success, message, data}`, every error is a non-2xx response with
20
+ `{"detail": [{loc, msg, type, code, params?}]}` and a stable `code`; camelCase JSON; pagination built in.
21
+ - **Localized messages**: stable message codes, catalogs per module and per project, and an exporter that produces the
22
+ JSON files a vue-i18n frontend needs (with a check-only mode for CI).
23
+ - **Live events**: an authenticated WebSocket with one-time tickets, an activity log, and automatic disconnection of
24
+ users who are deleted, deactivated or demoted.
25
+ - **Migrations**: one Alembic target per database declared by the modules.
26
+ - **Operations**: `serve` for production, generated Dockerfile and CI/CD pipelines (GitHub, GitLab, Gitea), health and
27
+ version endpoints, optional Redis cache.
28
+ - **Editor-friendly configuration**: environment variables, `.env` and a `pachifast.yaml` with a JSON Schema.
29
+
30
+ ## Install
31
+
32
+ Python 3.11 or later and [uv](https://docs.astral.sh/uv/) are required:
33
+
34
+ ```bash
35
+ uv tool install pachifast
36
+ pachifast --version
37
+ ```
38
+
39
+ In a project, `uv add pachifast` does the same. To install a specific version from PyPI (replace `X.Y.Z`):
40
+
41
+ ```bash
42
+ uv tool install pachifast==X.Y.Z
43
+ ```
44
+
45
+ Redis cache support is an extra: `pachifast[redis]`; PostgreSQL is `pachifast[postgres]`. Supported databases: SQLite and
46
+ PostgreSQL. See [Getting started](https://pachifast.ilpachi.it/getting-started/) for more installation options.
47
+
48
+ ## Stability
49
+
50
+ pachifast is **alpha**: the API contract (response envelope, message codes) is protected by tests, but settings, CLI and
51
+ the database schema of the core may change in any 0.x minor release, always announced in the [changelog](https://github.com/ellethee/pachifast/blob/main/CHANGELOG.md)
52
+ and in [Upgrading](https://pachifast.ilpachi.it/guides/upgrading/). Details and the deprecation policy: [Stability](https://pachifast.ilpachi.it/guides/stability/).
53
+
54
+ ## Quick start
55
+
56
+ ```bash
57
+ pachifast new project demo && cd demo # scaffold a project
58
+ pachifast new app hello # add an application module
59
+ pachifast init # .env with a secret key, SQLite database, migrations, first superuser
60
+ pachifast dev # run with auto-reload
61
+ ```
62
+
63
+ Then open <http://127.0.0.1:8000/docs> (application endpoints) or <http://127.0.0.1:8000/docs/core> (authentication,
64
+ administration, health, version). Application routes require a bearer token by default: log in at
65
+ `POST /api/auth/token`.
66
+
67
+ Want to see a complete project first? [`examples/demo`](https://github.com/ellethee/pachifast/tree/main/examples/demo) is a working backend (MFA, model admin, a module with
68
+ tables, uploads, bulk actions and per-user settings) that runs on SQLite with no external services.
69
+
70
+ A project looks like this:
71
+
72
+ ```text
73
+ demo/
74
+ apps/ # application modules
75
+ common/ # shared modules
76
+ main.py # the ASGI app
77
+ project_modules.py
78
+ pachifast.yaml # optional configuration (with a JSON Schema for editors)
79
+ pyproject.toml
80
+ ```
81
+
82
+ ## Documentation
83
+
84
+ The documentation is published at <https://pachifast.ilpachi.it/> and lives in [`docs/`](https://github.com/ellethee/pachifast/tree/main/docs):
85
+
86
+ - [Getting started](https://pachifast.ilpachi.it/getting-started/)
87
+ - Guides: [configuration](https://pachifast.ilpachi.it/guides/configuration/), [modules](https://pachifast.ilpachi.it/guides/modules/),
88
+ [authentication](https://pachifast.ilpachi.it/guides/authentication/), [routing and responses](https://pachifast.ilpachi.it/guides/routing-and-responses/),
89
+ [errors and i18n](https://pachifast.ilpachi.it/guides/errors-and-i18n/), [events](https://pachifast.ilpachi.it/guides/events/), [cache](https://pachifast.ilpachi.it/guides/cache/),
90
+ [database and migrations](https://pachifast.ilpachi.it/guides/database-and-migrations/), [operations](https://pachifast.ilpachi.it/guides/operations/),
91
+ [deployment](https://pachifast.ilpachi.it/guides/deployment/), [publishing](https://pachifast.ilpachi.it/guides/publishing/),
92
+ [frontend integration](https://pachifast.ilpachi.it/guides/frontend-integration/)
93
+ - Reference: [CLI](https://pachifast.ilpachi.it/reference/cli/), [settings](https://pachifast.ilpachi.it/reference/settings/),
94
+ [message codes](https://pachifast.ilpachi.it/reference/error-codes/)
95
+ - [Changelog](https://github.com/ellethee/pachifast/blob/main/CHANGELOG.md) and [contributing](https://pachifast.ilpachi.it/contributing/)
96
+
97
+ ## License
98
+
99
+ MIT, see [LICENSE](https://github.com/ellethee/pachifast/blob/main/LICENSE).
100
+
101
+ **Disclaimer.** pachifast is provided "as is", without warranty of any kind. It is alpha software: it can contain bugs
102
+ and change incompatibly between minor releases. You are responsible for reviewing, testing and securing the
103
+ applications you build with it before using them in production. See the [stability policy](https://pachifast.ilpachi.it/guides/stability/).
@@ -0,0 +1,3 @@
1
+ # Secret used to sign tokens. Required: the app refuses to start without it.
2
+ # Generate one with: openssl rand -hex 32
3
+ PACHIFAST_SECRET_KEY=
@@ -0,0 +1,12 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.pyc
4
+ .env
5
+ *.env
6
+ !.env.example
7
+ *.sqlite3
8
+ *.db
9
+ dist/
10
+ .pytest_cache/
11
+ .ruff_cache/
12
+ uploads/
@@ -0,0 +1,36 @@
1
+ # pachifast demo
2
+
3
+ A complete, self-contained backend built on pachifast. It needs no frontend, and no external database: everything runs on SQLite from this folder.
4
+
5
+ It shows:
6
+
7
+ - the core (authentication, users, permissions, refresh tokens), MFA and the generic model admin;
8
+ - an app module (`apps/demo`) with its own tables and migration target, a startup seed, lookups, a paginated and filterable items API with bulk actions, file upload and download, per-user settings and message catalogs in English and Italian.
9
+
10
+ ## Run it
11
+
12
+ From the repository root:
13
+
14
+ ```bash
15
+ cd examples/demo
16
+ uv sync
17
+ uv run pachifast init --username admin --password change-me-please # .env, auth migrations, first superuser
18
+ uv run pachifast migrations upgrade --target-name demo # tables of the demo app
19
+ uv run pachifast dev
20
+ ```
21
+
22
+ Open <http://127.0.0.1:8000/docs> for the API of the demo app and <http://127.0.0.1:8000/docs/core> for the built-in routes. Log in with the superuser you just created:
23
+
24
+ ```bash
25
+ curl -X POST http://127.0.0.1:8000/api/auth/token -d "username=admin" -d "password=change-me-please"
26
+ ```
27
+
28
+ `init` prepares the auth database only; every other migration target (here `demo`) is applied with `migrations upgrade`. Both are safe to run again. The sample records are inserted at startup, only when the table is empty.
29
+
30
+ ## Use a published release
31
+
32
+ The `pyproject.toml` points at the local sources so the demo always matches the repository. To try a released version from PyPI, delete the `[tool.uv.sources]` section; `uv sync` then installs `pachifast` from PyPI.
33
+
34
+ ## A frontend
35
+
36
+ Any frontend that follows the pachifast contract (response envelope, errors, token refresh, server-side tables) works against this backend: see the [frontend integration guide](../../docs/guides/frontend-integration.md).
File without changes
File without changes
@@ -0,0 +1,42 @@
1
+ """Model admin of the demo: the generic CRUD screens for items and files (see the pachifast guide "Model admin")."""
2
+
3
+ from pachifast.admin import ModelAdmin, admin_action, register_admin
4
+
5
+ from .models import DemoFile, DemoItem
6
+
7
+
8
+ @register_admin(DemoItem)
9
+ class ItemAdmin(ModelAdmin):
10
+ """Items: searchable by name and notes, filterable by status, category and active flag."""
11
+
12
+ name = "item"
13
+ title = "Item"
14
+ list_display = ["name", "category", "status", "price", "quantity", "active", "created_at"]
15
+ search_fields = ["name", "notes"]
16
+ list_filter = ["status", "category", "active"]
17
+ readonly_fields = ["created_at"]
18
+ actions = ["archive", "activate"]
19
+
20
+ @admin_action(label="Archive selected")
21
+ async def archive(self, session, rows) -> str:
22
+ """Set the status of the selected items to archived."""
23
+ for row in rows:
24
+ row.status = "archived"
25
+ return f"{len(rows)} archived"
26
+
27
+ @admin_action(label="Activate selected", confirm=False)
28
+ async def activate(self, session, rows) -> str:
29
+ """Set the status of the selected items to active."""
30
+ for row in rows:
31
+ row.status = "active"
32
+ return f"{len(rows)} activated"
33
+
34
+
35
+ @register_admin(DemoFile)
36
+ class FileAdmin(ModelAdmin):
37
+ """Files: metadata only, read-only (the content is managed by the upload routes)."""
38
+
39
+ name = "file"
40
+ title = "File"
41
+ search_fields = ["name"]
42
+ readonly_fields = ["name", "content_type", "size", "created_at"]
@@ -0,0 +1,62 @@
1
+ """Static data of the demo: lookups (countries, cities, categories) and the seed of the sample records."""
2
+
3
+ import random
4
+
5
+ COUNTRIES: list[dict] = [
6
+ {"value": 1, "label": "Italia"},
7
+ {"value": 2, "label": "Francia"},
8
+ {"value": 3, "label": "Germania"},
9
+ {"value": 4, "label": "Spagna"},
10
+ ]
11
+
12
+ CITIES: list[dict] = [
13
+ {"value": 1, "label": "Roma", "countryId": 1},
14
+ {"value": 2, "label": "Milano", "countryId": 1},
15
+ {"value": 3, "label": "Napoli", "countryId": 1},
16
+ {"value": 4, "label": "Parigi", "countryId": 2},
17
+ {"value": 5, "label": "Lione", "countryId": 2},
18
+ {"value": 6, "label": "Berlino", "countryId": 3},
19
+ {"value": 7, "label": "Monaco", "countryId": 3},
20
+ {"value": 8, "label": "Amburgo", "countryId": 3},
21
+ {"value": 9, "label": "Madrid", "countryId": 4},
22
+ {"value": 10, "label": "Barcellona", "countryId": 4},
23
+ ]
24
+
25
+ CATEGORIES: list[dict] = [
26
+ {"value": "tools", "label": "Strumenti"},
27
+ {"value": "books", "label": "Libri"},
28
+ {"value": "toys", "label": "Giochi"},
29
+ {"value": "food", "label": "Alimentari"},
30
+ {"value": "clothes", "label": "Abbigliamento"},
31
+ ]
32
+
33
+ STATUSES: list[dict] = [
34
+ {"value": "draft", "label": "Bozza"},
35
+ {"value": "active", "label": "Attivo"},
36
+ {"value": "archived", "label": "Archiviato"},
37
+ ]
38
+
39
+ _ADJECTIVES = ["Piccolo", "Grande", "Rapido", "Antico", "Moderno", "Verde", "Rosso", "Leggero", "Robusto", "Elegante"]
40
+ _NOUNS = ["martello", "libro", "robot", "pane", "giacca", "puzzle", "cacciavite", "romanzo", "casco", "formaggio"]
41
+
42
+
43
+ def sample_items(count: int = 120) -> list[dict]:
44
+ """``count`` reproducible sample records (fixed seed): same data on every database."""
45
+ rng = random.Random(42)
46
+ items = []
47
+ for number in range(1, count + 1):
48
+ city = rng.choice(CITIES)
49
+ items.append(
50
+ {
51
+ "name": f"{rng.choice(_ADJECTIVES)} {rng.choice(_NOUNS)} {number}",
52
+ "category": rng.choice(CATEGORIES)["value"],
53
+ "status": rng.choice(STATUSES)["value"],
54
+ "price": round(rng.uniform(1, 500), 2),
55
+ "quantity": rng.randint(0, 200),
56
+ "active": rng.random() > 0.2,
57
+ "country_id": city["countryId"],
58
+ "city_id": city["value"],
59
+ "notes": None if rng.random() > 0.3 else f"Nota di prova {number}",
60
+ }
61
+ )
62
+ return items