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,5 @@
1
+ from __future__ import annotations
2
+
3
+ from .text import dedent
4
+
5
+ __all__ = ["dedent"]
@@ -0,0 +1,10 @@
1
+ from __future__ import annotations
2
+
3
+ import textwrap
4
+
5
+
6
+ def dedent(text: str) -> str:
7
+ return textwrap.dedent(text)
8
+
9
+
10
+ __all__ = ["dedent"]
@@ -0,0 +1,87 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import shutil
5
+ import subprocess
6
+ from dataclasses import dataclass
7
+ from pathlib import Path
8
+
9
+ from pz_core.runtime.errors import PzError
10
+
11
+
12
+ _OWNER = "pz_core.authoring.env"
13
+
14
+
15
+ @dataclass(frozen=True, slots=True)
16
+ class ProjectVirtualenvResult:
17
+ path: Path
18
+ created: bool
19
+
20
+
21
+ def ensure_project_virtualenv(project_dir: Path, *, action: str) -> ProjectVirtualenvResult:
22
+ venv_path = project_dir / ".venv"
23
+ if _is_valid_virtualenv(venv_path):
24
+ return ProjectVirtualenvResult(path=venv_path.resolve(), created=False)
25
+ uv_binary = _require_uv_binary(action=action)
26
+ venv_path.parent.mkdir(parents=True, exist_ok=True)
27
+ completed = subprocess.run(
28
+ [uv_binary, "venv", str(venv_path)],
29
+ cwd=str(project_dir),
30
+ check=False,
31
+ capture_output=True,
32
+ text=True,
33
+ env=os.environ.copy(),
34
+ )
35
+ if completed.returncode == 0 and _is_valid_virtualenv(venv_path):
36
+ return ProjectVirtualenvResult(path=venv_path.resolve(), created=True)
37
+ detail = (completed.stderr or completed.stdout or "failed to create virtual environment").strip()
38
+ raise PzError(
39
+ code="PZ_ENV_PROJECT_VENV_FAILED",
40
+ message=f"failed to prepare project virtual environment for {project_dir}.",
41
+ stage="cli",
42
+ owner=_OWNER,
43
+ action=action,
44
+ detail=detail,
45
+ )
46
+
47
+
48
+ def resolve_virtualenv_python(venv_path: Path, *, action: str) -> Path:
49
+ for candidate in (
50
+ venv_path / "bin" / "python",
51
+ venv_path / "bin" / "python3",
52
+ venv_path / "Scripts" / "python.exe",
53
+ ):
54
+ if candidate.is_file():
55
+ return candidate.absolute()
56
+ raise PzError(
57
+ code="PZ_ENV_PROJECT_VENV_INVALID",
58
+ message=f"virtual environment is missing a Python executable: {venv_path}",
59
+ stage="cli",
60
+ owner=_OWNER,
61
+ action=action,
62
+ )
63
+
64
+
65
+ def _require_uv_binary(*, action: str) -> str:
66
+ uv_binary = shutil.which("uv")
67
+ if uv_binary:
68
+ return uv_binary
69
+ raise PzError(
70
+ code="PZ_ENV_UV_MISSING",
71
+ message="required dependency backend was not found on PATH.",
72
+ stage="cli",
73
+ owner=_OWNER,
74
+ action=action,
75
+ )
76
+
77
+
78
+ def _is_valid_virtualenv(path: Path) -> bool:
79
+ candidates = (
80
+ path / "bin" / "python",
81
+ path / "bin" / "python3",
82
+ path / "Scripts" / "python.exe",
83
+ )
84
+ return any(candidate.is_file() for candidate in candidates)
85
+
86
+
87
+ __all__ = ["ProjectVirtualenvResult", "ensure_project_virtualenv", "resolve_virtualenv_python"]
@@ -0,0 +1,167 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from pathlib import Path
5
+ import tomllib
6
+
7
+
8
+ @dataclass(frozen=True, slots=True)
9
+ class WorkspacePackage:
10
+ key: str
11
+ dist: str
12
+ repo: Path
13
+
14
+ @property
15
+ def app_id(self) -> str:
16
+ return self.dist.replace("-", "_")
17
+
18
+
19
+ def _read_pyproject_payload(pyproject_path: Path) -> dict[str, object] | None:
20
+ if not pyproject_path.is_file():
21
+ return None
22
+ try:
23
+ payload = tomllib.loads(pyproject_path.read_text(encoding="utf-8"))
24
+ except Exception:
25
+ return None
26
+ return payload if isinstance(payload, dict) else None
27
+
28
+
29
+ def _read_project_name(pyproject_path: Path) -> str | None:
30
+ payload = _read_pyproject_payload(pyproject_path)
31
+ if payload is None:
32
+ return None
33
+ project = payload.get("project")
34
+ if not isinstance(project, dict):
35
+ return None
36
+ name = project.get("name")
37
+ if not isinstance(name, str) or not name.strip():
38
+ return None
39
+ return name.strip()
40
+
41
+
42
+ def candidate_workspace_projects(*, anchors: tuple[Path, ...] = ()) -> tuple[Path, ...]:
43
+ candidates: list[Path] = []
44
+ seen: set[Path] = set()
45
+ resolved_anchors = anchors or (Path.cwd(), Path(__file__).resolve())
46
+ for anchor in resolved_anchors:
47
+ current = anchor if anchor.is_dir() else anchor.parent
48
+ for parent in (current, *current.parents):
49
+ pyproject_path = (parent / "pyproject.toml").resolve()
50
+ if pyproject_path in seen or not pyproject_path.is_file():
51
+ continue
52
+ seen.add(pyproject_path)
53
+ candidates.append(pyproject_path.parent)
54
+ return tuple(candidates)
55
+
56
+
57
+ def _iter_workspace_packages_from_projects(
58
+ project_roots: tuple[Path, ...],
59
+ ) -> tuple[WorkspacePackage, ...]:
60
+ packages: list[WorkspacePackage] = []
61
+ seen_keys: set[str] = set()
62
+ seen_roots: set[Path] = set()
63
+
64
+ def _append_package(dist: str, repo: Path, *, key: str | None = None) -> None:
65
+ normalized_dist = dist.strip()
66
+ normalized_key = (key or normalized_dist).strip()
67
+ if not normalized_dist or not normalized_key:
68
+ return
69
+ dedupe_key = normalized_key.lower()
70
+ resolved_repo = repo.expanduser().resolve()
71
+ if dedupe_key in seen_keys:
72
+ return
73
+ seen_keys.add(dedupe_key)
74
+ packages.append(
75
+ WorkspacePackage(
76
+ key=normalized_key,
77
+ dist=normalized_dist,
78
+ repo=resolved_repo,
79
+ )
80
+ )
81
+
82
+ def _append_ancestor_workspace_roots(repo: Path, *, project_root: Path) -> None:
83
+ resolved_repo = repo.expanduser().resolve()
84
+ resolved_project_root = project_root.resolve()
85
+ for ancestor in resolved_repo.parents:
86
+ if ancestor == resolved_project_root:
87
+ break
88
+ if ancestor in seen_roots:
89
+ continue
90
+ dist = _read_project_name(ancestor / "pyproject.toml")
91
+ if dist is None:
92
+ continue
93
+ seen_roots.add(ancestor)
94
+ _append_package(dist, ancestor)
95
+
96
+ for project_root in project_roots:
97
+ project_root = project_root.expanduser().resolve()
98
+ pyproject_path = project_root / "pyproject.toml"
99
+ payload = _read_pyproject_payload(pyproject_path)
100
+ if payload is None:
101
+ continue
102
+ project_name = _read_project_name(pyproject_path)
103
+ if project_name is not None:
104
+ _append_package(project_name, project_root)
105
+ tool = payload.get("tool")
106
+ if not isinstance(tool, dict):
107
+ continue
108
+ uv = tool.get("uv")
109
+ if not isinstance(uv, dict):
110
+ continue
111
+ sources = uv.get("sources")
112
+ if not isinstance(sources, dict):
113
+ continue
114
+ for dist, raw_meta in sources.items():
115
+ if not isinstance(dist, str) or not isinstance(raw_meta, dict):
116
+ continue
117
+ raw_path = raw_meta.get("path")
118
+ if not isinstance(raw_path, str) or not raw_path.strip():
119
+ continue
120
+ repo = Path(raw_path.strip()).expanduser()
121
+ if not repo.is_absolute():
122
+ repo = (project_root / repo).resolve()
123
+ _append_package(dist, repo)
124
+ _append_ancestor_workspace_roots(repo, project_root=project_root)
125
+ return tuple(packages)
126
+
127
+
128
+ def iter_workspace_packages(*, anchors: tuple[Path, ...] = ()) -> tuple[WorkspacePackage, ...]:
129
+ return _iter_workspace_packages_from_projects(
130
+ candidate_workspace_projects(anchors=anchors)
131
+ )
132
+
133
+
134
+ def iter_workspace_packages_in_roots(
135
+ project_roots: tuple[Path, ...],
136
+ ) -> tuple[WorkspacePackage, ...]:
137
+ """Discover packages without walking outside the caller-provided roots."""
138
+ return _iter_workspace_packages_from_projects(project_roots)
139
+
140
+
141
+ def resolve_workspace_package(
142
+ identifier: str,
143
+ *,
144
+ anchors: tuple[Path, ...] = (),
145
+ ) -> WorkspacePackage | None:
146
+ normalized = identifier.strip().lower()
147
+ if not normalized:
148
+ return None
149
+ for package in iter_workspace_packages(anchors=anchors):
150
+ candidates = {
151
+ package.key.lower(),
152
+ package.dist.lower(),
153
+ package.app_id.lower(),
154
+ package.repo.name.lower(),
155
+ }
156
+ if normalized in candidates:
157
+ return package
158
+ return None
159
+
160
+
161
+ __all__ = [
162
+ "WorkspacePackage",
163
+ "candidate_workspace_projects",
164
+ "iter_workspace_packages",
165
+ "iter_workspace_packages_in_roots",
166
+ "resolve_workspace_package",
167
+ ]
pz_core/cli.py ADDED
@@ -0,0 +1,291 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import sys
5
+ from collections.abc import Sequence
6
+ from pathlib import Path
7
+
8
+ from pz_core.project_root_commands import discover_project_root_command_handlers, render_project_root_command_help
9
+ from pz_core.authoring.root_cli import get_root_command_handlers as _builtin_root_command_handlers
10
+ from pz_core.cli_options import option_shortcuts_help, resolve_program_name
11
+ from pz_core.root_cli import CommandPath, RootCommandHandler, discover_root_command_handlers
12
+ from pz_core.project_runtime_cli import handoff_to_project_runtime, provider_resolution_locked, resolve_cli_project_dir
13
+ from pz_core.runtime.cli.main import main as _core_main
14
+ from pz_core.runtime.environment_integrity import validate_current_environment
15
+ from pz_core.runtime.errors import PzError
16
+
17
+
18
+ def _is_help(value: str | None) -> bool:
19
+ return isinstance(value, str) and value.strip().lower() in {"-h", "--help", "help"}
20
+
21
+
22
+ def _is_root_help_request(argv: Sequence[str] | None = None) -> bool:
23
+ args = [str(item).strip() for item in list(argv or sys.argv[1:]) if str(item).strip()]
24
+ if not args or _is_help(args[0]):
25
+ return True
26
+ saw_help = False
27
+ index = 0
28
+ while index < len(args):
29
+ item = args[index]
30
+ if _is_help(item):
31
+ saw_help = True
32
+ index += 1
33
+ continue
34
+ if item in {"--project-dir", "-d"}:
35
+ index += 2
36
+ continue
37
+ if item.startswith("--project-dir="):
38
+ index += 1
39
+ continue
40
+ if item.startswith("-d="):
41
+ index += 1
42
+ continue
43
+ return False
44
+ return saw_help
45
+
46
+
47
+ def _should_handoff_to_project_runtime(argv: Sequence[str] | None = None) -> bool:
48
+ args = [str(item).strip().lower() for item in list(argv or sys.argv[1:]) if str(item).strip()]
49
+ if not args:
50
+ return False
51
+ if _is_root_help_request(args):
52
+ return False
53
+ if tuple(args[:2]) in {("init", "settings"), ("update", "settings")}:
54
+ return False
55
+ if args[0] == "init":
56
+ return False
57
+ if args[0] in {"env", "settings", "startapp", "app", "dev", "pub", "publish", "pullapp"}:
58
+ return False
59
+ return True
60
+
61
+
62
+ def _resolve_program_name(argv0: str | None = None) -> str:
63
+ return resolve_program_name(argv0)
64
+
65
+
66
+ def _usage(program_name: str, argv: Sequence[str] | None = None) -> str:
67
+ extension_help = _render_project_root_command_help(argv)
68
+ return f"""{program_name} CLI
69
+
70
+ What You Usually Do:
71
+ 1. {program_name} dev init
72
+ Create the project scaffold, import every official pz_apps leaf into business ownership, update settings, and install dependencies.
73
+ 2. {program_name} env doctor
74
+ Check whether local authoring prerequisites such as the dependency backend and `git` are ready.
75
+ 3. {program_name} run
76
+ Start the formal project host through the root `main.py` entrypoint.
77
+ 4. {program_name} app init
78
+ Reconcile the typed source plan and install its exact released app versions.
79
+ 5. {program_name} app add <app_id>
80
+ Install a released package into the current runtime and declare it in the project.
81
+ 6. {program_name} dev add <app-or-source>
82
+ Import one minimal app into `apps/<app_id>` without nested Git metadata.
83
+ 7. {program_name} dev link <repo-or-app>
84
+ Keep a Git checkout under `apps/.sources` and expose it through a binding.
85
+ 8. {program_name} dev branch <repo-or-app>
86
+ Put a managed checkout on the project's business branch from `develop` by default.
87
+ 9. {program_name} pub <app_id>
88
+ Commit, tag, build, and publish one versioned package.
89
+ 10. {program_name} pub rm <app_id>
90
+ Remove one published package from the selected target.
91
+ 11. {program_name} pub batch <app_id> [<app_id> ...]
92
+ Publish several packages in the exact order you give.
93
+
94
+ Usage:
95
+ {program_name} --help
96
+ {program_name} env doctor [--json] [--project-dir PATH]
97
+ {program_name} env install [--json] [--project-dir PATH] [--group NAME] [--extra NAME] [--reinstall-package NAME] [--project-only]
98
+ {program_name} env init [--json] [--no-sync] [--project-dir PATH]
99
+ {program_name} env sync [--json] [--project-dir PATH] [--group NAME] [--extra NAME] [--reinstall-package NAME] [--project-only]
100
+ {program_name} settings init [--force] [--json] [--project-dir PATH]
101
+ {program_name} settings update [<target>] [--json] [--reset-middlewares-order] [--project-dir PATH]
102
+ {program_name} settings refresh-agents [--json] [--project-dir PATH]
103
+ {program_name} settings reset-agents [--json] [--project-dir PATH]
104
+ {program_name} run [develop|dev|test|product] [--project-dir PATH]
105
+ {program_name} startapp <name> [--json] [--target-dir PATH] [--project-dir PATH]
106
+ {program_name} app init [--json] [--no-sync] [--project-dir PATH]
107
+ {program_name} app add <app_id> [--json] [--version VERSION] [--project-dir PATH]
108
+ {program_name} app rm <app_id> [--json] [--project-dir PATH]
109
+ {program_name} app update <app_id> [--json] [--version VERSION] [--project-dir PATH]
110
+ {program_name} app versions <app_id> [--json] [--project-dir PATH]
111
+ {program_name} app declare <app_id> --version VERSION [--json] [--project-dir PATH]
112
+ {program_name} app undeclare <app_id> [--json] [--project-dir PATH]
113
+ {program_name} app install <app_id> --version VERSION [--json] [--project-dir PATH]
114
+ {program_name} dev init [--json] [--app-name NAME] [--no-sync] [--project-dir PATH]
115
+ {program_name} dev init --link (--clone-sources | --source-dir PATH) [--json] [--app-name NAME] [--base-branch develop|main] [--no-sync] [--project-dir PATH]
116
+ {program_name} dev add <app-or-source> [--json] [--branch NAME] [--project-dir PATH]
117
+ {program_name} dev link <repo-or-app> [--json] [--base-branch develop|main] [--project-dir PATH]
118
+ {program_name} dev branch <repo-or-app> [--json] [--base-branch develop|main] [--project-dir PATH]
119
+ {program_name} dev update <repo-or-app> [--json] [--project-dir PATH]
120
+ {program_name} dev unlink <binding> [--json] [--delete-checkout] [--project-dir PATH]
121
+ {program_name} dev source cache|import|link|branch|update|unlink ... [--json] [--project-dir PATH]
122
+ {program_name} dev ide sync [--json] [--project-dir PATH]
123
+ {program_name} pub <app_id> [--json] [--target NAME] [--dry-run] [--project-dir PATH]
124
+ {program_name} pub commit <app_id> [--json] [--project-dir PATH]
125
+ {program_name} pub tag <app_id> [--json] [--project-dir PATH]
126
+ {program_name} pub upload <app_id> [--json] [--version VERSION] [--target NAME] [--dry-run] [--project-dir PATH]
127
+ {program_name} pub rm <app_id> [--json] [--target NAME] [--dry-run] [--force] [--project-dir PATH]
128
+ {program_name} pub batch <app_id> [<app_id> ...] [--json] [--target NAME] [--dry-run] [--project-dir PATH]
129
+ {program_name} list [--json] [--project-dir PATH]
130
+ {program_name} check [--json] [--project-dir PATH]
131
+ {program_name} db <makemigrations|migrate|showmigrations> [--json] [--project-dir PATH]
132
+ {program_name} workers <list|status|stop|restart|run> [--project-dir PATH]
133
+ {program_name} resources images [--force] [--json] [--project-dir PATH]
134
+ {program_name} <app_id> <tool> [--project-dir PATH]
135
+
136
+ {option_shortcuts_help()}
137
+
138
+ Orchestration Commands:
139
+ {program_name} dev init | {program_name} dev add | {program_name} dev link | {program_name} dev branch | {program_name} dev update | {program_name} dev unlink
140
+ {program_name} env init | {program_name} app init | {program_name} app add | {program_name} app update | {program_name} app rm
141
+ {program_name} pub | {program_name} pub batch
142
+
143
+ Atomic Commands:
144
+ {program_name} env doctor | {program_name} env install | {program_name} env sync
145
+ {program_name} settings init | {program_name} settings update | {program_name} settings refresh-agents | {program_name} settings reset-agents
146
+ {program_name} startapp | {program_name} app versions | {program_name} app declare | {program_name} app undeclare | {program_name} app install
147
+ {program_name} dev source cache | {program_name} dev source import | {program_name} dev source link | {program_name} dev source branch | {program_name} dev source update | {program_name} dev source unlink | {program_name} dev ide sync
148
+ {program_name} pub commit | {program_name} pub tag | {program_name} pub upload | {program_name} pub rm
149
+
150
+ Runtime Commands:
151
+ {program_name} run | {program_name} list | {program_name} check | {program_name} db ...
152
+ {program_name} workers ... | {program_name} resources ... | {program_name} <app_id> <tool>
153
+
154
+ The canonical command classification table is `docs/pz命令总览.md`.
155
+
156
+ Examples:
157
+ {program_name} env doctor --project-dir .
158
+ {program_name} env install --project-dir .
159
+ {program_name} env init --project-dir .
160
+ {program_name} env sync --project-dir .
161
+ {program_name} settings init --project-dir .
162
+ {program_name} settings update --project-dir .
163
+ {program_name} settings refresh-agents --project-dir .
164
+ {program_name} settings reset-agents --project-dir .
165
+ {program_name} run --project-dir .
166
+ {program_name} run develop --project-dir .
167
+ {program_name} run dev --project-dir .
168
+ {program_name} run test --project-dir .
169
+ {program_name} run product --project-dir .
170
+ {program_name} resources images --force --project-dir .
171
+ {program_name} app init --project-dir .
172
+ {program_name} app add demo_auth --project-dir .
173
+ {program_name} dev init --app-name demo --project-dir .
174
+ {program_name} dev init --link --clone-sources --app-name demo --project-dir .
175
+ {program_name} dev add demo-auth --project-dir .
176
+ {program_name} dev link demo-auth --base-branch develop --project-dir .
177
+ {program_name} dev branch demo_auth --base-branch main --project-dir .
178
+ {program_name} dev update demo_auth --project-dir .
179
+ {program_name} dev unlink demo_auth --delete-checkout --project-dir .
180
+ {program_name} dev add ../demo_auth --project-dir .
181
+ {program_name} pub catalog --target devpi_dev --project-dir .
182
+ {program_name} pub rm catalog --target devpi_pub --force --project-dir .
183
+ {program_name} pub batch pz catalog --target devpi_dev --project-dir .
184
+ {extension_help}"""
185
+
186
+
187
+ def _has_help_flag(args: Sequence[object]) -> bool:
188
+ return any(_is_help(str(item)) for item in args)
189
+
190
+
191
+ def _discover_root_command_handlers() -> dict[CommandPath, RootCommandHandler]:
192
+ return discover_root_command_handlers()
193
+
194
+
195
+ def _builtin_root_handlers() -> dict[CommandPath, RootCommandHandler]:
196
+ return {handler.command_path: handler for handler in _builtin_root_command_handlers()}
197
+
198
+
199
+ def _core_reserved_command_paths() -> tuple[CommandPath, ...]:
200
+ return (("init",), ("list",), ("check",), ("db",), ("resources",))
201
+
202
+
203
+ def _discover_project_root_command_handlers(
204
+ reserved_paths: Sequence[CommandPath],
205
+ *,
206
+ argv: Sequence[str] | None = None,
207
+ ) -> dict[CommandPath, RootCommandHandler]:
208
+ return discover_project_root_command_handlers(
209
+ reserved_paths=reserved_paths,
210
+ project_dir=resolve_cli_project_dir(argv),
211
+ )
212
+
213
+
214
+ def _render_project_root_command_help(argv: Sequence[str] | None = None) -> str:
215
+ reserved_paths = (*_builtin_root_handlers().keys(), *_core_reserved_command_paths())
216
+ try:
217
+ return render_project_root_command_help(
218
+ reserved_paths=reserved_paths,
219
+ project_dir=resolve_cli_project_dir(argv),
220
+ )
221
+ except Exception:
222
+ return ""
223
+
224
+
225
+ def _matching_command(args: Sequence[str], command_paths: Sequence[CommandPath]) -> CommandPath | None:
226
+ normalized = tuple(str(item).strip().lower() for item in args[:2])
227
+ for command_path in sorted(command_paths, key=len, reverse=True):
228
+ if normalized[: len(command_path)] == command_path:
229
+ return command_path
230
+ return None
231
+
232
+
233
+ def _dispatch_root_command(program_name: str, argv: Sequence[str]) -> int | None:
234
+ builtin_handlers = _builtin_root_handlers()
235
+ builtin_path = _matching_command(argv, tuple(builtin_handlers))
236
+ if builtin_path is not None:
237
+ return builtin_handlers[builtin_path].handler(list(argv[len(builtin_path) :]))
238
+ core_reserved_paths = _core_reserved_command_paths()
239
+ if _matching_command(argv, core_reserved_paths) is not None:
240
+ return None
241
+
242
+ try:
243
+ handlers = _discover_root_command_handlers()
244
+ except Exception as exc:
245
+ sys.stderr.write(f"{program_name} could not load external root CLI providers: {exc}\n")
246
+ return 1
247
+ command_path = _matching_command(argv, tuple(handlers))
248
+ if command_path is None:
249
+ try:
250
+ project_handlers = _discover_project_root_command_handlers(
251
+ (*builtin_handlers.keys(), *handlers.keys(), *core_reserved_paths),
252
+ argv=argv,
253
+ )
254
+ except Exception as exc:
255
+ sys.stderr.write(f"{program_name} could not load project root commands: {exc}\n")
256
+ return 1
257
+ command_path = _matching_command(argv, tuple(project_handlers))
258
+ if command_path is None:
259
+ return None
260
+ return project_handlers[command_path].handler(list(argv[len(command_path) :]))
261
+ return handlers[command_path].handler(list(argv[len(command_path) :]))
262
+
263
+
264
+ def main(argv: Sequence[str] | None = None) -> int:
265
+ args = list(argv or sys.argv[1:])
266
+ program_name = _resolve_program_name(sys.argv[0] if sys.argv else None)
267
+ if _is_root_help_request(args):
268
+ sys.stdout.write(_usage(program_name, args))
269
+ return 0
270
+ if not _has_help_flag(args):
271
+ try:
272
+ validate_current_environment(os.environ)
273
+ except PzError as exc:
274
+ sys.stderr.write(f"{exc}\n")
275
+ return 2
276
+ if not provider_resolution_locked() and _should_handoff_to_project_runtime(argv) and handoff_to_project_runtime(
277
+ argv, current_package_root=Path(__file__).resolve().parent
278
+ ):
279
+ return 0
280
+
281
+ delegated = _dispatch_root_command(program_name, args)
282
+ if delegated is not None:
283
+ return delegated
284
+ return _core_main(list(args))
285
+
286
+
287
+ if __name__ == "__main__":
288
+ raise SystemExit(main())
289
+
290
+
291
+ __all__ = ["main"]
pz_core/cli_options.py ADDED
@@ -0,0 +1,74 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import os
5
+ import sys
6
+
7
+
8
+ OPTION_SHORT_ALIASES: dict[str, str] = {
9
+ "--app-name": "-a",
10
+ "--base-branch": "-b",
11
+ "--concurrency": "-c",
12
+ "--clone-sources": "-C",
13
+ "--dry-run": "-n",
14
+ "--delete-checkout": "-X",
15
+ "--extra": "-x",
16
+ "--force": "-f",
17
+ "--group": "-g",
18
+ "--host": "-H",
19
+ "--json": "-j",
20
+ "--no-sync": "-S",
21
+ "--once": "-o",
22
+ "--poll-interval": "-I",
23
+ "--port": "-p",
24
+ "--prepare-workspace": "-w",
25
+ "--project-dir": "-d",
26
+ "--project-only": "-P",
27
+ "--reinstall-package": "-i",
28
+ "--reload": "-r",
29
+ "--replica-slot": "-l",
30
+ "--reset-middlewares-order": "-M",
31
+ "--shutdown-timeout": "-T",
32
+ "--status": "-s",
33
+ "--target": "-t",
34
+ "--target-dir": "-D",
35
+ "--workers": "-W",
36
+ }
37
+
38
+
39
+ def add_cli_option(
40
+ parser: argparse.ArgumentParser,
41
+ long_option: str,
42
+ *args: object,
43
+ **kwargs: object,
44
+ ) -> argparse.Action:
45
+ short_option = OPTION_SHORT_ALIASES.get(long_option)
46
+ if short_option is None:
47
+ raise ValueError(f"missing short option alias for {long_option}")
48
+ option_names = (short_option, long_option)
49
+ return parser.add_argument(*option_names, *args, **kwargs)
50
+
51
+
52
+ def option_shortcuts_help() -> str:
53
+ lines = ["Common Option Shortcuts:"]
54
+ for long_option, short_option in sorted(OPTION_SHORT_ALIASES.items()):
55
+ lines.append(f" {short_option}, {long_option}")
56
+ return "\n".join(lines)
57
+
58
+
59
+ def resolve_program_name(argv0: str | None = None) -> str:
60
+ env_name = os.getenv("PZ_PROGRAM_NAME", "").strip().lower()
61
+ if env_name in {"pz", "pz"}:
62
+ return env_name
63
+ candidate = os.path.basename(str(argv0 or sys.argv[0] or "")).strip().lower()
64
+ if candidate in {"pz", "pz"}:
65
+ return candidate
66
+ return "pz"
67
+
68
+
69
+ __all__ = [
70
+ "OPTION_SHORT_ALIASES",
71
+ "add_cli_option",
72
+ "option_shortcuts_help",
73
+ "resolve_program_name",
74
+ ]
@@ -0,0 +1,3 @@
1
+ from __future__ import annotations
2
+
3
+ __all__: list[str] = []
@@ -0,0 +1,5 @@
1
+ from __future__ import annotations
2
+
3
+ from .models import PzError, as_pz_error
4
+
5
+ __all__ = ["PzError", "as_pz_error"]