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,569 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import re
5
+ import tomllib
6
+ from dataclasses import dataclass
7
+ from pathlib import Path, PurePosixPath
8
+ from typing import TYPE_CHECKING
9
+
10
+ from pz_core.core.errors import PzError
11
+
12
+ from .checks import CheckItem
13
+
14
+ if TYPE_CHECKING:
15
+ from pz_core.assembly.app_discovery import VisibleAppProjection
16
+ from pz_core.authoring.dev_git import DevGitService
17
+ from pz_core.authoring.dev_manifest import DevBinding, DevManifest
18
+
19
+
20
+ BLOCKING_DEV_SOURCE_CODES = frozenset(
21
+ {
22
+ "PZ_CHECK_DEV_MANIFEST_INVALID",
23
+ "PZ_CHECK_DEV_CHECKOUT_MISSING",
24
+ "PZ_CHECK_DEV_BINDING_LINK_INVALID",
25
+ "PZ_CHECK_DEV_BINDING_OVERLAP",
26
+ "PZ_CHECK_DEV_APP_DUPLICATE",
27
+ }
28
+ )
29
+
30
+ _BINDING_OWNER = re.compile(r"\$\.bindings\.([a-z][a-z0-9_]*)")
31
+ _RESOLUTION_ERRORS = (OSError, RuntimeError)
32
+
33
+
34
+ @dataclass(frozen=True, slots=True)
35
+ class _UvExpectation:
36
+ distribution: str
37
+ owner: str
38
+
39
+
40
+ def _item(
41
+ *,
42
+ code: str,
43
+ severity: str,
44
+ owner: str,
45
+ scope: str,
46
+ message: str,
47
+ expected: str | None,
48
+ actual: str | None,
49
+ repair_command: str | None,
50
+ ok: bool = False,
51
+ ) -> CheckItem:
52
+ return CheckItem(
53
+ severity=severity,
54
+ code=code,
55
+ owner=owner,
56
+ scope=scope,
57
+ message=message,
58
+ ok=ok,
59
+ expected=expected,
60
+ actual=actual,
61
+ repair_command=repair_command,
62
+ )
63
+
64
+
65
+ def _binding_key_from_manifest_error(message: str) -> str | None:
66
+ match = _BINDING_OWNER.search(message)
67
+ return None if match is None else match.group(1)
68
+
69
+
70
+ def _manifest_error_item(exc: PzError) -> CheckItem:
71
+ if "overlaps" in exc.message:
72
+ binding_key = _binding_key_from_manifest_error(exc.message) or "unknown"
73
+ return _item(
74
+ code="PZ_CHECK_DEV_BINDING_OVERLAP",
75
+ severity="error",
76
+ owner=f"dev.binding.{binding_key}",
77
+ scope="dev.bindings",
78
+ message="Development bindings overlap in the typed v5 manifest.",
79
+ expected="non-overlapping binding links and sources",
80
+ actual=exc.message,
81
+ repair_command=f"pz dev unlink {binding_key} --project-dir .",
82
+ )
83
+ return _item(
84
+ code="PZ_CHECK_DEV_MANIFEST_INVALID",
85
+ severity="error",
86
+ owner="dev.manifest",
87
+ scope="dev.manifest",
88
+ message="Development source manifest is not a valid typed v5 manifest.",
89
+ expected="typed schema_version=5 manifest",
90
+ actual=exc.message,
91
+ repair_command="pz dev init --project-dir .",
92
+ )
93
+
94
+
95
+ def _checkout_state_name(path: Path) -> str:
96
+ if path.is_symlink():
97
+ return "shared-symlink" if path.is_dir() else "broken-symlink"
98
+ if not path.exists():
99
+ return "missing"
100
+ if not path.is_dir():
101
+ return "not-directory"
102
+ return "unreadable"
103
+
104
+
105
+ def _repo_items(
106
+ project_dir: Path,
107
+ manifest: DevManifest,
108
+ git_service: DevGitService,
109
+ ) -> tuple[list[CheckItem], frozenset[str]]:
110
+ items: list[CheckItem] = []
111
+ unavailable: set[str] = set()
112
+ for repo_key, repo in sorted(manifest.repos.items()):
113
+ checkout = project_dir / Path(*repo.checkout.parts)
114
+ owner = f"dev.repo.{repo_key}"
115
+ shared_checkout = checkout.is_symlink()
116
+ if not checkout.is_dir():
117
+ unavailable.add(repo_key)
118
+ items.append(
119
+ _item(
120
+ code="PZ_CHECK_DEV_CHECKOUT_MISSING",
121
+ severity="error",
122
+ owner=owner,
123
+ scope="dev.repo",
124
+ message=f"Managed checkout {repo_key!r} is unavailable.",
125
+ expected=repo.checkout.as_posix(),
126
+ actual=_checkout_state_name(checkout),
127
+ repair_command=f"pz dev add {repo_key} --project-dir .",
128
+ )
129
+ )
130
+ continue
131
+ try:
132
+ state = (
133
+ git_service.inspect_shared(
134
+ checkout,
135
+ expected_source=repo.source,
136
+ )
137
+ if shared_checkout
138
+ else git_service.inspect(checkout)
139
+ )
140
+ except PzError:
141
+ unavailable.add(repo_key)
142
+ items.append(
143
+ _item(
144
+ code="PZ_CHECK_DEV_CHECKOUT_MISSING",
145
+ severity="error",
146
+ owner=owner,
147
+ scope="dev.repo",
148
+ message=f"Managed checkout {repo_key!r} is not a readable Git checkout.",
149
+ expected=repo.checkout.as_posix(),
150
+ actual="not-git",
151
+ repair_command=f"pz dev add {repo_key} --project-dir .",
152
+ )
153
+ )
154
+ continue
155
+ if shared_checkout:
156
+ continue
157
+ if state.branch != repo.branch:
158
+ items.append(
159
+ _item(
160
+ code="PZ_CHECK_DEV_BRANCH_DRIFT",
161
+ severity="error",
162
+ owner=owner,
163
+ scope="dev.repo",
164
+ message=f"Managed checkout {repo_key!r} is on the wrong branch.",
165
+ expected=repo.branch,
166
+ actual=state.branch or "detached HEAD",
167
+ repair_command=f"pz dev branch {repo_key} --project-dir .",
168
+ )
169
+ )
170
+ if state.dirty:
171
+ items.append(
172
+ _item(
173
+ code="PZ_CHECK_DEV_WORKTREE_DIRTY",
174
+ severity="warning",
175
+ owner=owner,
176
+ scope="dev.repo",
177
+ message=f"Managed checkout {repo_key!r} has local changes.",
178
+ expected="clean",
179
+ actual="dirty",
180
+ repair_command=(
181
+ f"git -C {repo.checkout.as_posix()} status --short"
182
+ ),
183
+ )
184
+ )
185
+ return items, frozenset(unavailable)
186
+
187
+
188
+ def _join_binding_source(
189
+ project_dir: Path,
190
+ manifest: DevManifest,
191
+ binding: DevBinding,
192
+ ) -> Path:
193
+ if binding.source_kind == "link":
194
+ source = Path(binding.source)
195
+ else:
196
+ assert binding.repo_key is not None
197
+ source = project_dir / Path(*manifest.repos[binding.repo_key].checkout.parts)
198
+ if binding.subpath == PurePosixPath("."):
199
+ return source
200
+ return source / Path(*binding.subpath.parts)
201
+
202
+
203
+ def _relative_link_target(link: Path, target: Path) -> str:
204
+ return Path(os.path.relpath(target, start=link.parent)).as_posix()
205
+
206
+
207
+ def _link_actual_state(link: Path, expected: Path, expected_target: str) -> str | None:
208
+ if not os.path.lexists(link):
209
+ return "missing"
210
+ if not link.is_symlink():
211
+ return "not-symlink"
212
+ try:
213
+ stored_target = os.readlink(link)
214
+ actual = link.resolve(strict=True)
215
+ expected_realpath = expected.resolve(strict=True)
216
+ except _RESOLUTION_ERRORS:
217
+ return "broken"
218
+ if (
219
+ Path(stored_target).is_absolute()
220
+ or "\\" in stored_target
221
+ or stored_target != expected_target
222
+ or actual != expected_realpath
223
+ ):
224
+ return "misdirected"
225
+ return None
226
+
227
+
228
+ def _binding_link_items(
229
+ project_dir: Path,
230
+ manifest: DevManifest,
231
+ unavailable_repos: frozenset[str],
232
+ ) -> list[CheckItem]:
233
+ items: list[CheckItem] = []
234
+ for binding_key, binding in sorted(manifest.bindings.items()):
235
+ if binding.repo_key in unavailable_repos:
236
+ continue
237
+ link = project_dir / Path(*binding.link.parts)
238
+ expected = _join_binding_source(project_dir, manifest, binding)
239
+ expected_target = _relative_link_target(link, expected)
240
+ actual = _link_actual_state(link, expected, expected_target)
241
+ if actual is None:
242
+ continue
243
+ items.append(
244
+ _item(
245
+ code="PZ_CHECK_DEV_BINDING_LINK_INVALID",
246
+ severity="error",
247
+ owner=f"dev.binding.{binding_key}",
248
+ scope="dev.binding",
249
+ message=f"Managed binding {binding_key!r} does not match its v5 declaration.",
250
+ expected=expected_target,
251
+ actual=actual,
252
+ repair_command=f"pz dev add {binding_key} --project-dir .",
253
+ )
254
+ )
255
+ return items
256
+
257
+
258
+ def _duplicate_binding_key(
259
+ project_dir: Path,
260
+ manifest: DevManifest,
261
+ message: str,
262
+ ) -> str | None:
263
+ for binding_key, binding in sorted(manifest.bindings.items()):
264
+ link = project_dir / Path(*binding.link.parts)
265
+ if str(link) in message:
266
+ return binding_key
267
+ return None
268
+
269
+
270
+ def _projection_error_item(
271
+ project_dir: Path,
272
+ manifest: DevManifest | None,
273
+ exc: PzError,
274
+ ) -> CheckItem:
275
+ if exc.code == "PZ_VISIBLE_APP_DUPLICATE":
276
+ app_id = exc.owner
277
+ binding_key = (
278
+ None
279
+ if manifest is None
280
+ else _duplicate_binding_key(project_dir, manifest, exc.message)
281
+ )
282
+ repair = (
283
+ f"pz dev unlink {binding_key} --project-dir ."
284
+ if binding_key is not None
285
+ else f"find apps -path '*/{app_id}/apps.py' -print"
286
+ )
287
+ return _item(
288
+ code="PZ_CHECK_DEV_APP_DUPLICATE",
289
+ severity="error",
290
+ owner=f"dev.app.{app_id}",
291
+ scope="dev.apps",
292
+ message=f"Visible app {app_id!r} is exposed more than once.",
293
+ expected="one visible projection per app_id",
294
+ actual=f"duplicate app_id={app_id}",
295
+ repair_command=repair,
296
+ )
297
+ binding_key = exc.owner
298
+ return _item(
299
+ code="PZ_CHECK_DEV_BINDING_LINK_INVALID",
300
+ severity="error",
301
+ owner=f"dev.binding.{binding_key}",
302
+ scope="dev.binding",
303
+ message=f"Managed binding {binding_key!r} does not expose a formal visible app.",
304
+ expected="formal visible projection matching the v5 binding",
305
+ actual="invalid-projection",
306
+ repair_command=f"pz dev add {binding_key} --project-dir .",
307
+ )
308
+
309
+
310
+ def _read_distribution_name(path: Path) -> str | None:
311
+ try:
312
+ payload = tomllib.loads(path.read_text(encoding="utf-8"))
313
+ except (OSError, UnicodeError, tomllib.TOMLDecodeError):
314
+ return None
315
+ project = payload.get("project")
316
+ if not isinstance(project, dict):
317
+ return None
318
+ name = project.get("name")
319
+ if not isinstance(name, str) or not name.strip():
320
+ return None
321
+ return name.strip()
322
+
323
+
324
+ def _bootstrap_expectations(
325
+ manifest: DevManifest,
326
+ ) -> list[_UvExpectation]:
327
+ from pz_core.project_sources import load_official_source_catalog
328
+
329
+ expectations: list[_UvExpectation] = []
330
+ catalog = load_official_source_catalog()
331
+ for repo_key, repo in sorted(manifest.repos.items()):
332
+ root = catalog.get(repo_key)
333
+ if root is None or not root.bootstrap:
334
+ continue
335
+ for distribution, child in sorted(root.children.items()):
336
+ if child.kind != "project":
337
+ continue
338
+ expectations.append(
339
+ _UvExpectation(
340
+ distribution=distribution,
341
+ owner=f"dev.repo.{repo_key}",
342
+ )
343
+ )
344
+ return expectations
345
+
346
+
347
+ def _binding_expectations(
348
+ project_dir: Path,
349
+ projections: tuple[VisibleAppProjection, ...],
350
+ ) -> list[_UvExpectation]:
351
+ expectations: list[_UvExpectation] = []
352
+ for projection in projections:
353
+ if projection.binding_key is None:
354
+ continue
355
+ distribution = _read_distribution_name(
356
+ projection.source_root / "pyproject.toml"
357
+ )
358
+ if distribution is None:
359
+ continue
360
+ expectations.append(
361
+ _UvExpectation(
362
+ distribution=distribution,
363
+ owner=f"dev.binding.{projection.binding_key}",
364
+ )
365
+ )
366
+ return expectations
367
+
368
+
369
+ def _read_uv_sources(project_dir: Path) -> dict[str, object]:
370
+ path = project_dir / "pyproject.toml"
371
+ try:
372
+ payload = tomllib.loads(path.read_text(encoding="utf-8"))
373
+ except (OSError, UnicodeError, tomllib.TOMLDecodeError):
374
+ return {}
375
+ tool = payload.get("tool")
376
+ if not isinstance(tool, dict):
377
+ return {}
378
+ uv = tool.get("uv")
379
+ if not isinstance(uv, dict):
380
+ return {}
381
+ sources = uv.get("sources")
382
+ if not isinstance(sources, dict):
383
+ return {}
384
+ return {str(key): value for key, value in sources.items()}
385
+
386
+
387
+ def _uv_source_state(value: object) -> tuple[str | None, bool | None]:
388
+ if not isinstance(value, dict):
389
+ return None, None
390
+ path = value.get("path")
391
+ editable = value.get("editable")
392
+ return (
393
+ path.strip() if isinstance(path, str) and path.strip() else None,
394
+ editable if type(editable) is bool else None,
395
+ )
396
+
397
+
398
+ def _format_uv_state(path: str | None, editable: bool | None) -> str:
399
+ if path is None:
400
+ return "missing"
401
+ editable_value = (
402
+ "true" if editable is True else "false" if editable is False else "missing"
403
+ )
404
+ return f"path={path}; editable={editable_value}"
405
+
406
+
407
+ def _display_uv_path(project_dir: Path, raw_path: str | None) -> str | None:
408
+ if raw_path is None:
409
+ return None
410
+ candidate = Path(raw_path).expanduser()
411
+ if not candidate.is_absolute():
412
+ return raw_path
413
+ try:
414
+ return candidate.relative_to(project_dir).as_posix()
415
+ except ValueError:
416
+ return "<absolute-path>"
417
+
418
+
419
+ def _uv_items(
420
+ project_dir: Path,
421
+ manifest: DevManifest,
422
+ projections: tuple[VisibleAppProjection, ...],
423
+ ) -> list[CheckItem]:
424
+ from pz_core.authoring.app_init_service import build_app_init_source_plan
425
+
426
+ owners = {
427
+ item.distribution: item
428
+ for item in (
429
+ *_bootstrap_expectations(manifest),
430
+ *_binding_expectations(project_dir, projections),
431
+ )
432
+ }
433
+ actual = _read_uv_sources(project_dir)
434
+ try:
435
+ plan = build_app_init_source_plan(
436
+ project_dir,
437
+ current_sources=actual,
438
+ action="check_dev_sources",
439
+ )
440
+ except PzError as exc:
441
+ return [
442
+ _item(
443
+ code="PZ_CHECK_DEV_UV_SOURCE_DRIFT",
444
+ severity="error",
445
+ owner="dev.uv.plan",
446
+ scope="dev.uv_sources",
447
+ message="uv sources cannot be compiled from the v5 source bindings.",
448
+ expected="valid app-init source plan",
449
+ actual=f"{exc.code}: {exc.message}",
450
+ repair_command="pz app init --project-dir .",
451
+ )
452
+ ]
453
+ items: list[CheckItem] = []
454
+ for distribution, binding in sorted(plan.desired_sources.items()):
455
+ actual_path, editable = _uv_source_state(actual.get(distribution))
456
+ expected_path = binding.path
457
+ if actual_path == expected_path and editable is True:
458
+ continue
459
+ expectation = owners.get(distribution)
460
+ items.append(
461
+ _item(
462
+ code="PZ_CHECK_DEV_UV_SOURCE_DRIFT",
463
+ severity="error",
464
+ owner=(
465
+ expectation.owner
466
+ if expectation is not None
467
+ else f"dev.uv.{distribution}"
468
+ ),
469
+ scope="dev.uv_sources",
470
+ message=f"uv source {distribution!r} does not match its v5 source binding.",
471
+ expected=_format_uv_state(expected_path, True),
472
+ actual=_format_uv_state(
473
+ _display_uv_path(project_dir, actual_path),
474
+ editable,
475
+ ),
476
+ repair_command="pz app init --project-dir .",
477
+ )
478
+ )
479
+ for distribution in plan.stale_source_keys:
480
+ value = actual.get(distribution)
481
+ actual_path, editable = _uv_source_state(value)
482
+ items.append(
483
+ _item(
484
+ code="PZ_CHECK_DEV_UV_SOURCE_DRIFT",
485
+ severity="error",
486
+ owner=f"dev.uv.{distribution}",
487
+ scope="dev.uv_sources",
488
+ message=f"uv source {distribution!r} has no v5 source owner.",
489
+ expected="absent",
490
+ actual=_format_uv_state(
491
+ _display_uv_path(project_dir, actual_path),
492
+ editable,
493
+ ),
494
+ repair_command="pz app init --project-dir .",
495
+ )
496
+ )
497
+ return items
498
+
499
+
500
+ def build_dev_source_check_items(
501
+ project_dir: str | Path,
502
+ *,
503
+ git_service: DevGitService | None = None,
504
+ ) -> tuple[CheckItem, ...]:
505
+ from pz_core.assembly.app_discovery import iter_visible_app_projections
506
+ from pz_core.authoring.dev_git import DevGitService
507
+ from pz_core.authoring.dev_manifest import load_dev_manifest
508
+
509
+ project_root = Path(project_dir).expanduser().resolve(strict=False)
510
+ try:
511
+ manifest = load_dev_manifest(project_root)
512
+ except PzError as exc:
513
+ return (_manifest_error_item(exc),)
514
+
515
+ items: list[CheckItem] = []
516
+ service = git_service or DevGitService()
517
+ if manifest is not None:
518
+ repo_items, unavailable_repos = _repo_items(
519
+ project_root,
520
+ manifest,
521
+ service,
522
+ )
523
+ items.extend(repo_items)
524
+ link_items = _binding_link_items(
525
+ project_root,
526
+ manifest,
527
+ unavailable_repos,
528
+ )
529
+ items.extend(link_items)
530
+ if link_items or unavailable_repos:
531
+ return tuple(items)
532
+
533
+ try:
534
+ projections = iter_visible_app_projections(project_root)
535
+ except PzError as exc:
536
+ items.append(_projection_error_item(project_root, manifest, exc))
537
+ return tuple(items)
538
+
539
+ if manifest is None:
540
+ return tuple(items)
541
+ items.extend(_uv_items(project_root, manifest, projections))
542
+ if items:
543
+ return tuple(items)
544
+ return (
545
+ _item(
546
+ code="PZ_CHECK_DEV_SOURCES_VALID",
547
+ severity="info",
548
+ owner="dev.sources",
549
+ scope="dev.sources",
550
+ message="Development source manifest, checkouts, links, apps, and uv sources are aligned.",
551
+ expected="all v5 development sources aligned",
552
+ actual="valid",
553
+ repair_command=None,
554
+ ok=True,
555
+ ),
556
+ )
557
+
558
+
559
+ def has_blocking_dev_source_failures(checks: tuple[CheckItem, ...]) -> bool:
560
+ return any(
561
+ not item.ok and item.code in BLOCKING_DEV_SOURCE_CODES for item in checks
562
+ )
563
+
564
+
565
+ __all__ = [
566
+ "BLOCKING_DEV_SOURCE_CODES",
567
+ "build_dev_source_check_items",
568
+ "has_blocking_dev_source_failures",
569
+ ]
@@ -0,0 +1,5 @@
1
+ from __future__ import annotations
2
+
3
+ from .compiler import EventDeclarationSource, collect_event_declarations, compile_event_registry
4
+
5
+ __all__ = ["EventDeclarationSource", "collect_event_declarations", "compile_event_registry"]