pz-cli 5.0.0__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 (399) hide show
  1. pz_cli-5.0.0.dist-info/METADATA +51 -0
  2. pz_cli-5.0.0.dist-info/RECORD +399 -0
  3. pz_cli-5.0.0.dist-info/WHEEL +4 -0
  4. pz_cli-5.0.0.dist-info/entry_points.txt +5 -0
  5. pz_core/__init__.py +64 -0
  6. pz_core/__main__.py +7 -0
  7. pz_core/app.py +45 -0
  8. pz_core/assembly/__init__.py +17 -0
  9. pz_core/assembly/app_discovery.py +1240 -0
  10. pz_core/assembly/apps/__init__.py +25 -0
  11. pz_core/assembly/apps/compiler.py +824 -0
  12. pz_core/assembly/apps/providers.py +188 -0
  13. pz_core/assembly/cli/__init__.py +9 -0
  14. pz_core/assembly/cli/compiler.py +166 -0
  15. pz_core/assembly/diagnostics/__init__.py +21 -0
  16. pz_core/assembly/diagnostics/checks.py +257 -0
  17. pz_core/assembly/diagnostics/dev_sources.py +569 -0
  18. pz_core/assembly/events/__init__.py +5 -0
  19. pz_core/assembly/events/compiler.py +219 -0
  20. pz_core/assembly/extensions/__init__.py +5 -0
  21. pz_core/assembly/extensions/compiler.py +696 -0
  22. pz_core/assembly/infra/__init__.py +6 -0
  23. pz_core/assembly/infra/compiler.py +272 -0
  24. pz_core/assembly/lifecycle/__init__.py +5 -0
  25. pz_core/assembly/lifecycle/compiler.py +95 -0
  26. pz_core/assembly/middlewares/__init__.py +19 -0
  27. pz_core/assembly/middlewares/compiler.py +508 -0
  28. pz_core/assembly/project/__init__.py +7 -0
  29. pz_core/assembly/project/compiler.py +9 -0
  30. pz_core/assembly/project/context.py +17 -0
  31. pz_core/assembly/project/discovery.py +227 -0
  32. pz_core/assembly/resources/__init__.py +19 -0
  33. pz_core/assembly/resources/compiler.py +310 -0
  34. pz_core/assembly/resources/settings.py +129 -0
  35. pz_core/assembly/routes/__init__.py +7 -0
  36. pz_core/assembly/routes/compiler.py +400 -0
  37. pz_core/assembly/runtime_manifests/__init__.py +13 -0
  38. pz_core/assembly/runtime_manifests/compiler.py +159 -0
  39. pz_core/assembly/settings/__init__.py +17 -0
  40. pz_core/assembly/settings/compiler.py +786 -0
  41. pz_core/assembly/settings/host_project_overrides.py +82 -0
  42. pz_core/assembly/settings/host_runtime_endpoint.py +207 -0
  43. pz_core/authoring/__init__.py +79 -0
  44. pz_core/authoring/app_init_service.py +946 -0
  45. pz_core/authoring/app_versions.py +814 -0
  46. pz_core/authoring/cli.py +192 -0
  47. pz_core/authoring/commands.py +1810 -0
  48. pz_core/authoring/conflicts.py +180 -0
  49. pz_core/authoring/dev_bindings.py +916 -0
  50. pz_core/authoring/dev_git.py +1087 -0
  51. pz_core/authoring/dev_import.py +1061 -0
  52. pz_core/authoring/dev_manifest.py +522 -0
  53. pz_core/authoring/dev_sources.py +1638 -0
  54. pz_core/authoring/env_cli.py +454 -0
  55. pz_core/authoring/files.py +109 -0
  56. pz_core/authoring/ide_projection.py +1129 -0
  57. pz_core/authoring/naming.py +58 -0
  58. pz_core/authoring/official_dev_sources.py +432 -0
  59. pz_core/authoring/official_sources.json +156 -0
  60. pz_core/authoring/orchestration_service.py +558 -0
  61. pz_core/authoring/project_default.jsonc +53 -0
  62. pz_core/authoring/project_defaults.py +88 -0
  63. pz_core/authoring/project_metadata_service.py +199 -0
  64. pz_core/authoring/project_settings_checks.py +51 -0
  65. pz_core/authoring/project_settings_cli.py +299 -0
  66. pz_core/authoring/project_settings_service.py +1700 -0
  67. pz_core/authoring/project_state.py +399 -0
  68. pz_core/authoring/publish_git.py +423 -0
  69. pz_core/authoring/publish_lock.py +188 -0
  70. pz_core/authoring/publish_source.py +195 -0
  71. pz_core/authoring/release.py +1382 -0
  72. pz_core/authoring/repo_keys.py +29 -0
  73. pz_core/authoring/root_cli.py +28 -0
  74. pz_core/authoring/scaffold_service.py +325 -0
  75. pz_core/authoring/sync_service.py +787 -0
  76. pz_core/authoring/templates/app/__init__.py +1 -0
  77. pz_core/authoring/templates/app/api.py +25 -0
  78. pz_core/authoring/templates/app/apps.py +31 -0
  79. pz_core/authoring/templates/app/auth_package_init.py +14 -0
  80. pz_core/authoring/templates/app/auth_readme.py +29 -0
  81. pz_core/authoring/templates/app/configs_package_init.py +14 -0
  82. pz_core/authoring/templates/app/default_env.py +18 -0
  83. pz_core/authoring/templates/app/default_jsonc.py +25 -0
  84. pz_core/authoring/templates/app/locales_readme.py +25 -0
  85. pz_core/authoring/templates/app/migrations_readme.py +19 -0
  86. pz_core/authoring/templates/app/models.py +14 -0
  87. pz_core/authoring/templates/app/package_init.py +8 -0
  88. pz_core/authoring/templates/app/pages_base.py +161 -0
  89. pz_core/authoring/templates/app/pages_readme.py +25 -0
  90. pz_core/authoring/templates/app/public.py +31 -0
  91. pz_core/authoring/templates/app/pyproject.py +77 -0
  92. pz_core/authoring/templates/app/readme.py +74 -0
  93. pz_core/authoring/templates/app/settings.py +46 -0
  94. pz_core/authoring/templates/app/static_app_js.py +24 -0
  95. pz_core/authoring/templates/app/static_readme.py +31 -0
  96. pz_core/authoring/templates/app/template_config_page.py +23 -0
  97. pz_core/authoring/templates/app/template_index_html.py +28 -0
  98. pz_core/authoring/templates/app/templates_readme.py +32 -0
  99. pz_core/authoring/templates/app/urls.py +36 -0
  100. pz_core/authoring/templates/app/views.py +36 -0
  101. pz_core/authoring/templates/project/__init__.py +1 -0
  102. pz_core/authoring/templates/project/agents.py +51 -0
  103. pz_core/authoring/templates/project/apps_container_readme.py +37 -0
  104. pz_core/authoring/templates/project/main_py.py +59 -0
  105. pz_core/authoring/templates/project/project_env.py +19 -0
  106. pz_core/authoring/templates/project/pyproject.py +26 -0
  107. pz_core/authoring/templates/project/pz_env_env.py +65 -0
  108. pz_core/authoring/templates/project/pz_env_jsonc.py +69 -0
  109. pz_core/authoring/templates/project/pz_jsonc.py +12 -0
  110. pz_core/authoring/templates/project/readme.py +94 -0
  111. pz_core/authoring/templates/project/root_gitkeep.py +8 -0
  112. pz_core/authoring/templates/shared/__init__.py +5 -0
  113. pz_core/authoring/templates/shared/text.py +10 -0
  114. pz_core/authoring/venv_service.py +87 -0
  115. pz_core/authoring/workspace.py +167 -0
  116. pz_core/cli.py +291 -0
  117. pz_core/cli_options.py +74 -0
  118. pz_core/core/__init__.py +3 -0
  119. pz_core/core/errors/__init__.py +5 -0
  120. pz_core/core/errors/models.py +117 -0
  121. pz_core/core/events/__init__.py +5 -0
  122. pz_core/core/events/registry.py +54 -0
  123. pz_core/core/extensions/__init__.py +51 -0
  124. pz_core/core/extensions/registry.py +790 -0
  125. pz_core/core/health/__init__.py +6 -0
  126. pz_core/core/health/contracts.py +10 -0
  127. pz_core/core/middlewares/__init__.py +6 -0
  128. pz_core/core/middlewares/models.py +24 -0
  129. pz_core/core/routing/__init__.py +5 -0
  130. pz_core/core/routing/models.py +21 -0
  131. pz_core/core/settings_contracts.py +25 -0
  132. pz_core/docs/README.md +20 -0
  133. pz_core/docs/distribution-README.md +438 -0
  134. pz_core/docs/pz/345/221/275/344/273/244/346/200/273/350/247/210.md +1011 -0
  135. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/00-pz/346/236/266/346/236/204/346/200/273/347/272/262.md +240 -0
  136. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/01-/347/233/256/345/275/225/344/270/216/345/210/206/345/261/202/350/247/204/350/214/203.md +216 -0
  137. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/02-/345/214/205/344/270/216/345/210/206/345/217/221/350/247/204/350/214/203.md +403 -0
  138. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/03-App/346/234/200/345/260/217/345/255/220/345/214/205/350/247/204/350/214/203.md +571 -0
  139. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/04-Settings/344/270/216/351/205/215/347/275/256/350/247/204/350/214/203.md +1177 -0
  140. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/05-/350/265/204/346/272/220/344/270/216/350/277/220/350/241/214/347/233/256/345/275/225/350/247/204/350/214/203.md +575 -0
  141. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/06-/346/225/260/346/215/256/345/272/223/344/270/216/345/217/257/351/200/211/345/237/272/347/241/200/350/256/276/346/226/275/350/247/204/350/214/203.md +499 -0
  142. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/07-App/346/233/277/346/215/242/350/247/204/350/214/203.md +206 -0
  143. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/08-/345/271/263/345/217/260/347/272/247App/344/270/216/350/277/220/350/241/214/346/227/266/345/215/225/344/276/213/350/247/204/350/214/203.md +445 -0
  144. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/09-CLI/344/270/216Worker/345/205/245/345/217/243/350/247/204/350/214/203.md +950 -0
  145. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/10-/346/265/213/350/257/225/344/270/216/345/245/221/347/272/246/350/247/204/350/214/203.md +1001 -0
  146. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/11-/344/273/223/345/272/223/347/234/237/347/233/270/346/272/220/345/234/260/345/233/276.md +102 -0
  147. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/12-/346/236/204/345/273/272/344/270/216/345/217/221/345/270/203/346/243/200/346/237/245/346/270/205/345/215/225.md +171 -0
  148. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/13-/346/255/243/345/274/217Facade/346/200/273/350/241/250.md +402 -0
  149. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/14-/345/210/206/345/261/202/344/270/216/346/211/251/345/261/225/350/247/204/350/214/203.md +550 -0
  150. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/15-/345/255/220/345/214/205/345/274/200/345/217/221/344/275/277/347/224/250/346/211/213/345/206/214.md +1004 -0
  151. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/16-/346/211/251/345/261/225/347/202/271/346/255/243/345/274/217/345/215/217/350/256/256/346/270/205/345/215/225.md +352 -0
  152. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/17-pz.protocols.v1/346/255/243/345/274/217/345/215/217/350/256/256.md +266 -0
  153. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/18-/346/211/251/345/261/225/347/202/271/345/206/262/347/252/201/350/243/201/345/206/263/346/200/273/350/241/250.md +131 -0
  154. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/19-/351/224/231/350/257/257/347/240/201/344/270/216/350/257/212/346/226/255/345/215/217/350/256/256.md +176 -0
  155. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/20-/347/247/201/346/234/211/345/214/205/344/273/223/344/270/216/347/273/237/344/270/200/350/256/244/350/257/201/351/203/250/347/275/262/350/247/204/350/214/203.md +243 -0
  156. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/21-contrib/347/272/246/345/256/232/344/270/216Provider/346/216/245/345/205/245/350/247/204/350/214/203.md +365 -0
  157. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/22-/345/244/232/345/233/275/350/257/255/350/250/200/350/265/204/346/272/220/346/262/273/347/220/206/344/270/216/346/214/211/351/234/200/345/212/240/350/275/275/350/247/204/350/214/203.md +912 -0
  158. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/23-/351/246/226/345/261/217/345/261/225/347/244/272/344/270/216/351/246/226/345/270/247/347/250/263/345/256/232/350/247/204/350/214/203.md +269 -0
  159. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/24-pz/345/220/257/345/212/250/344/270/216/350/277/220/350/241/214/346/227/266/347/274/226/350/257/221/346/265/201/347/250/213.md +245 -0
  160. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/25-/351/235/242/345/220/221/345/257/271/350/261/241/345/274/200/345/217/221/350/247/204/350/214/203.md +300 -0
  161. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/README.md +98 -0
  162. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/archive//344/270/255/351/227/264/346/200/201/00-legacy_core/346/240/207/345/207/206pip/345/214/205/345/214/226/351/207/215/346/236/204/346/200/273/347/272/262.md +1073 -0
  163. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/archive//344/270/255/351/227/264/346/200/201/01-/347/233/256/345/275/225/344/270/216/345/210/206/345/261/202/351/207/215/346/236/204/346/211/247/350/241/214/346/226/271/346/241/210.md +224 -0
  164. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/archive//344/270/255/351/227/264/346/200/201/02-/345/214/205/344/270/216/345/210/206/345/217/221/350/247/204/350/214/203-/345/220/253/345/216/206/345/217/262/345/217/243/345/276/204.md +671 -0
  165. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/archive//344/270/255/351/227/264/346/200/201/13-/344/270/200/346/254/241/346/200/247/345/256/236/346/226/275/346/270/205/345/215/225.md +387 -0
  166. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/archive//344/270/255/351/227/264/346/200/201/14-/345/255/220/345/214/205/351/200/202/351/205/215/346/224/271/351/200/240/346/270/205/345/215/225.md +592 -0
  167. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/archive//344/270/255/351/227/264/346/200/201/15-infra/350/243/201/345/211/252/344/270/216/350/220/275/344/275/215/346/270/205/345/215/225.md +81 -0
  168. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/archive//344/270/255/351/227/264/346/200/201/19-core/345/215/225/344/270/200/346/255/243/345/274/217/346/226/271/346/241/210/346/224/266/346/225/233/346/211/247/350/241/214/346/270/205/345/215/225.md +161 -0
  169. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/archive//344/270/255/351/227/264/346/200/201/25-/345/215/217/350/256/256/345/210/260/346/272/220/347/240/201/345/267/256/350/267/235/346/270/205/345/215/225.md +377 -0
  170. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/archive//344/270/255/351/227/264/346/200/201/26-cutover/345/256/214/345/267/245/346/243/200/346/237/245/346/270/205/345/215/225.md +117 -0
  171. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/archive//344/270/255/351/227/264/346/200/201/29-/345/244/232/345/233/275/350/257/255/350/250/200/350/265/204/346/272/220/346/262/273/347/220/206/344/270/216/346/214/211/351/234/200/345/212/240/350/275/275/350/247/204/350/214/203-/345/220/253/350/277/201/347/247/273/347/255/226/347/225/245.md +956 -0
  172. pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/archive//344/270/255/351/227/264/346/200/201/99-/350/265/204/346/272/220/346/224/266/345/217/243/345/220/216/347/273/255TODO.md +84 -0
  173. pz_core/docs//345/217/221/347/211/210/345/211/215/346/270/205/345/215/225-4.0.11.md +84 -0
  174. pz_core/docs//346/226/260/346/211/213/346/214/207/345/215/227.md +422 -0
  175. pz_core/infra/__init__.py +17 -0
  176. pz_core/infra/db/__init__.py +23 -0
  177. pz_core/infra/db/contracts.py +73 -0
  178. pz_core/infra/health/__init__.py +5 -0
  179. pz_core/infra/health/contracts.py +8 -0
  180. pz_core/infra/kv/__init__.py +5 -0
  181. pz_core/infra/kv/contracts.py +17 -0
  182. pz_core/infra/observability/__init__.py +23 -0
  183. pz_core/infra/observability/contracts.py +142 -0
  184. pz_core/infra/resilience/__init__.py +5 -0
  185. pz_core/infra/resilience/contracts.py +17 -0
  186. pz_core/infra/resources/__init__.py +5 -0
  187. pz_core/infra/resources/contracts.py +16 -0
  188. pz_core/infra/settings/__init__.py +17 -0
  189. pz_core/infra/settings/models.py +81 -0
  190. pz_core/infra/storage/__init__.py +5 -0
  191. pz_core/infra/storage/ports.py +27 -0
  192. pz_core/project_root_commands.py +282 -0
  193. pz_core/project_runtime_cli.py +344 -0
  194. pz_core/project_sources.py +253 -0
  195. pz_core/pz_launcher.py +209 -0
  196. pz_core/root_cli.py +70 -0
  197. pz_core/runtime/__init__.py +229 -0
  198. pz_core/runtime/access.py +86 -0
  199. pz_core/runtime/adapters/__init__.py +5 -0
  200. pz_core/runtime/adapters/base.py +18 -0
  201. pz_core/runtime/asyncio_bridge.py +18 -0
  202. pz_core/runtime/bindings/__init__.py +5 -0
  203. pz_core/runtime/bindings/container.py +50 -0
  204. pz_core/runtime/cli/__init__.py +5 -0
  205. pz_core/runtime/cli/_args.py +67 -0
  206. pz_core/runtime/cli/app_commands.py +417 -0
  207. pz_core/runtime/cli/check.py +214 -0
  208. pz_core/runtime/cli/db.py +297 -0
  209. pz_core/runtime/cli/main.py +89 -0
  210. pz_core/runtime/cli/resources.py +280 -0
  211. pz_core/runtime/discovery.py +23 -0
  212. pz_core/runtime/environment_integrity.py +157 -0
  213. pz_core/runtime/errors.py +5 -0
  214. pz_core/runtime/events.py +87 -0
  215. pz_core/runtime/facades/__init__.py +38 -0
  216. pz_core/runtime/facades/_capabilities.py +46 -0
  217. pz_core/runtime/facades/cache.py +103 -0
  218. pz_core/runtime/facades/database.py +71 -0
  219. pz_core/runtime/facades/events.py +380 -0
  220. pz_core/runtime/facades/health.py +101 -0
  221. pz_core/runtime/facades/mail.py +121 -0
  222. pz_core/runtime/facades/observability.py +102 -0
  223. pz_core/runtime/facades/providers.py +75 -0
  224. pz_core/runtime/facades/resources.py +52 -0
  225. pz_core/runtime/facades/storage.py +296 -0
  226. pz_core/runtime/health/__init__.py +5 -0
  227. pz_core/runtime/health/service.py +102 -0
  228. pz_core/runtime/host.py +188 -0
  229. pz_core/runtime/host_runner.py +282 -0
  230. pz_core/runtime/http/__init__.py +20 -0
  231. pz_core/runtime/http/app.py +576 -0
  232. pz_core/runtime/http_timing.py +173 -0
  233. pz_core/runtime/invocation.py +29 -0
  234. pz_core/runtime/json_safe.py +47 -0
  235. pz_core/runtime/lifecycle/__init__.py +25 -0
  236. pz_core/runtime/lifecycle/manager.py +533 -0
  237. pz_core/runtime/plan.py +214 -0
  238. pz_core/runtime/plan_context.py +33 -0
  239. pz_core/runtime/plan_snapshot.py +177 -0
  240. pz_core/runtime/registries/__init__.py +27 -0
  241. pz_core/runtime/registries/capabilities.py +101 -0
  242. pz_core/runtime/registries/providers.py +396 -0
  243. pz_core/runtime/resource_assets.py +344 -0
  244. pz_core/runtime/run_cli.py +211 -0
  245. pz_core/runtime/settings.py +888 -0
  246. pz_core/runtime/worker/__init__.py +21 -0
  247. pz_core/runtime/worker/engine.py +921 -0
  248. pz_core/runtime/worker/runtime.py +25 -0
  249. pz_core/testing/__init__.py +15 -0
  250. pz_core/testing/doc_route_contracts.py +305 -0
  251. pz_core/utils/__init__.py +44 -0
  252. pz_core/utils/env.py +65 -0
  253. pz_core/utils/project_jsonc/__init__.py +29 -0
  254. pz_core/utils/project_jsonc/document.py +420 -0
  255. pz_core/utils/project_settings.py +99 -0
  256. pz_foundation/__init__.py +50 -0
  257. pz_foundation/_contracts.py +81 -0
  258. pz_foundation/_errors.py +34 -0
  259. pz_foundation/api.py +14 -0
  260. pz_foundation/apps.py +127 -0
  261. pz_foundation/auth/__init__.py +1 -0
  262. pz_foundation/cache_control.py +233 -0
  263. pz_foundation/cli/__init__.py +2 -0
  264. pz_foundation/cli/workers.py +565 -0
  265. pz_foundation/configs/__init__.py +0 -0
  266. pz_foundation/configs/default.env +15 -0
  267. pz_foundation/configs/default.jsonc +452 -0
  268. pz_foundation/db/__init__.py +94 -0
  269. pz_foundation/db/aerich_executor.py +664 -0
  270. pz_foundation/db/config.py +358 -0
  271. pz_foundation/db/connection_manager.py +689 -0
  272. pz_foundation/db/connection_probe.py +204 -0
  273. pz_foundation/db/database.py +1291 -0
  274. pz_foundation/db/deps.py +47 -0
  275. pz_foundation/db/lifecycle_status.py +85 -0
  276. pz_foundation/db/migrations.py +477 -0
  277. pz_foundation/db/mysql.py +57 -0
  278. pz_foundation/db/postgresql.py +409 -0
  279. pz_foundation/db/production_pool_fallback.py +143 -0
  280. pz_foundation/db/public.py +45 -0
  281. pz_foundation/db/session.py +369 -0
  282. pz_foundation/db/sqlite.py +15 -0
  283. pz_foundation/db/tortoise_manager.py +724 -0
  284. pz_foundation/db/tortoise_psycopg.py +148 -0
  285. pz_foundation/docs/README.md +18 -0
  286. pz_foundation/docs/distribution-README.md +319 -0
  287. pz_foundation/docs/infra/350/243/201/345/211/252/344/270/216/350/220/275/344/275/215/350/257/264/346/230/216.md +39 -0
  288. pz_foundation/docs//345/205/254/345/274/200/345/205/215/350/264/271/346/216/245/345/217/243/351/230/262/346/273/245/347/224/250/344/270/216/344/272/272/346/234/272/346/240/241/351/252/214.md +680 -0
  289. pz_foundation/docs//350/256/276/350/256/241/346/226/207/346/241/243.md +288 -0
  290. pz_foundation/docs//350/267/257/347/224/261/344/270/216URL/345/244/204/347/220/206/350/247/204/350/214/203.md +119 -0
  291. pz_foundation/health.py +105 -0
  292. pz_foundation/host/__init__.py +11 -0
  293. pz_foundation/host/builder.py +34 -0
  294. pz_foundation/host/cache_runtime.py +44 -0
  295. pz_foundation/host/db/__init__.py +17 -0
  296. pz_foundation/host/db/aerich_config.py +36 -0
  297. pz_foundation/host/db/config.py +106 -0
  298. pz_foundation/host/db/connection_manager.py +48 -0
  299. pz_foundation/host/db/deps.py +5 -0
  300. pz_foundation/host/db/orm_retry_patch.py +566 -0
  301. pz_foundation/host/db/request_adapter.py +325 -0
  302. pz_foundation/host/db/router.py +28 -0
  303. pz_foundation/host/db/session.py +284 -0
  304. pz_foundation/host/db/tortoise_manager.py +10 -0
  305. pz_foundation/host/idempotency.py +132 -0
  306. pz_foundation/host/lifespan.py +247 -0
  307. pz_foundation/host/redis_runtime.py +100 -0
  308. pz_foundation/host/web.py +790 -0
  309. pz_foundation/infra_provider.py +236 -0
  310. pz_foundation/kv/__init__.py +25 -0
  311. pz_foundation/kv/cache.py +1166 -0
  312. pz_foundation/kv/deps.py +84 -0
  313. pz_foundation/kv/public.py +25 -0
  314. pz_foundation/kv/redis_manager.py +1531 -0
  315. pz_foundation/lazy_exports.py +43 -0
  316. pz_foundation/lazy_imports.py +124 -0
  317. pz_foundation/lifecycle.py +392 -0
  318. pz_foundation/managed_workers.py +1117 -0
  319. pz_foundation/middlewares/__init__.py +26 -0
  320. pz_foundation/middlewares/_settings.py +250 -0
  321. pz_foundation/middlewares/analytics.py +124 -0
  322. pz_foundation/middlewares/cache_control.py +156 -0
  323. pz_foundation/middlewares/compression.py +202 -0
  324. pz_foundation/middlewares/cors.py +62 -0
  325. pz_foundation/middlewares/geo_country.py +44 -0
  326. pz_foundation/middlewares/inner_router.py +50 -0
  327. pz_foundation/middlewares/rate_limited/__init__.py +3 -0
  328. pz_foundation/middlewares/rate_limited/key_limiter.py +115 -0
  329. pz_foundation/middlewares/request_logging.py +104 -0
  330. pz_foundation/middlewares/route_owner.py +309 -0
  331. pz_foundation/middlewares/security_csrf.py +44 -0
  332. pz_foundation/middlewares/security_headers/__init__.py +4 -0
  333. pz_foundation/middlewares/security_headers/conflicts.py +44 -0
  334. pz_foundation/middlewares/security_headers/csp_nonce.py +200 -0
  335. pz_foundation/middlewares/security_headers/security_headers.py +44 -0
  336. pz_foundation/migrations/__init__.py +1 -0
  337. pz_foundation/migrations/pz_foundation/__init__.py +1 -0
  338. pz_foundation/models.py +22 -0
  339. pz_foundation/notifications/__init__.py +23 -0
  340. pz_foundation/notifications/email.py +542 -0
  341. pz_foundation/notifications/public.py +31 -0
  342. pz_foundation/observability/__init__.py +71 -0
  343. pz_foundation/observability/http.py +34 -0
  344. pz_foundation/observability/logger/__init__.py +49 -0
  345. pz_foundation/observability/logger/_bot_settings.py +126 -0
  346. pz_foundation/observability/logger/bot_message.py +592 -0
  347. pz_foundation/observability/logger/core.py +385 -0
  348. pz_foundation/observability/logger/delivery_audit.py +84 -0
  349. pz_foundation/observability/logger/feishu_bot.py +199 -0
  350. pz_foundation/observability/logger/telegram_bot.py +194 -0
  351. pz_foundation/observability/metrics.py +365 -0
  352. pz_foundation/observability/runtime.py +68 -0
  353. pz_foundation/public.py +405 -0
  354. pz_foundation/resources/__init__.py +12 -0
  355. pz_foundation/resources/builder.py +900 -0
  356. pz_foundation/resources/images.py +363 -0
  357. pz_foundation/root_cli.py +20 -0
  358. pz_foundation/routing/__init__.py +203 -0
  359. pz_foundation/routing/canonical.py +486 -0
  360. pz_foundation/routing/convertors.py +82 -0
  361. pz_foundation/routing/declarations.py +843 -0
  362. pz_foundation/routing/exports.py +148 -0
  363. pz_foundation/routing/loaders.py +138 -0
  364. pz_foundation/routing/manifest.py +215 -0
  365. pz_foundation/routing/manifest_provider.py +47 -0
  366. pz_foundation/routing/mounts.py +101 -0
  367. pz_foundation/routing/ordering.py +172 -0
  368. pz_foundation/routing/registry.py +133 -0
  369. pz_foundation/routing/utils.py +28 -0
  370. pz_foundation/runtime.py +234 -0
  371. pz_foundation/settings.py +253 -0
  372. pz_foundation/settings_normalization.py +130 -0
  373. pz_foundation/storage/__init__.py +25 -0
  374. pz_foundation/storage/local.py +209 -0
  375. pz_foundation/storage/public.py +106 -0
  376. pz_foundation/storage/s3.py +116 -0
  377. pz_foundation/storage/service.py +234 -0
  378. pz_foundation/urls.py +19 -0
  379. pz_foundation/utils/__init__.py +6 -0
  380. pz_foundation/utils/merge.py +160 -0
  381. pz_foundation/worker_replicas.py +55 -0
  382. pz_settings_center/__init__.py +5 -0
  383. pz_settings_center/api/__init__.py +5 -0
  384. pz_settings_center/api/runtime_overrides.py +360 -0
  385. pz_settings_center/apps.py +28 -0
  386. pz_settings_center/configs/__init__.py +0 -0
  387. pz_settings_center/configs/default.env +2 -0
  388. pz_settings_center/configs/default.jsonc +1 -0
  389. pz_settings_center/docs/01-settings_center/350/203/275/345/212/233/350/276/271/347/225/214.md +124 -0
  390. pz_settings_center/docs/README.md +12 -0
  391. pz_settings_center/docs/distribution-README.md +150 -0
  392. pz_settings_center/docs//350/256/276/350/256/241/346/226/207/346/241/243.md +48 -0
  393. pz_settings_center/integration_payload.py +18 -0
  394. pz_settings_center/project_helpers.py +405 -0
  395. pz_settings_center/public.py +139 -0
  396. pz_settings_center/routing_helpers.py +73 -0
  397. pz_settings_center/runtime_override_provider.py +61 -0
  398. pz_settings_center/typed_settings.py +324 -0
  399. pz_settings_center/urls.py +9 -0
@@ -0,0 +1,157 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Iterable, Mapping
4
+ from importlib import metadata as importlib_metadata
5
+ from pathlib import Path
6
+ import re
7
+
8
+ from pz_core.runtime.errors import PzError
9
+
10
+
11
+ PROJECT_CONFIG_NAME = "pz.jsonc"
12
+ PROJECT_ENV_CONFIG_PATTERN = "pz.{environment}.jsonc"
13
+ PZ_ENV_PREFIX = "PZ_"
14
+ _FORMAL_ENVIRONMENTS = ("develop", "test", "product")
15
+
16
+ _LEGACY_STEM = "pyz" + "za"
17
+ _LEGACY_ENV_PREFIX = _LEGACY_STEM.upper() + "_"
18
+ _LEGACY_APP_PREFIX = _LEGACY_STEM + "_"
19
+ _LEGACY_DISTRIBUTION_PREFIX = _LEGACY_STEM + "-"
20
+ _RETIRED_BASE_DISTRIBUTIONS = frozenset(
21
+ {"pz-core", "pz-settings-center", "pz-foundation", "pz-contrib"}
22
+ )
23
+
24
+
25
+ def _canonicalize_distribution_name(value: object) -> str:
26
+ return re.sub(r"[-_.]+", "-", str(value or "").strip()).lower()
27
+
28
+
29
+ def _distribution_name(distribution: importlib_metadata.Distribution) -> str:
30
+ metadata = getattr(distribution, "metadata", None)
31
+ raw_name = metadata.get("Name") if metadata is not None and hasattr(metadata, "get") else None
32
+ if raw_name is None:
33
+ raw_name = getattr(distribution, "name", None)
34
+ return _canonicalize_distribution_name(raw_name)
35
+
36
+
37
+ def validate_process_environment(environ: Mapping[str, str]) -> None:
38
+ """Reject every framework-owned v4 environment key."""
39
+
40
+ legacy_keys = sorted(
41
+ str(key)
42
+ for key in environ
43
+ if str(key).startswith(_LEGACY_ENV_PREFIX)
44
+ )
45
+ if not legacy_keys:
46
+ return
47
+ raise PzError(
48
+ code="PZ_LEGACY_ENV_UNSUPPORTED",
49
+ message=(
50
+ "Legacy framework environment keys are not supported. "
51
+ f"Use {PZ_ENV_PREFIX}* keys only."
52
+ ),
53
+ stage="environment",
54
+ owner="runtime.environment_integrity",
55
+ action="validate_process_environment",
56
+ detail=", ".join(legacy_keys),
57
+ )
58
+
59
+
60
+ def validate_installed_distributions(
61
+ distributions: Iterable[importlib_metadata.Distribution],
62
+ ) -> None:
63
+ """Reject every installed v4 framework distribution."""
64
+
65
+ unsupported_names = sorted(
66
+ {
67
+ name
68
+ for distribution in distributions
69
+ if (name := _distribution_name(distribution))
70
+ and (
71
+ name == _LEGACY_STEM
72
+ or name.startswith(_LEGACY_DISTRIBUTION_PREFIX)
73
+ or name in _RETIRED_BASE_DISTRIBUTIONS
74
+ )
75
+ }
76
+ )
77
+ if not unsupported_names:
78
+ return
79
+ raise PzError(
80
+ code="PZ_ENVIRONMENT_MIXED_GENERATIONS",
81
+ message=(
82
+ "The current Python environment contains unsupported legacy or "
83
+ "retired split-wheel distributions. Recreate it with pz-cli==5.0.0."
84
+ ),
85
+ stage="environment",
86
+ owner="runtime.environment_integrity",
87
+ action="validate_installed_distributions",
88
+ detail=", ".join(unsupported_names),
89
+ )
90
+
91
+
92
+ def validate_installed_app_identities(app_ids: Iterable[object]) -> None:
93
+ legacy_app_ids = sorted(
94
+ {
95
+ value
96
+ for raw_value in app_ids
97
+ if isinstance(raw_value, str)
98
+ and (value := raw_value.strip())
99
+ and any(part.startswith(_LEGACY_APP_PREFIX) for part in value.split("."))
100
+ }
101
+ )
102
+ if not legacy_app_ids:
103
+ return
104
+ raise PzError(
105
+ code="PZ_LEGACY_APP_ID_UNSUPPORTED",
106
+ message="installed_apps contains unsupported v4 app identities.",
107
+ stage="apps",
108
+ owner="runtime.environment_integrity",
109
+ action="validate_installed_app_identities",
110
+ detail=", ".join(legacy_app_ids),
111
+ )
112
+
113
+
114
+ def validate_project_config_identity(project_dir: str | Path) -> None:
115
+ root = Path(project_dir).expanduser().resolve()
116
+ legacy_paths = [root / (_LEGACY_STEM + ".jsonc")]
117
+ legacy_paths.extend(
118
+ root / f"{_LEGACY_STEM}.{environment}.jsonc"
119
+ for environment in _FORMAL_ENVIRONMENTS
120
+ )
121
+ existing = sorted({path.resolve() for path in legacy_paths if path.is_file()})
122
+ if not existing:
123
+ return
124
+ raise PzError(
125
+ code="PZ_PROJECT_CONFIG_LEGACY_UNSUPPORTED",
126
+ message=(
127
+ "Legacy project configuration files are not supported. "
128
+ f"Use {PROJECT_CONFIG_NAME} and {PROJECT_ENV_CONFIG_PATTERN}."
129
+ ),
130
+ stage="project",
131
+ owner="runtime.environment_integrity",
132
+ action="validate_project_config_identity",
133
+ detail=", ".join(path.name for path in existing),
134
+ )
135
+
136
+
137
+ def validate_current_environment(
138
+ environ: Mapping[str, str],
139
+ *,
140
+ distributions: Iterable[importlib_metadata.Distribution] | None = None,
141
+ ) -> None:
142
+ validate_process_environment(environ)
143
+ validate_installed_distributions(
144
+ importlib_metadata.distributions() if distributions is None else distributions
145
+ )
146
+
147
+
148
+ __all__ = [
149
+ "PROJECT_CONFIG_NAME",
150
+ "PROJECT_ENV_CONFIG_PATTERN",
151
+ "PZ_ENV_PREFIX",
152
+ "validate_current_environment",
153
+ "validate_installed_app_identities",
154
+ "validate_installed_distributions",
155
+ "validate_process_environment",
156
+ "validate_project_config_identity",
157
+ ]
@@ -0,0 +1,5 @@
1
+ from __future__ import annotations
2
+
3
+ from pz_core.core.errors import PzError, as_pz_error
4
+
5
+ __all__ = ["PzError", "as_pz_error"]
@@ -0,0 +1,87 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from pz_core.runtime.errors import PzError
6
+ from pz_core.runtime.access import get_bindings
7
+ from pz_core.runtime.bindings import RuntimeBindings
8
+
9
+
10
+ def _resolve_runtime_bindings(
11
+ *,
12
+ bindings: RuntimeBindings | None = None,
13
+ request: Any | None = None,
14
+ runtime: Any | None = None,
15
+ ) -> RuntimeBindings:
16
+ if bindings is not None:
17
+ if not isinstance(bindings, RuntimeBindings):
18
+ raise PzError(
19
+ code="PZ_RUNTIME_BINDINGS_INVALID",
20
+ message="runtime events bindings must be a RuntimeBindings instance.",
21
+ stage="events",
22
+ owner="runtime.events",
23
+ action="resolve_bindings",
24
+ )
25
+ return bindings
26
+ return get_bindings(request=request, runtime=runtime)
27
+
28
+
29
+ def publish_nowait(
30
+ event_name: str,
31
+ payload: dict[str, Any] | None = None,
32
+ *,
33
+ owner: str = "pz_core.runtime.events",
34
+ bindings: RuntimeBindings | None = None,
35
+ request: Any | None = None,
36
+ runtime: Any | None = None,
37
+ ):
38
+ resolved_bindings = _resolve_runtime_bindings(
39
+ bindings=bindings,
40
+ request=request,
41
+ runtime=runtime,
42
+ )
43
+ return resolved_bindings.events.publish_nowait(event_name, payload, owner=owner)
44
+
45
+
46
+ async def publish(
47
+ event_name: str,
48
+ payload: dict[str, Any] | None = None,
49
+ *,
50
+ owner: str = "pz_core.runtime.events",
51
+ bindings: RuntimeBindings | None = None,
52
+ request: Any | None = None,
53
+ runtime: Any | None = None,
54
+ ):
55
+ resolved_bindings = _resolve_runtime_bindings(
56
+ bindings=bindings,
57
+ request=request,
58
+ runtime=runtime,
59
+ )
60
+ return await resolved_bindings.events.publish(event_name, payload, owner=owner)
61
+
62
+
63
+ def subscribe(
64
+ event_name: str,
65
+ handler,
66
+ *,
67
+ owner: str | None = None,
68
+ wildcard: bool = False,
69
+ bindings: RuntimeBindings | None = None,
70
+ request: Any | None = None,
71
+ runtime: Any | None = None,
72
+ ):
73
+ normalized_owner = owner or getattr(handler, "__module__", "pz_core.runtime.events")
74
+ resolved_bindings = _resolve_runtime_bindings(
75
+ bindings=bindings,
76
+ request=request,
77
+ runtime=runtime,
78
+ )
79
+ return resolved_bindings.events.subscribe(
80
+ event_name,
81
+ handler,
82
+ owner=normalized_owner,
83
+ wildcard=wildcard,
84
+ )
85
+
86
+
87
+ __all__ = ["publish", "publish_nowait", "subscribe"]
@@ -0,0 +1,38 @@
1
+ from __future__ import annotations
2
+
3
+ from .cache import CacheFacade
4
+ from .database import DatabaseFacade
5
+ from .events import EventBusFacade, EventDispatchResult, EventDispatchTicket, EventSubscription
6
+ from .health import HealthFacade
7
+ from .mail import MailFacade
8
+ from .observability import ObservabilityFacade
9
+ from .providers import ProviderFacade
10
+ from .resources import ResourceFacade
11
+ from .storage import StorageFacade
12
+ from .storage import (
13
+ RuntimePresignInfo,
14
+ RuntimeStoragePort,
15
+ RuntimeStoredObject,
16
+ StorageClient,
17
+ get_storage,
18
+ )
19
+
20
+ __all__ = [
21
+ "CacheFacade",
22
+ "DatabaseFacade",
23
+ "EventBusFacade",
24
+ "EventDispatchResult",
25
+ "EventDispatchTicket",
26
+ "EventSubscription",
27
+ "HealthFacade",
28
+ "MailFacade",
29
+ "ObservabilityFacade",
30
+ "ProviderFacade",
31
+ "ResourceFacade",
32
+ "StorageFacade",
33
+ "RuntimePresignInfo",
34
+ "RuntimeStoragePort",
35
+ "RuntimeStoredObject",
36
+ "StorageClient",
37
+ "get_storage",
38
+ ]
@@ -0,0 +1,46 @@
1
+ from __future__ import annotations
2
+
3
+ from pz_core.runtime.facades.providers import ProviderFacade
4
+ from pz_core.runtime.plan import RuntimePlan
5
+ from pz_core.runtime.registries import CapabilityStatus
6
+ from pz_core.runtime.errors import PzError
7
+
8
+
9
+ def merged_capability_status(
10
+ plan: RuntimePlan,
11
+ providers: ProviderFacade,
12
+ capability: str,
13
+ ) -> CapabilityStatus:
14
+ if not isinstance(plan, RuntimePlan):
15
+ raise PzError(
16
+ code="PZ_CAPABILITY_PLAN_INVALID",
17
+ message="capability status merge requires a RuntimePlan instance.",
18
+ stage="capabilities",
19
+ owner="runtime.capabilities",
20
+ action="merged_capability_status",
21
+ )
22
+ if not hasattr(providers, "declared_for") or not hasattr(providers, "status"):
23
+ raise PzError(
24
+ code="PZ_CAPABILITY_PROVIDERS_INVALID",
25
+ message="capability status merge requires providers with declared_for() and status().",
26
+ stage="capabilities",
27
+ owner="runtime.capabilities",
28
+ action="merged_capability_status",
29
+ )
30
+ if not isinstance(capability, str) or not capability.strip():
31
+ raise PzError(
32
+ code="PZ_CAPABILITY_NAME_INVALID",
33
+ message="capability name must be a non-empty string.",
34
+ stage="capabilities",
35
+ owner="runtime.capabilities",
36
+ action="merged_capability_status",
37
+ )
38
+ normalized = capability.strip()
39
+ base = plan.capability_registry.get(normalized)
40
+ base_status: CapabilityStatus = base.status if base is not None else "disabled"
41
+ if not providers.declared_for(normalized):
42
+ return base_status
43
+ provider_status = providers.status(normalized)
44
+ if provider_status == "disabled":
45
+ return base_status
46
+ return provider_status
@@ -0,0 +1,103 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from pz_core.runtime.errors import PzError
6
+ from pz_core.infra.kv import CacheClientFactory, CachePort
7
+ from pz_core.runtime.facades._capabilities import merged_capability_status
8
+ from pz_core.runtime.facades.providers import ProviderFacade
9
+ from pz_core.runtime.plan import RuntimePlan
10
+ from pz_core.runtime.registries import CapabilityStatus
11
+
12
+
13
+ def _require_cache_key(key: str, *, action: str) -> str:
14
+ if not isinstance(key, str) or not key.strip():
15
+ raise PzError(
16
+ code="PZ_CACHE_KEY_INVALID",
17
+ message="Cache key must be a non-empty string.",
18
+ stage="cache",
19
+ owner="runtime.cache",
20
+ action=action,
21
+ )
22
+ return key
23
+
24
+
25
+ def _require_cache_ttl(ttl: int | None, *, action: str) -> int | None:
26
+ if ttl is None:
27
+ return None
28
+ if isinstance(ttl, bool) or not isinstance(ttl, int) or ttl <= 0:
29
+ raise PzError(
30
+ code="PZ_CACHE_TTL_INVALID",
31
+ message="Cache ttl must be a positive integer when configured.",
32
+ stage="cache",
33
+ owner="runtime.cache",
34
+ action=action,
35
+ )
36
+ return ttl
37
+
38
+
39
+ class CacheFacade:
40
+ def __init__(self, plan: RuntimePlan, providers: ProviderFacade) -> None:
41
+ if not isinstance(plan, RuntimePlan):
42
+ raise PzError(
43
+ code="PZ_CACHE_PLAN_INVALID",
44
+ message="CacheFacade requires a RuntimePlan instance.",
45
+ stage="cache",
46
+ owner="runtime.cache",
47
+ action="bind_cache_facade",
48
+ )
49
+ if not hasattr(providers, "require"):
50
+ raise PzError(
51
+ code="PZ_CACHE_PROVIDERS_INVALID",
52
+ message="CacheFacade providers must expose require().",
53
+ stage="cache",
54
+ owner="runtime.cache",
55
+ action="bind_cache_facade",
56
+ )
57
+ self._plan = plan
58
+ self._providers = providers
59
+
60
+ def status(self) -> CapabilityStatus:
61
+ return merged_capability_status(self._plan, self._providers, "cache")
62
+
63
+ def _cache(self) -> CachePort:
64
+ provider = self._providers.require("cache")
65
+ if isinstance(provider, CachePort):
66
+ return provider
67
+ if isinstance(provider, CacheClientFactory):
68
+ return provider.create_cache()
69
+ raise PzError(
70
+ code="PZ_CACHE_PROVIDER_INVALID",
71
+ message="Registered cache provider does not implement CachePort or CacheClientFactory.",
72
+ stage="cache",
73
+ owner="infra.cache",
74
+ action="resolve_cache",
75
+ )
76
+
77
+ def get(self, key: str) -> Any:
78
+ key = _require_cache_key(key, action="get")
79
+ return self._cache().get(key)
80
+
81
+ def set(self, key: str, value: object, *, ttl: int | None = None) -> None:
82
+ key = _require_cache_key(key, action="set")
83
+ ttl = _require_cache_ttl(ttl, action="set")
84
+ self._cache().set(key, value, ttl_seconds=ttl)
85
+
86
+ def delete(self, key: str) -> None:
87
+ key = _require_cache_key(key, action="delete")
88
+ self._cache().delete(key)
89
+
90
+ def lock(self, key: str, *, ttl: int | None = None) -> object:
91
+ key = _require_cache_key(key, action="lock")
92
+ ttl = _require_cache_ttl(ttl, action="lock")
93
+ provider = self._providers.require("cache")
94
+ lock_factory = getattr(provider, "lock", None)
95
+ if not callable(lock_factory):
96
+ raise PzError(
97
+ code="PZ_CACHE_LOCK_UNSUPPORTED",
98
+ message="Registered cache provider does not expose lock().",
99
+ stage="cache",
100
+ owner="infra.cache",
101
+ action="lock",
102
+ )
103
+ return lock_factory(key, ttl=ttl)
@@ -0,0 +1,71 @@
1
+ from __future__ import annotations
2
+
3
+ from pz_core.runtime.errors import PzError
4
+ from pz_core.infra.db import DatabaseAdapter
5
+ from pz_core.runtime.facades._capabilities import merged_capability_status
6
+ from pz_core.runtime.facades.providers import ProviderFacade
7
+ from pz_core.runtime.plan import RuntimePlan
8
+ from pz_core.runtime.registries import CapabilityStatus
9
+
10
+
11
+ class DatabaseFacade:
12
+ def __init__(self, plan: RuntimePlan, providers: ProviderFacade) -> None:
13
+ if not isinstance(plan, RuntimePlan):
14
+ raise PzError(
15
+ code="PZ_DATABASE_PLAN_INVALID",
16
+ message="DatabaseFacade requires a RuntimePlan instance.",
17
+ stage="database",
18
+ owner="runtime.database",
19
+ action="bind_database_facade",
20
+ )
21
+ if not hasattr(providers, "require"):
22
+ raise PzError(
23
+ code="PZ_DATABASE_PROVIDERS_INVALID",
24
+ message="DatabaseFacade providers must expose require().",
25
+ stage="database",
26
+ owner="runtime.database",
27
+ action="bind_database_facade",
28
+ )
29
+ self._plan = plan
30
+ self._providers = providers
31
+
32
+ def status(self) -> CapabilityStatus:
33
+ return merged_capability_status(self._plan, self._providers, "database")
34
+
35
+ def connection(self) -> DatabaseAdapter:
36
+ provider = self._providers.require("database")
37
+ if not isinstance(provider, DatabaseAdapter):
38
+ raise PzError(
39
+ code="PZ_DATABASE_PROVIDER_INVALID",
40
+ message="Registered database provider does not implement DatabaseAdapter.",
41
+ stage="database",
42
+ owner="infra.database",
43
+ action="connection",
44
+ )
45
+ return provider
46
+
47
+ def session(self):
48
+ connection = self.connection()
49
+ factory = getattr(connection, "create_session", None)
50
+ if not callable(factory):
51
+ raise PzError(
52
+ code="PZ_DATABASE_SESSION_UNSUPPORTED",
53
+ message="Registered database adapter does not expose create_session().",
54
+ stage="database",
55
+ owner="infra.database",
56
+ action="session",
57
+ )
58
+ return factory()
59
+
60
+ def transaction(self):
61
+ session = self.session()
62
+ begin = getattr(session, "begin", None)
63
+ if not callable(begin):
64
+ raise PzError(
65
+ code="PZ_DATABASE_TRANSACTION_UNSUPPORTED",
66
+ message="Database session does not expose begin().",
67
+ stage="database",
68
+ owner="infra.database",
69
+ action="transaction",
70
+ )
71
+ return begin()