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,214 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from pathlib import Path
5
+ from types import SimpleNamespace
6
+ from typing import Any, Iterable
7
+
8
+ from pz_core.assembly.apps import AppRegistry, compile_app_registry, compile_provider_declarations
9
+ from pz_core.assembly.cli import CliManifest, compile_cli_manifest
10
+ from pz_core.assembly.events import compile_event_registry
11
+ from pz_core.assembly.extensions import compile_extension_registry
12
+ from pz_core.assembly.infra import compile_infra_context
13
+ from pz_core.assembly.lifecycle import LifecycleManifest, compile_lifecycle_manifest
14
+ from pz_core.assembly.middlewares import MiddlewareManifest, compile_middleware_manifest
15
+ from pz_core.assembly.project import active_project_import_root, compile_project_context
16
+ from pz_core.assembly.resources import ResourceManifest, compile_resource_manifest
17
+ from pz_core.assembly.routes import RouteManifest, compile_route_manifest
18
+ from pz_core.assembly.runtime_manifests import RuntimeManifestMap, compile_runtime_manifests
19
+ from pz_core.assembly.settings import SettingsSnapshot, compile_settings_snapshot
20
+ from pz_core.assembly.project import ProjectContext
21
+ from pz_core.core.events import EventRegistry
22
+ from pz_core.core.extensions import ExtensionRegistry, HostBuilderSpec, SettingsProviderSpec
23
+ from pz_core.infra.settings import InfraContext
24
+ from pz_core.runtime.plan_context import active_runtime_plan
25
+ from pz_core.runtime.registries import CapabilityRegistry, build_capability_registry
26
+ from pz_core.runtime.registries import ProviderDecl, ProviderRegistry
27
+ from pz_core.runtime.settings import (
28
+ active_settings_project,
29
+ bound_settings_snapshot,
30
+ )
31
+
32
+
33
+ def _compile_host_builder_specs(extension_registry: ExtensionRegistry) -> tuple[HostBuilderSpec, ...]:
34
+ return tuple(
35
+ item
36
+ for item in extension_registry.by_kind("host.builder")
37
+ if isinstance(item, HostBuilderSpec)
38
+ )
39
+
40
+
41
+ def _compile_settings_provider_specs(extension_registry: ExtensionRegistry) -> tuple[SettingsProviderSpec, ...]:
42
+ return tuple(
43
+ item
44
+ for item in extension_registry.by_kind("settings.provider")
45
+ if isinstance(item, SettingsProviderSpec)
46
+ )
47
+
48
+
49
+ @dataclass(frozen=True, slots=True)
50
+ class RuntimePlan:
51
+ project: ProjectContext
52
+ settings: SettingsSnapshot
53
+ app_registry: AppRegistry
54
+ event_registry: EventRegistry
55
+ extension_registry: ExtensionRegistry
56
+ host_builders: tuple[HostBuilderSpec, ...]
57
+ settings_providers: tuple[SettingsProviderSpec, ...]
58
+ provider_declarations: tuple[ProviderDecl, ...]
59
+ lifecycle_manifest: LifecycleManifest
60
+ resource_manifest: ResourceManifest
61
+ cli_manifest: CliManifest
62
+ infra: InfraContext
63
+ route_manifest: RouteManifest
64
+ middleware_manifest: MiddlewareManifest
65
+ runtime_manifests: RuntimeManifestMap
66
+ capability_registry: CapabilityRegistry
67
+ extension_conflicts: tuple[dict[str, Any], ...] = ()
68
+
69
+
70
+ def _build_resource_outputs_for_runtime_manifest(
71
+ *,
72
+ project: ProjectContext,
73
+ settings: SettingsSnapshot,
74
+ app_registry: AppRegistry,
75
+ event_registry: EventRegistry,
76
+ extension_registry: ExtensionRegistry,
77
+ host_builders: tuple[HostBuilderSpec, ...],
78
+ settings_providers: tuple[SettingsProviderSpec, ...],
79
+ provider_declarations: tuple[ProviderDecl, ...],
80
+ lifecycle_manifest: LifecycleManifest,
81
+ resource_manifest: ResourceManifest,
82
+ ) -> None:
83
+ resource_provider_declarations = tuple(
84
+ declaration
85
+ for declaration in provider_declarations
86
+ if declaration.capability == "resources"
87
+ )
88
+ if not resource_provider_declarations:
89
+ return
90
+ provider_registry = ProviderRegistry(resource_provider_declarations)
91
+ providers = SimpleNamespace(
92
+ activate_declared=provider_registry.activate_declared,
93
+ require=provider_registry.require,
94
+ status=provider_registry.status,
95
+ )
96
+ bindings = SimpleNamespace(providers=providers)
97
+ build_plan = SimpleNamespace(
98
+ project=project,
99
+ settings=settings,
100
+ app_registry=app_registry,
101
+ event_registry=event_registry,
102
+ extension_registry=extension_registry,
103
+ host_builders=host_builders,
104
+ settings_providers=settings_providers,
105
+ provider_declarations=provider_declarations,
106
+ lifecycle_manifest=lifecycle_manifest,
107
+ resource_manifest=resource_manifest,
108
+ runtime_manifests={},
109
+ )
110
+ with active_runtime_plan(build_plan):
111
+ providers.activate_declared(
112
+ plan=build_plan,
113
+ bindings=bindings,
114
+ host=None,
115
+ owner="pz_foundation",
116
+ )
117
+ provider = providers.require("resources")
118
+ build = getattr(provider, "build", None)
119
+ if not callable(build):
120
+ from pz_core.runtime.errors import PzError
121
+
122
+ raise PzError(
123
+ code="PZ_RESOURCE_PROVIDER_INVALID",
124
+ message="Registered resources provider does not expose build().",
125
+ stage="resources",
126
+ owner="runtime.resources",
127
+ action="compile_runtime_plan",
128
+ )
129
+ build()
130
+
131
+
132
+ def compile_runtime_plan(
133
+ project_dir: Path | str | None = None,
134
+ *,
135
+ installed_apps: Iterable[str] | None = None,
136
+ include_cli_manifest: bool = True,
137
+ ) -> RuntimePlan:
138
+ project = compile_project_context(project_dir=project_dir)
139
+ settings = compile_settings_snapshot(project)
140
+ if installed_apps is not None:
141
+ settings = settings.with_installed_apps(tuple(installed_apps))
142
+
143
+ with (
144
+ bound_settings_snapshot(settings, project_dir=project.project_dir),
145
+ active_settings_project(project.project_dir),
146
+ active_project_import_root(
147
+ project.project_dir,
148
+ extra_import_roots=settings.import_roots,
149
+ preserve_loaded_modules=True,
150
+ ),
151
+ ):
152
+ app_registry = compile_app_registry(settings, project_dir=project.project_dir)
153
+ extension_registry = compile_extension_registry(settings, app_registry)
154
+ event_registry = compile_event_registry(settings, extension_registry)
155
+ host_builders = _compile_host_builder_specs(extension_registry)
156
+ settings_providers = _compile_settings_provider_specs(extension_registry)
157
+ provider_declarations = compile_provider_declarations(settings, app_registry)
158
+ lifecycle_manifest = compile_lifecycle_manifest(app_registry, extension_registry)
159
+ resource_manifest = compile_resource_manifest(
160
+ project,
161
+ settings,
162
+ app_registry,
163
+ extension_registry=extension_registry,
164
+ )
165
+ _build_resource_outputs_for_runtime_manifest(
166
+ project=project,
167
+ settings=settings,
168
+ app_registry=app_registry,
169
+ event_registry=event_registry,
170
+ extension_registry=extension_registry,
171
+ host_builders=host_builders,
172
+ settings_providers=settings_providers,
173
+ provider_declarations=provider_declarations,
174
+ lifecycle_manifest=lifecycle_manifest,
175
+ resource_manifest=resource_manifest,
176
+ )
177
+ cli_manifest = (
178
+ compile_cli_manifest(app_registry, resource_manifest)
179
+ if include_cli_manifest
180
+ else CliManifest(commands=())
181
+ )
182
+ infra = compile_infra_context(settings, project, extension_registry=extension_registry)
183
+ route_manifest = compile_route_manifest(settings)
184
+ middleware_manifest = compile_middleware_manifest(settings, app_registry)
185
+ runtime_manifests = compile_runtime_manifests(
186
+ project=project,
187
+ settings=settings,
188
+ app_registry=app_registry,
189
+ extension_registry=extension_registry,
190
+ resource_manifest=resource_manifest,
191
+ )
192
+ capability_registry = build_capability_registry(infra=infra, app_registry=app_registry)
193
+
194
+ return RuntimePlan(
195
+ project=project,
196
+ settings=settings,
197
+ app_registry=app_registry,
198
+ event_registry=event_registry,
199
+ extension_registry=extension_registry,
200
+ host_builders=host_builders,
201
+ settings_providers=settings_providers,
202
+ provider_declarations=provider_declarations,
203
+ lifecycle_manifest=lifecycle_manifest,
204
+ resource_manifest=resource_manifest,
205
+ cli_manifest=cli_manifest,
206
+ infra=infra,
207
+ route_manifest=route_manifest,
208
+ middleware_manifest=middleware_manifest,
209
+ runtime_manifests=runtime_manifests,
210
+ capability_registry=capability_registry,
211
+ )
212
+
213
+
214
+ __all__ = ["RuntimePlan", "compile_runtime_plan"]
@@ -0,0 +1,33 @@
1
+ from __future__ import annotations
2
+
3
+ from contextlib import contextmanager
4
+ from contextvars import ContextVar
5
+ from typing import TYPE_CHECKING, Iterator
6
+
7
+ if TYPE_CHECKING:
8
+ from pz_core.runtime.plan import RuntimePlan
9
+
10
+
11
+ _ACTIVE_RUNTIME_PLAN: ContextVar["RuntimePlan | None"] = ContextVar(
12
+ "pz_active_runtime_plan",
13
+ default=None,
14
+ )
15
+
16
+
17
+ @contextmanager
18
+ def active_runtime_plan(plan: "RuntimePlan | None") -> Iterator[None]:
19
+ token = _ACTIVE_RUNTIME_PLAN.set(plan)
20
+ try:
21
+ yield
22
+ finally:
23
+ _ACTIVE_RUNTIME_PLAN.reset(token)
24
+
25
+
26
+ def current_runtime_plan() -> "RuntimePlan | None":
27
+ return _ACTIVE_RUNTIME_PLAN.get()
28
+
29
+
30
+ __all__ = [
31
+ "active_runtime_plan",
32
+ "current_runtime_plan",
33
+ ]
@@ -0,0 +1,177 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from pathlib import Path
5
+ import pickle
6
+ from typing import Any
7
+
8
+ try: # pragma: no cover - fcntl is unavailable on some platforms.
9
+ import fcntl
10
+ except Exception: # pragma: no cover
11
+ fcntl = None # type: ignore[assignment]
12
+
13
+ from pz_core.assembly.project import compile_project_context
14
+ from pz_core.runtime.errors import PzError
15
+ from pz_core.runtime.plan import RuntimePlan
16
+
17
+
18
+ RUNTIME_PLAN_SNAPSHOT_ENV = "PZ_RUNTIME_PLAN_SNAPSHOT"
19
+ RUNTIME_PLAN_SNAPSHOT_ID_ENV = "PZ_RUNTIME_PLAN_SNAPSHOT_ID"
20
+
21
+
22
+ def _snapshot_path(plan: RuntimePlan, *, invocation_id: str) -> Path:
23
+ safe_id = "".join(ch for ch in str(invocation_id or "").strip() if ch.isalnum() or ch in {"-", "_"})
24
+ if not safe_id:
25
+ raise PzError(
26
+ code="PZ_RUNTIME_PLAN_SNAPSHOT_ID_INVALID",
27
+ message="Runtime plan snapshot requires a non-empty runtime invocation id.",
28
+ stage="runtime",
29
+ owner="pz_core.runtime.plan_snapshot",
30
+ action="write_runtime_plan_snapshot",
31
+ )
32
+ return Path(plan.project.cache_dir) / "runtime_plan" / f"{safe_id}.pickle"
33
+
34
+
35
+ def write_runtime_plan_snapshot(plan: RuntimePlan, *, invocation_id: str) -> Path:
36
+ if not isinstance(plan, RuntimePlan):
37
+ raise PzError(
38
+ code="PZ_RUNTIME_PLAN_SNAPSHOT_PLAN_INVALID",
39
+ message="Runtime plan snapshot requires a compiled RuntimePlan.",
40
+ stage="runtime",
41
+ owner="pz_core.runtime.plan_snapshot",
42
+ action="write_runtime_plan_snapshot",
43
+ )
44
+ path = _snapshot_path(plan, invocation_id=invocation_id)
45
+ path.parent.mkdir(parents=True, exist_ok=True)
46
+ tmp_path = path.with_suffix(path.suffix + ".tmp")
47
+ with tmp_path.open("wb") as handle:
48
+ pickle.dump(plan, handle, protocol=pickle.HIGHEST_PROTOCOL)
49
+ tmp_path.replace(path)
50
+ return path
51
+
52
+
53
+ def runtime_plan_snapshot_path(
54
+ *,
55
+ project_dir: str | Path,
56
+ invocation_id: str,
57
+ ) -> Path:
58
+ project = compile_project_context(project_dir=project_dir)
59
+ return _snapshot_path_placeholder(project.cache_dir, invocation_id=invocation_id)
60
+
61
+
62
+ def _snapshot_path_placeholder(cache_dir: Path, *, invocation_id: str) -> Path:
63
+ safe_id = "".join(ch for ch in str(invocation_id or "").strip() if ch.isalnum() or ch in {"-", "_"})
64
+ if not safe_id:
65
+ raise PzError(
66
+ code="PZ_RUNTIME_PLAN_SNAPSHOT_ID_INVALID",
67
+ message="Runtime plan snapshot requires a non-empty runtime invocation id.",
68
+ stage="runtime",
69
+ owner="pz_core.runtime.plan_snapshot",
70
+ action="runtime_plan_snapshot_path",
71
+ )
72
+ return Path(cache_dir) / "runtime_plan" / f"{safe_id}.pickle"
73
+
74
+
75
+ def bind_runtime_plan_snapshot_env(path: str | Path | None) -> None:
76
+ if path is None:
77
+ os.environ.pop(RUNTIME_PLAN_SNAPSHOT_ENV, None)
78
+ return
79
+ snapshot_path = str(Path(path).resolve())
80
+ if not snapshot_path:
81
+ os.environ.pop(RUNTIME_PLAN_SNAPSHOT_ENV, None)
82
+ return
83
+ os.environ[RUNTIME_PLAN_SNAPSHOT_ENV] = snapshot_path
84
+
85
+
86
+ def bind_runtime_plan_snapshot_invocation_env(invocation_id: str | None) -> None:
87
+ raw = str(invocation_id or "").strip()
88
+ if not raw:
89
+ os.environ.pop(RUNTIME_PLAN_SNAPSHOT_ID_ENV, None)
90
+ return
91
+ os.environ[RUNTIME_PLAN_SNAPSHOT_ID_ENV] = raw
92
+
93
+
94
+ def load_runtime_plan_snapshot(path: str | Path | None = None) -> RuntimePlan | None:
95
+ raw_path: Any = path if path is not None else os.environ.get(RUNTIME_PLAN_SNAPSHOT_ENV)
96
+ if not isinstance(raw_path, (str, Path)) or not str(raw_path).strip():
97
+ return None
98
+ snapshot_path = Path(raw_path).resolve()
99
+ if not snapshot_path.is_file():
100
+ return None
101
+ try:
102
+ with snapshot_path.open("rb") as handle:
103
+ plan = pickle.load(handle)
104
+ except Exception as exc:
105
+ raise PzError(
106
+ code="PZ_RUNTIME_PLAN_SNAPSHOT_LOAD_FAILED",
107
+ message=f"Failed to load runtime plan snapshot '{snapshot_path}': {exc}",
108
+ stage="runtime",
109
+ owner="pz_core.runtime.plan_snapshot",
110
+ action="load_runtime_plan_snapshot",
111
+ ) from exc
112
+ if not isinstance(plan, RuntimePlan):
113
+ raise PzError(
114
+ code="PZ_RUNTIME_PLAN_SNAPSHOT_INVALID",
115
+ message=f"Runtime plan snapshot '{snapshot_path}' did not contain a RuntimePlan.",
116
+ stage="runtime",
117
+ owner="pz_core.runtime.plan_snapshot",
118
+ action="load_runtime_plan_snapshot",
119
+ )
120
+ return plan
121
+
122
+
123
+ def write_runtime_plan_snapshot_if_requested(
124
+ plan: RuntimePlan,
125
+ *,
126
+ invocation_id: str | None = None,
127
+ ) -> Path | None:
128
+ raw_invocation_id = str(invocation_id or os.environ.get(RUNTIME_PLAN_SNAPSHOT_ID_ENV) or "").strip()
129
+ if not raw_invocation_id:
130
+ return None
131
+ if not isinstance(plan, RuntimePlan):
132
+ return None
133
+ snapshot_path = _snapshot_path(plan, invocation_id=raw_invocation_id)
134
+ if snapshot_path.is_file():
135
+ return snapshot_path
136
+ lock_path = Path(plan.project.runtime_dir) / "locks" / f"runtime-plan-{snapshot_path.stem}.lock"
137
+ lock_path.parent.mkdir(parents=True, exist_ok=True)
138
+ handle = lock_path.open("a+", encoding="utf-8")
139
+ fallback_lock_dir: Path | None = None
140
+ try:
141
+ if fcntl is not None:
142
+ try:
143
+ fcntl.flock(handle.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
144
+ except BlockingIOError:
145
+ return None
146
+ else: # pragma: no cover
147
+ fallback_lock_dir = lock_path.with_suffix(lock_path.suffix + ".d")
148
+ try:
149
+ fallback_lock_dir.mkdir(parents=False, exist_ok=False)
150
+ except FileExistsError:
151
+ return None
152
+ if snapshot_path.is_file():
153
+ return snapshot_path
154
+ return write_runtime_plan_snapshot(plan, invocation_id=raw_invocation_id)
155
+ finally:
156
+ try:
157
+ if fcntl is not None:
158
+ fcntl.flock(handle.fileno(), fcntl.LOCK_UN)
159
+ finally:
160
+ handle.close()
161
+ if fallback_lock_dir is not None:
162
+ try: # pragma: no cover
163
+ fallback_lock_dir.rmdir()
164
+ except FileNotFoundError: # pragma: no cover
165
+ pass
166
+
167
+
168
+ __all__ = [
169
+ "RUNTIME_PLAN_SNAPSHOT_ENV",
170
+ "RUNTIME_PLAN_SNAPSHOT_ID_ENV",
171
+ "bind_runtime_plan_snapshot_env",
172
+ "bind_runtime_plan_snapshot_invocation_env",
173
+ "load_runtime_plan_snapshot",
174
+ "runtime_plan_snapshot_path",
175
+ "write_runtime_plan_snapshot",
176
+ "write_runtime_plan_snapshot_if_requested",
177
+ ]
@@ -0,0 +1,27 @@
1
+ from __future__ import annotations
2
+
3
+ from .capabilities import (
4
+ CapabilityRegistry,
5
+ CapabilityState,
6
+ CapabilityStatus,
7
+ build_capability_registry,
8
+ )
9
+ from .providers import (
10
+ ProviderActivationContext,
11
+ ProviderBinding,
12
+ ProviderDecl,
13
+ ProviderDiagnostic,
14
+ ProviderRegistry,
15
+ )
16
+
17
+ __all__ = [
18
+ "CapabilityRegistry",
19
+ "CapabilityState",
20
+ "CapabilityStatus",
21
+ "ProviderActivationContext",
22
+ "ProviderBinding",
23
+ "ProviderDecl",
24
+ "ProviderDiagnostic",
25
+ "ProviderRegistry",
26
+ "build_capability_registry",
27
+ ]
@@ -0,0 +1,101 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Literal
5
+
6
+ from pz_core.assembly.apps import AppRegistry
7
+ from pz_core.infra.settings import InfraComponent, InfraContext
8
+
9
+ CapabilityStatus = Literal["disabled", "enabled", "ready", "unavailable"]
10
+
11
+
12
+ @dataclass(frozen=True, slots=True)
13
+ class CapabilityState:
14
+ name: str
15
+ owner: str
16
+ status: CapabilityStatus
17
+ reason: str | None = None
18
+
19
+ @property
20
+ def enabled(self) -> bool:
21
+ return self.status in {"enabled", "ready", "unavailable"}
22
+
23
+ @property
24
+ def ready(self) -> bool:
25
+ return self.status == "ready"
26
+
27
+
28
+ @dataclass(frozen=True, slots=True)
29
+ class CapabilityRegistry:
30
+ capabilities: tuple[CapabilityState, ...]
31
+
32
+ def get(self, name: str) -> CapabilityState | None:
33
+ for capability in self.capabilities:
34
+ if capability.name == name:
35
+ return capability
36
+ return None
37
+
38
+ @property
39
+ def enabled_names(self) -> tuple[str, ...]:
40
+ return tuple(capability.name for capability in self.capabilities if capability.enabled)
41
+
42
+ @property
43
+ def ready_names(self) -> tuple[str, ...]:
44
+ return tuple(capability.name for capability in self.capabilities if capability.ready)
45
+
46
+ def statuses(self) -> dict[str, CapabilityStatus]:
47
+ return {capability.name: capability.status for capability in self.capabilities}
48
+
49
+
50
+ def _component_status(component: InfraComponent) -> CapabilityStatus:
51
+ status = str(component.status or "").strip()
52
+ if status in {"disabled", "enabled", "ready", "unavailable"}:
53
+ return status # type: ignore[return-value]
54
+ return "enabled" if component.enabled else "disabled"
55
+
56
+
57
+ def _component_capability(
58
+ *,
59
+ name: str,
60
+ owner: str,
61
+ component: InfraComponent,
62
+ ) -> CapabilityState:
63
+ return CapabilityState(
64
+ name=name,
65
+ owner=owner,
66
+ status=_component_status(component),
67
+ reason=component.reason,
68
+ )
69
+
70
+
71
+ def build_capability_registry(
72
+ *,
73
+ infra: InfraContext,
74
+ app_registry: AppRegistry,
75
+ ) -> CapabilityRegistry:
76
+ capabilities: list[CapabilityState] = []
77
+
78
+ capabilities.append(_component_capability(name="health", owner="runtime.health", component=infra.health))
79
+ capabilities.append(_component_capability(name="database", owner="infra.database", component=infra.database))
80
+ capabilities.append(_component_capability(name="cache", owner="infra.cache", component=infra.cache))
81
+ capabilities.append(_component_capability(name="metrics", owner="infra.metrics", component=infra.metrics))
82
+ capabilities.append(_component_capability(name="tracing", owner="infra.tracing", component=infra.tracing))
83
+ capabilities.append(_component_capability(name="storage", owner="infra.storage", component=infra.storage))
84
+ capabilities.append(
85
+ CapabilityState(
86
+ name="resources",
87
+ owner="assembly.resources",
88
+ status="ready",
89
+ )
90
+ )
91
+ capabilities.append(_component_capability(name="mail", owner="infra.mail", component=infra.mail))
92
+
93
+ for app in app_registry.apps:
94
+ capabilities.append(
95
+ CapabilityState(
96
+ name=f"app:{app.app_id}",
97
+ owner=app.module_path,
98
+ status="enabled",
99
+ )
100
+ )
101
+ return CapabilityRegistry(capabilities=tuple(capabilities))