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,400 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from pz_core.assembly.settings import SettingsSnapshot
6
+ from pz_core.core.errors import PzError
7
+ from pz_core.core.routing import RouteDecl, RouteManifest
8
+
9
+
10
+ def _read_path_segment(part: object) -> str:
11
+ if not isinstance(part, str):
12
+ raise PzError(
13
+ code="PZ_ROUTE_PATH_SEGMENT_INVALID",
14
+ message="Route path segments must be strings.",
15
+ stage="routes",
16
+ owner="assembly.routes",
17
+ action="compile_route_manifest",
18
+ )
19
+ return part.strip("/")
20
+
21
+
22
+ def _join_path(*parts: str) -> str:
23
+ cleaned = [segment for segment in (_read_path_segment(part) for part in parts) if segment]
24
+ if not cleaned:
25
+ return "/"
26
+ return "/" + "/".join(cleaned)
27
+
28
+
29
+ def _languages(settings: SettingsSnapshot) -> tuple[str, ...]:
30
+ raw = settings.get("routing", "all_supported_languages", default=None)
31
+ if raw is None:
32
+ raw = settings.get("i18n", "languages", default=None)
33
+ if isinstance(raw, list):
34
+ out: list[str] = []
35
+ for index, item in enumerate(raw):
36
+ if not isinstance(item, str):
37
+ raise PzError(
38
+ code="PZ_ROUTING_SUPPORTED_LANGUAGES_ITEM_INVALID",
39
+ message=(
40
+ f"routing.all_supported_languages entry at index {index} must be a non-empty string."
41
+ ),
42
+ stage="routes",
43
+ owner="assembly.routes",
44
+ action="compile_route_manifest",
45
+ )
46
+ value = item.strip()
47
+ if not value:
48
+ raise PzError(
49
+ code="PZ_ROUTING_SUPPORTED_LANGUAGES_ITEM_INVALID",
50
+ message=(
51
+ f"routing.all_supported_languages entry at index {index} must be a non-empty string."
52
+ ),
53
+ stage="routes",
54
+ owner="assembly.routes",
55
+ action="compile_route_manifest",
56
+ )
57
+ out.append(value)
58
+ if out:
59
+ return tuple(out)
60
+ raise PzError(
61
+ code="PZ_ROUTING_SUPPORTED_LANGUAGES_INVALID",
62
+ message="routing.all_supported_languages must declare at least one language when configured.",
63
+ stage="routes",
64
+ owner="assembly.routes",
65
+ action="compile_route_manifest",
66
+ )
67
+ return ("en",)
68
+
69
+
70
+ def _language_aliases(settings: SettingsSnapshot, languages: tuple[str, ...]) -> dict[str, str]:
71
+ raw = settings.get("routing", "language_aliases", default=None)
72
+ if raw is None:
73
+ return {}
74
+ if not isinstance(raw, dict):
75
+ raise PzError(
76
+ code="PZ_ROUTING_LANGUAGE_ALIASES_INVALID",
77
+ message="routing.language_aliases must be an object mapping alias language segments to supported languages.",
78
+ stage="routes",
79
+ owner="assembly.routes",
80
+ action="compile_route_manifest",
81
+ )
82
+ supported = {item.casefold(): item for item in languages if item}
83
+ aliases: dict[str, str] = {}
84
+ for raw_alias, raw_target in raw.items():
85
+ if not isinstance(raw_alias, str) or not raw_alias.strip():
86
+ raise PzError(
87
+ code="PZ_ROUTING_LANGUAGE_ALIAS_INVALID",
88
+ message="routing.language_aliases keys must be non-empty strings.",
89
+ stage="routes",
90
+ owner="assembly.routes",
91
+ action="compile_route_manifest",
92
+ )
93
+ if not isinstance(raw_target, str) or not raw_target.strip():
94
+ raise PzError(
95
+ code="PZ_ROUTING_LANGUAGE_ALIAS_TARGET_INVALID",
96
+ message="routing.language_aliases values must be non-empty supported language strings.",
97
+ stage="routes",
98
+ owner="assembly.routes",
99
+ action="compile_route_manifest",
100
+ )
101
+ alias = raw_alias.strip().strip("/")
102
+ target = raw_target.strip().strip("/")
103
+ canonical_target = supported.get(target.casefold())
104
+ if not canonical_target:
105
+ raise PzError(
106
+ code="PZ_ROUTING_LANGUAGE_ALIAS_TARGET_UNSUPPORTED",
107
+ message=f"routing.language_aliases target '{target}' must be listed in routing.all_supported_languages.",
108
+ stage="routes",
109
+ owner="assembly.routes",
110
+ action="compile_route_manifest",
111
+ )
112
+ if alias.casefold() == canonical_target.casefold():
113
+ raise PzError(
114
+ code="PZ_ROUTING_LANGUAGE_ALIAS_REDUNDANT",
115
+ message=f"routing.language_aliases alias '{alias}' must not point to itself.",
116
+ stage="routes",
117
+ owner="assembly.routes",
118
+ action="compile_route_manifest",
119
+ )
120
+ aliases[alias] = canonical_target
121
+ return aliases
122
+
123
+
124
+ def _read_required_string(
125
+ value: object,
126
+ *,
127
+ code: str,
128
+ message: str,
129
+ owner: str,
130
+ ) -> str:
131
+ if not isinstance(value, str) or not value.strip():
132
+ raise PzError(
133
+ code=code,
134
+ message=message,
135
+ stage="routes",
136
+ owner=owner,
137
+ action="compile_route_manifest",
138
+ )
139
+ return value.strip()
140
+
141
+
142
+ def _read_optional_string(
143
+ value: object,
144
+ *,
145
+ default: str,
146
+ code: str,
147
+ message: str,
148
+ owner: str,
149
+ ) -> str:
150
+ if value is None:
151
+ return default
152
+ if not isinstance(value, str) or not value.strip():
153
+ raise PzError(
154
+ code=code,
155
+ message=message,
156
+ stage="routes",
157
+ owner=owner,
158
+ action="compile_route_manifest",
159
+ )
160
+ return value.strip()
161
+
162
+
163
+ def _read_required_path(
164
+ value: object,
165
+ *,
166
+ code: str,
167
+ message: str,
168
+ owner: str,
169
+ ) -> str:
170
+ path = _read_required_string(
171
+ value,
172
+ code=code,
173
+ message=message,
174
+ owner=owner,
175
+ )
176
+ if not path.startswith("/"):
177
+ raise PzError(
178
+ code=code,
179
+ message=message,
180
+ stage="routes",
181
+ owner=owner,
182
+ action="compile_route_manifest",
183
+ )
184
+ return path
185
+
186
+
187
+ def _read_optional_path(
188
+ value: object,
189
+ *,
190
+ default: str,
191
+ code: str,
192
+ message: str,
193
+ owner: str,
194
+ ) -> str:
195
+ if value is None:
196
+ return default
197
+ return _read_required_path(
198
+ value,
199
+ code=code,
200
+ message=message,
201
+ owner=owner,
202
+ )
203
+
204
+
205
+ def _read_optional_bool(
206
+ value: object,
207
+ *,
208
+ default: bool,
209
+ code: str,
210
+ message: str,
211
+ owner: str,
212
+ ) -> bool:
213
+ if value is None:
214
+ return default
215
+ if not isinstance(value, bool):
216
+ raise PzError(
217
+ code=code,
218
+ message=message,
219
+ stage="routes",
220
+ owner=owner,
221
+ action="compile_route_manifest",
222
+ )
223
+ return value
224
+
225
+
226
+ def _expand_route(
227
+ item: dict[str, Any],
228
+ *,
229
+ default_base_prefix: str,
230
+ api_version_prefix: str,
231
+ languages: tuple[str, ...],
232
+ ) -> tuple[RouteDecl, ...]:
233
+ owner = _read_optional_string(
234
+ item.get("owner"),
235
+ default="runtime",
236
+ code="PZ_ROUTE_OWNER_INVALID",
237
+ message="Route declarations must declare owner as a non-empty string when provided.",
238
+ owner="assembly.routes",
239
+ )
240
+ raw_path = item.get("path")
241
+ if raw_path is None:
242
+ raise PzError(
243
+ code="PZ_ROUTE_PATH_MISSING",
244
+ message="Route declarations must declare a non-empty path.",
245
+ stage="routes",
246
+ owner=owner,
247
+ action="compile_route_manifest",
248
+ )
249
+ raw_path = _read_required_path(
250
+ raw_path,
251
+ code="PZ_ROUTE_PATH_INVALID",
252
+ message="Route declarations must declare path as a slash-prefixed non-empty string.",
253
+ owner=owner,
254
+ )
255
+ source_path = raw_path
256
+ path = source_path
257
+ base_prefix = _read_optional_path(
258
+ item.get("base_prefix"),
259
+ default=default_base_prefix,
260
+ code="PZ_ROUTE_BASE_PREFIX_INVALID",
261
+ message=(
262
+ f"Route '{source_path}' base_prefix must be a slash-prefixed non-empty string when provided."
263
+ ),
264
+ owner=owner,
265
+ )
266
+ if _read_optional_bool(
267
+ item.get("api_version"),
268
+ default=False,
269
+ code="PZ_ROUTE_API_VERSION_INVALID",
270
+ message=f"Route '{source_path}' api_version must be a boolean when provided.",
271
+ owner=owner,
272
+ ):
273
+ path = _join_path(api_version_prefix, path)
274
+ if base_prefix:
275
+ path = _join_path(base_prefix, path)
276
+
277
+ method = _read_optional_string(
278
+ item.get("method"),
279
+ default="GET",
280
+ code="PZ_ROUTE_METHOD_INVALID",
281
+ message=f"Route '{source_path}' method must be a non-empty string when provided.",
282
+ owner=owner,
283
+ ).upper()
284
+ name = _read_optional_string(
285
+ item.get("name"),
286
+ default=f"{owner}:{path}",
287
+ code="PZ_ROUTE_NAME_INVALID",
288
+ message=f"Route '{source_path}' name must be a non-empty string when provided.",
289
+ owner=owner,
290
+ )
291
+ i18n_aware = _read_optional_bool(
292
+ item.get("i18n_aware"),
293
+ default=False,
294
+ code="PZ_ROUTE_I18N_AWARE_INVALID",
295
+ message=f"Route '{source_path}' i18n_aware must be a boolean when provided.",
296
+ owner=owner,
297
+ )
298
+ if not i18n_aware:
299
+ return (RouteDecl(path=path, method=method, name=name, owner=owner, source_path=source_path),)
300
+
301
+ expanded: list[RouteDecl] = [
302
+ RouteDecl(path=path, method=method, name=name, owner=owner, source_path=source_path)
303
+ ]
304
+ for language in languages:
305
+ expanded.append(
306
+ RouteDecl(
307
+ path=_join_path(language, path),
308
+ method=method,
309
+ name=f"{name}:{language}",
310
+ owner=owner,
311
+ source_path=source_path,
312
+ )
313
+ )
314
+ return tuple(expanded)
315
+
316
+
317
+ def _validate_conflicts(routes: tuple[RouteDecl, ...], conflict_policy: str) -> None:
318
+ seen: dict[tuple[str, str], RouteDecl] = {}
319
+ duplicates: list[str] = []
320
+ for route in routes:
321
+ key = (route.method, route.path)
322
+ previous = seen.get(key)
323
+ if previous is not None:
324
+ duplicates.append(f"{route.method} {route.path} ({previous.owner}, {route.owner})")
325
+ continue
326
+ seen[key] = route
327
+ if duplicates and conflict_policy != "warn":
328
+ raise PzError(
329
+ code="PZ_ROUTE_CONFLICT",
330
+ message="Route conflict detected before runtime registration: " + ", ".join(duplicates),
331
+ stage="routes",
332
+ owner="assembly.routes",
333
+ action="compile_route_manifest",
334
+ )
335
+
336
+
337
+ def compile_route_manifest(settings: SettingsSnapshot) -> RouteManifest:
338
+ routes: list[RouteDecl] = []
339
+ conflict_policy = _read_optional_string(
340
+ settings.get("routing", "conflict_policy", default=None),
341
+ default="fail",
342
+ code="PZ_ROUTE_CONFLICT_POLICY_INVALID",
343
+ message="routing.conflict_policy must be one of: fail, warn.",
344
+ owner="assembly.routes",
345
+ ).lower()
346
+ if conflict_policy not in {"fail", "warn"}:
347
+ raise PzError(
348
+ code="PZ_ROUTE_CONFLICT_POLICY_INVALID",
349
+ message="routing.conflict_policy must be one of: fail, warn.",
350
+ stage="routes",
351
+ owner="assembly.routes",
352
+ action="compile_route_manifest",
353
+ )
354
+ default_base_prefix = _read_optional_path(
355
+ settings.get("routing", "base_prefix", default=None),
356
+ default="",
357
+ code="PZ_ROUTE_BASE_PREFIX_INVALID",
358
+ message="routing.base_prefix must be a slash-prefixed non-empty string when provided.",
359
+ owner="assembly.routes",
360
+ )
361
+ api_version_prefix = _read_optional_path(
362
+ settings.get("routing", "api_version_prefix", default=None),
363
+ default="/api/v1",
364
+ code="PZ_ROUTE_API_VERSION_PREFIX_INVALID",
365
+ message="routing.api_version_prefix must be a slash-prefixed non-empty string when provided.",
366
+ owner="assembly.routes",
367
+ )
368
+ languages = _languages(settings)
369
+ _language_aliases(settings, languages)
370
+
371
+ raw_routes = settings.get("routes", default=[])
372
+ if not isinstance(raw_routes, list):
373
+ raise PzError(
374
+ code="PZ_ROUTES_CONFIG_INVALID",
375
+ message="Routes configuration must be declared as an array.",
376
+ stage="routes",
377
+ owner="assembly.routes",
378
+ action="compile_route_manifest",
379
+ )
380
+ for index, item in enumerate(raw_routes):
381
+ if not isinstance(item, dict):
382
+ raise PzError(
383
+ code="PZ_ROUTE_ITEM_INVALID",
384
+ message=f"Route entry at index {index} must be a table/object declaration.",
385
+ stage="routes",
386
+ owner="assembly.routes",
387
+ action="compile_route_manifest",
388
+ )
389
+ routes.extend(
390
+ _expand_route(
391
+ item,
392
+ default_base_prefix=default_base_prefix,
393
+ api_version_prefix=api_version_prefix,
394
+ languages=languages,
395
+ )
396
+ )
397
+
398
+ manifest = RouteManifest(routes=tuple(routes), conflict_policy="warn" if conflict_policy == "warn" else "fail")
399
+ _validate_conflicts(manifest.routes, manifest.conflict_policy)
400
+ return manifest
@@ -0,0 +1,13 @@
1
+ from __future__ import annotations
2
+
3
+ from .compiler import (
4
+ RuntimeManifestContributionContext,
5
+ RuntimeManifestMap,
6
+ compile_runtime_manifests,
7
+ )
8
+
9
+ __all__ = [
10
+ "RuntimeManifestContributionContext",
11
+ "RuntimeManifestMap",
12
+ "compile_runtime_manifests",
13
+ ]
@@ -0,0 +1,159 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Mapping
4
+ from dataclasses import dataclass
5
+ from importlib import import_module
6
+ from typing import Any
7
+
8
+ from pz_core.assembly.apps import AppRegistry
9
+ from pz_core.assembly.project import ProjectContext
10
+ from pz_core.assembly.resources import ResourceManifest
11
+ from pz_core.assembly.settings import SettingsSnapshot
12
+ from pz_core.core.errors import PzError
13
+ from pz_core.core.extensions import ExtensionRegistry, RuntimeManifestContributionSpec
14
+
15
+
16
+ RuntimeManifestMap = dict[str, Any]
17
+
18
+
19
+ @dataclass(frozen=True, slots=True)
20
+ class RuntimeManifestContributionContext:
21
+ project: ProjectContext
22
+ settings: SettingsSnapshot
23
+ app_registry: AppRegistry
24
+ extension_registry: ExtensionRegistry
25
+ resource_manifest: ResourceManifest
26
+ runtime_manifests: Mapping[str, Any]
27
+
28
+
29
+ def _resolve_dotted(target: str) -> Any:
30
+ if ":" in target:
31
+ module_name, attr_name = target.split(":", 1)
32
+ else:
33
+ module_name, attr_name = target.rsplit(".", 1)
34
+ module = import_module(module_name)
35
+ return getattr(module, attr_name)
36
+
37
+
38
+ def _resolve_provider(provider: Any) -> Any:
39
+ if isinstance(provider, str):
40
+ provider = _resolve_dotted(provider)
41
+ if isinstance(provider, type):
42
+ return provider()
43
+ return provider
44
+
45
+
46
+ def _normalize_provider_result(payload: Any, *, owner: str) -> tuple[tuple[str, Any], ...]:
47
+ if payload in (None, (), []):
48
+ return ()
49
+ if isinstance(payload, tuple) and len(payload) == 2 and isinstance(payload[0], str):
50
+ return ((payload[0], payload[1]),)
51
+ if isinstance(payload, Mapping):
52
+ return tuple((str(key), value) for key, value in dict(payload).items())
53
+ if isinstance(payload, (list, tuple)):
54
+ out: list[tuple[str, Any]] = []
55
+ for item in payload:
56
+ if not isinstance(item, tuple) or len(item) != 2 or not isinstance(item[0], str):
57
+ raise PzError(
58
+ code="PZ_RUNTIME_MANIFEST_PROVIDER_RESULT_INVALID",
59
+ message=(
60
+ f"Runtime manifest provider '{owner}' must return a mapping or "
61
+ "(manifest_key, manifest) pairs."
62
+ ),
63
+ stage="runtime_manifests",
64
+ owner=owner,
65
+ action="compile_runtime_manifests",
66
+ )
67
+ out.append((item[0], item[1]))
68
+ return tuple(out)
69
+ manifest_key = str(getattr(payload, "manifest_key", "") or "").strip()
70
+ if manifest_key:
71
+ return ((manifest_key, payload),)
72
+ raise PzError(
73
+ code="PZ_RUNTIME_MANIFEST_PROVIDER_RESULT_INVALID",
74
+ message=(
75
+ f"Runtime manifest provider '{owner}' must return a mapping, a manifest object with "
76
+ "manifest_key, or (manifest_key, manifest) pairs."
77
+ ),
78
+ stage="runtime_manifests",
79
+ owner=owner,
80
+ action="compile_runtime_manifests",
81
+ )
82
+
83
+
84
+ def compile_runtime_manifests(
85
+ *,
86
+ project: ProjectContext,
87
+ settings: SettingsSnapshot,
88
+ app_registry: AppRegistry,
89
+ extension_registry: ExtensionRegistry,
90
+ resource_manifest: ResourceManifest,
91
+ ) -> RuntimeManifestMap:
92
+ manifests: RuntimeManifestMap = {}
93
+ providers = tuple(
94
+ spec
95
+ for spec in tuple(getattr(extension_registry, "extensions", ()) or ())
96
+ if isinstance(spec, RuntimeManifestContributionSpec)
97
+ )
98
+ ordered = sorted(
99
+ providers,
100
+ key=lambda item: (int(item.priority), str(item.owner_app), str(item.id)),
101
+ )
102
+ for spec in ordered:
103
+ provider = _resolve_provider(spec.provider)
104
+ compile_method = getattr(provider, "compile", None)
105
+ if not callable(compile_method):
106
+ raise PzError(
107
+ code="PZ_RUNTIME_MANIFEST_PROVIDER_INVALID",
108
+ message=f"Runtime manifest provider '{spec.id}' must declare compile(ctx).",
109
+ stage="runtime_manifests",
110
+ owner=spec.owner_app,
111
+ action="compile_runtime_manifests",
112
+ )
113
+ ctx = RuntimeManifestContributionContext(
114
+ project=project,
115
+ settings=settings,
116
+ app_registry=app_registry,
117
+ extension_registry=extension_registry,
118
+ resource_manifest=resource_manifest,
119
+ runtime_manifests=dict(manifests),
120
+ )
121
+ try:
122
+ items = _normalize_provider_result(compile_method(ctx), owner=spec.id)
123
+ except PzError:
124
+ raise
125
+ except Exception as exc:
126
+ raise PzError(
127
+ code="PZ_RUNTIME_MANIFEST_PROVIDER_FAILED",
128
+ message=f"Runtime manifest provider '{spec.id}' failed while compiling runtime manifests: {exc}",
129
+ stage="runtime_manifests",
130
+ owner=spec.owner_app,
131
+ action="compile_runtime_manifests",
132
+ ) from exc
133
+ for manifest_key, manifest in items:
134
+ key = str(manifest_key or "").strip()
135
+ if not key:
136
+ raise PzError(
137
+ code="PZ_RUNTIME_MANIFEST_KEY_INVALID",
138
+ message=f"Runtime manifest provider '{spec.id}' returned an empty manifest key.",
139
+ stage="runtime_manifests",
140
+ owner=spec.owner_app,
141
+ action="compile_runtime_manifests",
142
+ )
143
+ if key in manifests:
144
+ raise PzError(
145
+ code="PZ_RUNTIME_MANIFEST_DUPLICATE_KEY",
146
+ message=f"Runtime manifest key '{key}' is already compiled.",
147
+ stage="runtime_manifests",
148
+ owner=spec.owner_app,
149
+ action="compile_runtime_manifests",
150
+ )
151
+ manifests[key] = manifest
152
+ return manifests
153
+
154
+
155
+ __all__ = [
156
+ "RuntimeManifestContributionContext",
157
+ "RuntimeManifestMap",
158
+ "compile_runtime_manifests",
159
+ ]
@@ -0,0 +1,17 @@
1
+ from __future__ import annotations
2
+
3
+ from .compiler import (
4
+ SettingsSnapshot,
5
+ compile_settings_snapshot,
6
+ compile_settings_snapshot_from_payload,
7
+ load_project_env_file,
8
+ )
9
+ from .host_project_overrides import apply_host_project_env_overrides
10
+
11
+ __all__ = [
12
+ "SettingsSnapshot",
13
+ "apply_host_project_env_overrides",
14
+ "compile_settings_snapshot",
15
+ "compile_settings_snapshot_from_payload",
16
+ "load_project_env_file",
17
+ ]