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.
- pz_cli-5.0.0.dist-info/METADATA +51 -0
- pz_cli-5.0.0.dist-info/RECORD +399 -0
- pz_cli-5.0.0.dist-info/WHEEL +4 -0
- pz_cli-5.0.0.dist-info/entry_points.txt +5 -0
- pz_core/__init__.py +64 -0
- pz_core/__main__.py +7 -0
- pz_core/app.py +45 -0
- pz_core/assembly/__init__.py +17 -0
- pz_core/assembly/app_discovery.py +1240 -0
- pz_core/assembly/apps/__init__.py +25 -0
- pz_core/assembly/apps/compiler.py +824 -0
- pz_core/assembly/apps/providers.py +188 -0
- pz_core/assembly/cli/__init__.py +9 -0
- pz_core/assembly/cli/compiler.py +166 -0
- pz_core/assembly/diagnostics/__init__.py +21 -0
- pz_core/assembly/diagnostics/checks.py +257 -0
- pz_core/assembly/diagnostics/dev_sources.py +569 -0
- pz_core/assembly/events/__init__.py +5 -0
- pz_core/assembly/events/compiler.py +219 -0
- pz_core/assembly/extensions/__init__.py +5 -0
- pz_core/assembly/extensions/compiler.py +696 -0
- pz_core/assembly/infra/__init__.py +6 -0
- pz_core/assembly/infra/compiler.py +272 -0
- pz_core/assembly/lifecycle/__init__.py +5 -0
- pz_core/assembly/lifecycle/compiler.py +95 -0
- pz_core/assembly/middlewares/__init__.py +19 -0
- pz_core/assembly/middlewares/compiler.py +508 -0
- pz_core/assembly/project/__init__.py +7 -0
- pz_core/assembly/project/compiler.py +9 -0
- pz_core/assembly/project/context.py +17 -0
- pz_core/assembly/project/discovery.py +227 -0
- pz_core/assembly/resources/__init__.py +19 -0
- pz_core/assembly/resources/compiler.py +310 -0
- pz_core/assembly/resources/settings.py +129 -0
- pz_core/assembly/routes/__init__.py +7 -0
- pz_core/assembly/routes/compiler.py +400 -0
- pz_core/assembly/runtime_manifests/__init__.py +13 -0
- pz_core/assembly/runtime_manifests/compiler.py +159 -0
- pz_core/assembly/settings/__init__.py +17 -0
- pz_core/assembly/settings/compiler.py +786 -0
- pz_core/assembly/settings/host_project_overrides.py +82 -0
- pz_core/assembly/settings/host_runtime_endpoint.py +207 -0
- pz_core/authoring/__init__.py +79 -0
- pz_core/authoring/app_init_service.py +946 -0
- pz_core/authoring/app_versions.py +814 -0
- pz_core/authoring/cli.py +192 -0
- pz_core/authoring/commands.py +1810 -0
- pz_core/authoring/conflicts.py +180 -0
- pz_core/authoring/dev_bindings.py +916 -0
- pz_core/authoring/dev_git.py +1087 -0
- pz_core/authoring/dev_import.py +1061 -0
- pz_core/authoring/dev_manifest.py +522 -0
- pz_core/authoring/dev_sources.py +1638 -0
- pz_core/authoring/env_cli.py +454 -0
- pz_core/authoring/files.py +109 -0
- pz_core/authoring/ide_projection.py +1129 -0
- pz_core/authoring/naming.py +58 -0
- pz_core/authoring/official_dev_sources.py +432 -0
- pz_core/authoring/official_sources.json +156 -0
- pz_core/authoring/orchestration_service.py +558 -0
- pz_core/authoring/project_default.jsonc +53 -0
- pz_core/authoring/project_defaults.py +88 -0
- pz_core/authoring/project_metadata_service.py +199 -0
- pz_core/authoring/project_settings_checks.py +51 -0
- pz_core/authoring/project_settings_cli.py +299 -0
- pz_core/authoring/project_settings_service.py +1700 -0
- pz_core/authoring/project_state.py +399 -0
- pz_core/authoring/publish_git.py +423 -0
- pz_core/authoring/publish_lock.py +188 -0
- pz_core/authoring/publish_source.py +195 -0
- pz_core/authoring/release.py +1382 -0
- pz_core/authoring/repo_keys.py +29 -0
- pz_core/authoring/root_cli.py +28 -0
- pz_core/authoring/scaffold_service.py +325 -0
- pz_core/authoring/sync_service.py +787 -0
- pz_core/authoring/templates/app/__init__.py +1 -0
- pz_core/authoring/templates/app/api.py +25 -0
- pz_core/authoring/templates/app/apps.py +31 -0
- pz_core/authoring/templates/app/auth_package_init.py +14 -0
- pz_core/authoring/templates/app/auth_readme.py +29 -0
- pz_core/authoring/templates/app/configs_package_init.py +14 -0
- pz_core/authoring/templates/app/default_env.py +18 -0
- pz_core/authoring/templates/app/default_jsonc.py +25 -0
- pz_core/authoring/templates/app/locales_readme.py +25 -0
- pz_core/authoring/templates/app/migrations_readme.py +19 -0
- pz_core/authoring/templates/app/models.py +14 -0
- pz_core/authoring/templates/app/package_init.py +8 -0
- pz_core/authoring/templates/app/pages_base.py +161 -0
- pz_core/authoring/templates/app/pages_readme.py +25 -0
- pz_core/authoring/templates/app/public.py +31 -0
- pz_core/authoring/templates/app/pyproject.py +77 -0
- pz_core/authoring/templates/app/readme.py +74 -0
- pz_core/authoring/templates/app/settings.py +46 -0
- pz_core/authoring/templates/app/static_app_js.py +24 -0
- pz_core/authoring/templates/app/static_readme.py +31 -0
- pz_core/authoring/templates/app/template_config_page.py +23 -0
- pz_core/authoring/templates/app/template_index_html.py +28 -0
- pz_core/authoring/templates/app/templates_readme.py +32 -0
- pz_core/authoring/templates/app/urls.py +36 -0
- pz_core/authoring/templates/app/views.py +36 -0
- pz_core/authoring/templates/project/__init__.py +1 -0
- pz_core/authoring/templates/project/agents.py +51 -0
- pz_core/authoring/templates/project/apps_container_readme.py +37 -0
- pz_core/authoring/templates/project/main_py.py +59 -0
- pz_core/authoring/templates/project/project_env.py +19 -0
- pz_core/authoring/templates/project/pyproject.py +26 -0
- pz_core/authoring/templates/project/pz_env_env.py +65 -0
- pz_core/authoring/templates/project/pz_env_jsonc.py +69 -0
- pz_core/authoring/templates/project/pz_jsonc.py +12 -0
- pz_core/authoring/templates/project/readme.py +94 -0
- pz_core/authoring/templates/project/root_gitkeep.py +8 -0
- pz_core/authoring/templates/shared/__init__.py +5 -0
- pz_core/authoring/templates/shared/text.py +10 -0
- pz_core/authoring/venv_service.py +87 -0
- pz_core/authoring/workspace.py +167 -0
- pz_core/cli.py +291 -0
- pz_core/cli_options.py +74 -0
- pz_core/core/__init__.py +3 -0
- pz_core/core/errors/__init__.py +5 -0
- pz_core/core/errors/models.py +117 -0
- pz_core/core/events/__init__.py +5 -0
- pz_core/core/events/registry.py +54 -0
- pz_core/core/extensions/__init__.py +51 -0
- pz_core/core/extensions/registry.py +790 -0
- pz_core/core/health/__init__.py +6 -0
- pz_core/core/health/contracts.py +10 -0
- pz_core/core/middlewares/__init__.py +6 -0
- pz_core/core/middlewares/models.py +24 -0
- pz_core/core/routing/__init__.py +5 -0
- pz_core/core/routing/models.py +21 -0
- pz_core/core/settings_contracts.py +25 -0
- pz_core/docs/README.md +20 -0
- pz_core/docs/distribution-README.md +438 -0
- pz_core/docs/pz/345/221/275/344/273/244/346/200/273/350/247/210.md +1011 -0
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- pz_core/docs/pz/350/247/204/350/214/203/344/270/216/344/275/277/347/224/250/README.md +98 -0
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- pz_core/docs//345/217/221/347/211/210/345/211/215/346/270/205/345/215/225-4.0.11.md +84 -0
- pz_core/docs//346/226/260/346/211/213/346/214/207/345/215/227.md +422 -0
- pz_core/infra/__init__.py +17 -0
- pz_core/infra/db/__init__.py +23 -0
- pz_core/infra/db/contracts.py +73 -0
- pz_core/infra/health/__init__.py +5 -0
- pz_core/infra/health/contracts.py +8 -0
- pz_core/infra/kv/__init__.py +5 -0
- pz_core/infra/kv/contracts.py +17 -0
- pz_core/infra/observability/__init__.py +23 -0
- pz_core/infra/observability/contracts.py +142 -0
- pz_core/infra/resilience/__init__.py +5 -0
- pz_core/infra/resilience/contracts.py +17 -0
- pz_core/infra/resources/__init__.py +5 -0
- pz_core/infra/resources/contracts.py +16 -0
- pz_core/infra/settings/__init__.py +17 -0
- pz_core/infra/settings/models.py +81 -0
- pz_core/infra/storage/__init__.py +5 -0
- pz_core/infra/storage/ports.py +27 -0
- pz_core/project_root_commands.py +282 -0
- pz_core/project_runtime_cli.py +344 -0
- pz_core/project_sources.py +253 -0
- pz_core/pz_launcher.py +209 -0
- pz_core/root_cli.py +70 -0
- pz_core/runtime/__init__.py +229 -0
- pz_core/runtime/access.py +86 -0
- pz_core/runtime/adapters/__init__.py +5 -0
- pz_core/runtime/adapters/base.py +18 -0
- pz_core/runtime/asyncio_bridge.py +18 -0
- pz_core/runtime/bindings/__init__.py +5 -0
- pz_core/runtime/bindings/container.py +50 -0
- pz_core/runtime/cli/__init__.py +5 -0
- pz_core/runtime/cli/_args.py +67 -0
- pz_core/runtime/cli/app_commands.py +417 -0
- pz_core/runtime/cli/check.py +214 -0
- pz_core/runtime/cli/db.py +297 -0
- pz_core/runtime/cli/main.py +89 -0
- pz_core/runtime/cli/resources.py +280 -0
- pz_core/runtime/discovery.py +23 -0
- pz_core/runtime/environment_integrity.py +157 -0
- pz_core/runtime/errors.py +5 -0
- pz_core/runtime/events.py +87 -0
- pz_core/runtime/facades/__init__.py +38 -0
- pz_core/runtime/facades/_capabilities.py +46 -0
- pz_core/runtime/facades/cache.py +103 -0
- pz_core/runtime/facades/database.py +71 -0
- pz_core/runtime/facades/events.py +380 -0
- pz_core/runtime/facades/health.py +101 -0
- pz_core/runtime/facades/mail.py +121 -0
- pz_core/runtime/facades/observability.py +102 -0
- pz_core/runtime/facades/providers.py +75 -0
- pz_core/runtime/facades/resources.py +52 -0
- pz_core/runtime/facades/storage.py +296 -0
- pz_core/runtime/health/__init__.py +5 -0
- pz_core/runtime/health/service.py +102 -0
- pz_core/runtime/host.py +188 -0
- pz_core/runtime/host_runner.py +282 -0
- pz_core/runtime/http/__init__.py +20 -0
- pz_core/runtime/http/app.py +576 -0
- pz_core/runtime/http_timing.py +173 -0
- pz_core/runtime/invocation.py +29 -0
- pz_core/runtime/json_safe.py +47 -0
- pz_core/runtime/lifecycle/__init__.py +25 -0
- pz_core/runtime/lifecycle/manager.py +533 -0
- pz_core/runtime/plan.py +214 -0
- pz_core/runtime/plan_context.py +33 -0
- pz_core/runtime/plan_snapshot.py +177 -0
- pz_core/runtime/registries/__init__.py +27 -0
- pz_core/runtime/registries/capabilities.py +101 -0
- pz_core/runtime/registries/providers.py +396 -0
- pz_core/runtime/resource_assets.py +344 -0
- pz_core/runtime/run_cli.py +211 -0
- pz_core/runtime/settings.py +888 -0
- pz_core/runtime/worker/__init__.py +21 -0
- pz_core/runtime/worker/engine.py +921 -0
- pz_core/runtime/worker/runtime.py +25 -0
- pz_core/testing/__init__.py +15 -0
- pz_core/testing/doc_route_contracts.py +305 -0
- pz_core/utils/__init__.py +44 -0
- pz_core/utils/env.py +65 -0
- pz_core/utils/project_jsonc/__init__.py +29 -0
- pz_core/utils/project_jsonc/document.py +420 -0
- pz_core/utils/project_settings.py +99 -0
- pz_foundation/__init__.py +50 -0
- pz_foundation/_contracts.py +81 -0
- pz_foundation/_errors.py +34 -0
- pz_foundation/api.py +14 -0
- pz_foundation/apps.py +127 -0
- pz_foundation/auth/__init__.py +1 -0
- pz_foundation/cache_control.py +233 -0
- pz_foundation/cli/__init__.py +2 -0
- pz_foundation/cli/workers.py +565 -0
- pz_foundation/configs/__init__.py +0 -0
- pz_foundation/configs/default.env +15 -0
- pz_foundation/configs/default.jsonc +452 -0
- pz_foundation/db/__init__.py +94 -0
- pz_foundation/db/aerich_executor.py +664 -0
- pz_foundation/db/config.py +358 -0
- pz_foundation/db/connection_manager.py +689 -0
- pz_foundation/db/connection_probe.py +204 -0
- pz_foundation/db/database.py +1291 -0
- pz_foundation/db/deps.py +47 -0
- pz_foundation/db/lifecycle_status.py +85 -0
- pz_foundation/db/migrations.py +477 -0
- pz_foundation/db/mysql.py +57 -0
- pz_foundation/db/postgresql.py +409 -0
- pz_foundation/db/production_pool_fallback.py +143 -0
- pz_foundation/db/public.py +45 -0
- pz_foundation/db/session.py +369 -0
- pz_foundation/db/sqlite.py +15 -0
- pz_foundation/db/tortoise_manager.py +724 -0
- pz_foundation/db/tortoise_psycopg.py +148 -0
- pz_foundation/docs/README.md +18 -0
- pz_foundation/docs/distribution-README.md +319 -0
- 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
- 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
- pz_foundation/docs//350/256/276/350/256/241/346/226/207/346/241/243.md +288 -0
- 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
- pz_foundation/health.py +105 -0
- pz_foundation/host/__init__.py +11 -0
- pz_foundation/host/builder.py +34 -0
- pz_foundation/host/cache_runtime.py +44 -0
- pz_foundation/host/db/__init__.py +17 -0
- pz_foundation/host/db/aerich_config.py +36 -0
- pz_foundation/host/db/config.py +106 -0
- pz_foundation/host/db/connection_manager.py +48 -0
- pz_foundation/host/db/deps.py +5 -0
- pz_foundation/host/db/orm_retry_patch.py +566 -0
- pz_foundation/host/db/request_adapter.py +325 -0
- pz_foundation/host/db/router.py +28 -0
- pz_foundation/host/db/session.py +284 -0
- pz_foundation/host/db/tortoise_manager.py +10 -0
- pz_foundation/host/idempotency.py +132 -0
- pz_foundation/host/lifespan.py +247 -0
- pz_foundation/host/redis_runtime.py +100 -0
- pz_foundation/host/web.py +790 -0
- pz_foundation/infra_provider.py +236 -0
- pz_foundation/kv/__init__.py +25 -0
- pz_foundation/kv/cache.py +1166 -0
- pz_foundation/kv/deps.py +84 -0
- pz_foundation/kv/public.py +25 -0
- pz_foundation/kv/redis_manager.py +1531 -0
- pz_foundation/lazy_exports.py +43 -0
- pz_foundation/lazy_imports.py +124 -0
- pz_foundation/lifecycle.py +392 -0
- pz_foundation/managed_workers.py +1117 -0
- pz_foundation/middlewares/__init__.py +26 -0
- pz_foundation/middlewares/_settings.py +250 -0
- pz_foundation/middlewares/analytics.py +124 -0
- pz_foundation/middlewares/cache_control.py +156 -0
- pz_foundation/middlewares/compression.py +202 -0
- pz_foundation/middlewares/cors.py +62 -0
- pz_foundation/middlewares/geo_country.py +44 -0
- pz_foundation/middlewares/inner_router.py +50 -0
- pz_foundation/middlewares/rate_limited/__init__.py +3 -0
- pz_foundation/middlewares/rate_limited/key_limiter.py +115 -0
- pz_foundation/middlewares/request_logging.py +104 -0
- pz_foundation/middlewares/route_owner.py +309 -0
- pz_foundation/middlewares/security_csrf.py +44 -0
- pz_foundation/middlewares/security_headers/__init__.py +4 -0
- pz_foundation/middlewares/security_headers/conflicts.py +44 -0
- pz_foundation/middlewares/security_headers/csp_nonce.py +200 -0
- pz_foundation/middlewares/security_headers/security_headers.py +44 -0
- pz_foundation/migrations/__init__.py +1 -0
- pz_foundation/migrations/pz_foundation/__init__.py +1 -0
- pz_foundation/models.py +22 -0
- pz_foundation/notifications/__init__.py +23 -0
- pz_foundation/notifications/email.py +542 -0
- pz_foundation/notifications/public.py +31 -0
- pz_foundation/observability/__init__.py +71 -0
- pz_foundation/observability/http.py +34 -0
- pz_foundation/observability/logger/__init__.py +49 -0
- pz_foundation/observability/logger/_bot_settings.py +126 -0
- pz_foundation/observability/logger/bot_message.py +592 -0
- pz_foundation/observability/logger/core.py +385 -0
- pz_foundation/observability/logger/delivery_audit.py +84 -0
- pz_foundation/observability/logger/feishu_bot.py +199 -0
- pz_foundation/observability/logger/telegram_bot.py +194 -0
- pz_foundation/observability/metrics.py +365 -0
- pz_foundation/observability/runtime.py +68 -0
- pz_foundation/public.py +405 -0
- pz_foundation/resources/__init__.py +12 -0
- pz_foundation/resources/builder.py +900 -0
- pz_foundation/resources/images.py +363 -0
- pz_foundation/root_cli.py +20 -0
- pz_foundation/routing/__init__.py +203 -0
- pz_foundation/routing/canonical.py +486 -0
- pz_foundation/routing/convertors.py +82 -0
- pz_foundation/routing/declarations.py +843 -0
- pz_foundation/routing/exports.py +148 -0
- pz_foundation/routing/loaders.py +138 -0
- pz_foundation/routing/manifest.py +215 -0
- pz_foundation/routing/manifest_provider.py +47 -0
- pz_foundation/routing/mounts.py +101 -0
- pz_foundation/routing/ordering.py +172 -0
- pz_foundation/routing/registry.py +133 -0
- pz_foundation/routing/utils.py +28 -0
- pz_foundation/runtime.py +234 -0
- pz_foundation/settings.py +253 -0
- pz_foundation/settings_normalization.py +130 -0
- pz_foundation/storage/__init__.py +25 -0
- pz_foundation/storage/local.py +209 -0
- pz_foundation/storage/public.py +106 -0
- pz_foundation/storage/s3.py +116 -0
- pz_foundation/storage/service.py +234 -0
- pz_foundation/urls.py +19 -0
- pz_foundation/utils/__init__.py +6 -0
- pz_foundation/utils/merge.py +160 -0
- pz_foundation/worker_replicas.py +55 -0
- pz_settings_center/__init__.py +5 -0
- pz_settings_center/api/__init__.py +5 -0
- pz_settings_center/api/runtime_overrides.py +360 -0
- pz_settings_center/apps.py +28 -0
- pz_settings_center/configs/__init__.py +0 -0
- pz_settings_center/configs/default.env +2 -0
- pz_settings_center/configs/default.jsonc +1 -0
- pz_settings_center/docs/01-settings_center/350/203/275/345/212/233/350/276/271/347/225/214.md +124 -0
- pz_settings_center/docs/README.md +12 -0
- pz_settings_center/docs/distribution-README.md +150 -0
- pz_settings_center/docs//350/256/276/350/256/241/346/226/207/346/241/243.md +48 -0
- pz_settings_center/integration_payload.py +18 -0
- pz_settings_center/project_helpers.py +405 -0
- pz_settings_center/public.py +139 -0
- pz_settings_center/routing_helpers.py +73 -0
- pz_settings_center/runtime_override_provider.py +61 -0
- pz_settings_center/typed_settings.py +324 -0
- pz_settings_center/urls.py +9 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
|
|
5
|
+
from pz_core.runtime.errors import PzError
|
|
6
|
+
from pz_core.runtime.registries.providers import (
|
|
7
|
+
ProviderBinding,
|
|
8
|
+
ProviderActivationContext,
|
|
9
|
+
ProviderDecl,
|
|
10
|
+
ProviderDiagnostic,
|
|
11
|
+
ProviderRegistry,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass(slots=True)
|
|
16
|
+
class ProviderFacade:
|
|
17
|
+
registry: ProviderRegistry
|
|
18
|
+
|
|
19
|
+
def __post_init__(self) -> None:
|
|
20
|
+
if not isinstance(self.registry, ProviderRegistry):
|
|
21
|
+
raise PzError(
|
|
22
|
+
code="PZ_PROVIDER_REGISTRY_INVALID",
|
|
23
|
+
message="ProviderFacade requires a ProviderRegistry instance.",
|
|
24
|
+
stage="providers",
|
|
25
|
+
owner="runtime.providers",
|
|
26
|
+
action="bind_provider_facade",
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
def declared(self) -> tuple[ProviderDecl, ...]:
|
|
30
|
+
return self.registry.declared()
|
|
31
|
+
|
|
32
|
+
def declared_for(self, capability: str) -> tuple[ProviderDecl, ...]:
|
|
33
|
+
return self.registry.declared_for(capability)
|
|
34
|
+
|
|
35
|
+
def bindings(self) -> tuple[ProviderBinding, ...]:
|
|
36
|
+
return self.registry.bindings()
|
|
37
|
+
|
|
38
|
+
def bindings_for(self, capability: str) -> tuple[ProviderBinding, ...]:
|
|
39
|
+
return self.registry.bindings_for(capability)
|
|
40
|
+
|
|
41
|
+
def register(self, binding_id: str, provider: object) -> str:
|
|
42
|
+
return self.registry.register(binding_id, provider)
|
|
43
|
+
|
|
44
|
+
def unregister(self, token: str) -> bool:
|
|
45
|
+
return self.registry.unregister(token)
|
|
46
|
+
|
|
47
|
+
def reset(self, *, owner: str | None = None) -> int:
|
|
48
|
+
return self.registry.reset(owner=owner)
|
|
49
|
+
|
|
50
|
+
def activate_declared(
|
|
51
|
+
self,
|
|
52
|
+
*,
|
|
53
|
+
plan: object,
|
|
54
|
+
bindings: object,
|
|
55
|
+
host: object | None = None,
|
|
56
|
+
owner: str | None = None,
|
|
57
|
+
) -> int:
|
|
58
|
+
return self.registry.activate_declared(
|
|
59
|
+
plan=plan,
|
|
60
|
+
bindings=bindings,
|
|
61
|
+
host=host,
|
|
62
|
+
owner=owner,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
def require(self, capability: str) -> object:
|
|
66
|
+
return self.registry.require(capability)
|
|
67
|
+
|
|
68
|
+
def status(self, capability: str) -> str:
|
|
69
|
+
return self.registry.status(capability)
|
|
70
|
+
|
|
71
|
+
def failed_for(self, capability: str) -> tuple[ProviderDiagnostic, ...]:
|
|
72
|
+
return self.registry.failed_for(capability)
|
|
73
|
+
|
|
74
|
+
def diagnostics(self) -> tuple[ProviderDiagnostic, ...]:
|
|
75
|
+
return self.registry.diagnostics()
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pz_core.assembly.resources import ResourceManifest, ResourceSource
|
|
4
|
+
from pz_core.infra.resources import ResourceBuildPort, ResourceBuildResult
|
|
5
|
+
from pz_core.runtime.errors import PzError
|
|
6
|
+
from pz_core.runtime.facades.providers import ProviderFacade
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ResourceFacade:
|
|
10
|
+
def __init__(self, manifest: ResourceManifest, providers: ProviderFacade) -> None:
|
|
11
|
+
if not isinstance(manifest, ResourceManifest):
|
|
12
|
+
raise PzError(
|
|
13
|
+
code="PZ_RESOURCE_MANIFEST_INVALID",
|
|
14
|
+
message="ResourceFacade requires a ResourceManifest instance.",
|
|
15
|
+
stage="resources",
|
|
16
|
+
owner="runtime.resources",
|
|
17
|
+
action="bind_resource_facade",
|
|
18
|
+
)
|
|
19
|
+
if not hasattr(providers, "require"):
|
|
20
|
+
raise PzError(
|
|
21
|
+
code="PZ_RESOURCE_PROVIDERS_INVALID",
|
|
22
|
+
message="ResourceFacade providers must expose require().",
|
|
23
|
+
stage="resources",
|
|
24
|
+
owner="runtime.resources",
|
|
25
|
+
action="bind_resource_facade",
|
|
26
|
+
)
|
|
27
|
+
self._manifest = manifest
|
|
28
|
+
self._providers = providers
|
|
29
|
+
|
|
30
|
+
def status(self) -> str:
|
|
31
|
+
return self._providers.status("resources")
|
|
32
|
+
|
|
33
|
+
def manifest(self) -> ResourceManifest:
|
|
34
|
+
return self._manifest
|
|
35
|
+
|
|
36
|
+
def app_order(self) -> tuple[str, ...]:
|
|
37
|
+
return self._manifest.app_order
|
|
38
|
+
|
|
39
|
+
def sources(self) -> tuple[ResourceSource, ...]:
|
|
40
|
+
return self._manifest.sources
|
|
41
|
+
|
|
42
|
+
def build(self, *, force: bool = False) -> ResourceBuildResult:
|
|
43
|
+
provider = self._providers.require("resources")
|
|
44
|
+
if not isinstance(provider, ResourceBuildPort):
|
|
45
|
+
raise PzError(
|
|
46
|
+
code="PZ_RESOURCE_PROVIDER_INVALID",
|
|
47
|
+
message="Registered resources provider does not implement ResourceBuildPort.",
|
|
48
|
+
stage="resources",
|
|
49
|
+
owner="runtime.resources",
|
|
50
|
+
action="build",
|
|
51
|
+
)
|
|
52
|
+
return provider.build(force=force)
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any, Protocol, runtime_checkable
|
|
5
|
+
|
|
6
|
+
from pz_core.runtime.errors import PzError
|
|
7
|
+
from pz_core.infra.storage import PresignInfo, StoragePort, StoredObject
|
|
8
|
+
from pz_core.runtime.facades._capabilities import merged_capability_status
|
|
9
|
+
from pz_core.runtime.access import get_runtime
|
|
10
|
+
from pz_core.runtime.facades.providers import ProviderFacade
|
|
11
|
+
from pz_core.runtime.plan import RuntimePlan
|
|
12
|
+
from pz_core.runtime.registries import CapabilityStatus
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _require_storage_key(key: str, *, action: str) -> str:
|
|
16
|
+
if not isinstance(key, str) or not key.strip():
|
|
17
|
+
raise PzError(
|
|
18
|
+
code="PZ_STORAGE_KEY_INVALID",
|
|
19
|
+
message="Storage key must be a non-empty string.",
|
|
20
|
+
stage="storage",
|
|
21
|
+
owner="runtime.storage",
|
|
22
|
+
action=action,
|
|
23
|
+
)
|
|
24
|
+
return key
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _require_storage_mode(mode: str, *, action: str) -> str:
|
|
28
|
+
if not isinstance(mode, str) or not mode.strip():
|
|
29
|
+
raise PzError(
|
|
30
|
+
code="PZ_STORAGE_MODE_INVALID",
|
|
31
|
+
message="Storage mode must be a non-empty string.",
|
|
32
|
+
stage="storage",
|
|
33
|
+
owner="runtime.storage",
|
|
34
|
+
action=action,
|
|
35
|
+
)
|
|
36
|
+
return mode
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _require_storage_method(method: str, *, action: str) -> str:
|
|
40
|
+
if not isinstance(method, str) or not method.strip():
|
|
41
|
+
raise PzError(
|
|
42
|
+
code="PZ_STORAGE_METHOD_INVALID",
|
|
43
|
+
message="Storage method must be a non-empty string.",
|
|
44
|
+
stage="storage",
|
|
45
|
+
owner="runtime.storage",
|
|
46
|
+
action=action,
|
|
47
|
+
)
|
|
48
|
+
return method
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _require_storage_expires_in(expires_in: int | None, *, action: str) -> int | None:
|
|
52
|
+
if expires_in is None:
|
|
53
|
+
return None
|
|
54
|
+
if isinstance(expires_in, bool) or not isinstance(expires_in, int) or expires_in <= 0:
|
|
55
|
+
raise PzError(
|
|
56
|
+
code="PZ_STORAGE_EXPIRES_IN_INVALID",
|
|
57
|
+
message="Storage expires_in must be a positive integer when configured.",
|
|
58
|
+
stage="storage",
|
|
59
|
+
owner="runtime.storage",
|
|
60
|
+
action=action,
|
|
61
|
+
)
|
|
62
|
+
return expires_in
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class StorageFacade:
|
|
66
|
+
def __init__(self, plan: RuntimePlan, providers: ProviderFacade) -> None:
|
|
67
|
+
if not isinstance(plan, RuntimePlan):
|
|
68
|
+
raise PzError(
|
|
69
|
+
code="PZ_STORAGE_PLAN_INVALID",
|
|
70
|
+
message="StorageFacade requires a RuntimePlan instance.",
|
|
71
|
+
stage="storage",
|
|
72
|
+
owner="runtime.storage",
|
|
73
|
+
action="bind_storage_facade",
|
|
74
|
+
)
|
|
75
|
+
if not hasattr(providers, "require"):
|
|
76
|
+
raise PzError(
|
|
77
|
+
code="PZ_STORAGE_PROVIDERS_INVALID",
|
|
78
|
+
message="StorageFacade providers must expose require().",
|
|
79
|
+
stage="storage",
|
|
80
|
+
owner="runtime.storage",
|
|
81
|
+
action="bind_storage_facade",
|
|
82
|
+
)
|
|
83
|
+
self._plan = plan
|
|
84
|
+
self._providers = providers
|
|
85
|
+
|
|
86
|
+
def status(self) -> CapabilityStatus:
|
|
87
|
+
return merged_capability_status(self._plan, self._providers, "storage")
|
|
88
|
+
|
|
89
|
+
def _storage(self) -> StoragePort:
|
|
90
|
+
provider = self._providers.require("storage")
|
|
91
|
+
if not isinstance(provider, StoragePort):
|
|
92
|
+
raise PzError(
|
|
93
|
+
code="PZ_STORAGE_PROVIDER_INVALID",
|
|
94
|
+
message="Registered storage provider does not implement StoragePort.",
|
|
95
|
+
stage="storage",
|
|
96
|
+
owner="infra.storage",
|
|
97
|
+
action="resolve_storage",
|
|
98
|
+
)
|
|
99
|
+
return provider
|
|
100
|
+
|
|
101
|
+
def open(self, key: str, *, mode: str = "rb"):
|
|
102
|
+
key = _require_storage_key(key, action="open")
|
|
103
|
+
mode = _require_storage_mode(mode, action="open")
|
|
104
|
+
provider = self._providers.require("storage")
|
|
105
|
+
opener = getattr(provider, "open", None)
|
|
106
|
+
if callable(opener):
|
|
107
|
+
return opener(key, mode=mode)
|
|
108
|
+
raise PzError(
|
|
109
|
+
code="PZ_STORAGE_OPEN_UNSUPPORTED",
|
|
110
|
+
message="Registered storage provider does not expose open().",
|
|
111
|
+
stage="storage",
|
|
112
|
+
owner="infra.storage",
|
|
113
|
+
action="open",
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
def save(
|
|
117
|
+
self,
|
|
118
|
+
key: str,
|
|
119
|
+
payload: object,
|
|
120
|
+
*,
|
|
121
|
+
content_type: str | None = None,
|
|
122
|
+
metadata: dict[str, str] | None = None,
|
|
123
|
+
) -> StoredObject:
|
|
124
|
+
key = _require_storage_key(key, action="save")
|
|
125
|
+
del metadata
|
|
126
|
+
if isinstance(payload, bytes):
|
|
127
|
+
body = payload
|
|
128
|
+
elif isinstance(payload, str):
|
|
129
|
+
body = payload.encode("utf-8")
|
|
130
|
+
elif hasattr(payload, "read"):
|
|
131
|
+
body = payload.read()
|
|
132
|
+
if isinstance(body, str):
|
|
133
|
+
body = body.encode("utf-8")
|
|
134
|
+
else:
|
|
135
|
+
raise PzError(
|
|
136
|
+
code="PZ_STORAGE_PAYLOAD_INVALID",
|
|
137
|
+
message="StorageFacade.save() payload must be bytes, str, or file-like.",
|
|
138
|
+
stage="storage",
|
|
139
|
+
owner="infra.storage",
|
|
140
|
+
action="save",
|
|
141
|
+
)
|
|
142
|
+
if not isinstance(body, bytes):
|
|
143
|
+
raise PzError(
|
|
144
|
+
code="PZ_STORAGE_PAYLOAD_INVALID",
|
|
145
|
+
message="StorageFacade.save() payload reader must return bytes or str.",
|
|
146
|
+
stage="storage",
|
|
147
|
+
owner="infra.storage",
|
|
148
|
+
action="save",
|
|
149
|
+
)
|
|
150
|
+
return self._storage().store_bytes(key, body, content_type=content_type)
|
|
151
|
+
|
|
152
|
+
def delete(self, key: str) -> None:
|
|
153
|
+
key = _require_storage_key(key, action="delete")
|
|
154
|
+
self._storage().delete(key)
|
|
155
|
+
|
|
156
|
+
def url(
|
|
157
|
+
self,
|
|
158
|
+
key: str,
|
|
159
|
+
*,
|
|
160
|
+
expires_in: int | None = None,
|
|
161
|
+
download_name: str | None = None,
|
|
162
|
+
) -> str | None:
|
|
163
|
+
key = _require_storage_key(key, action="url")
|
|
164
|
+
expires_in = _require_storage_expires_in(expires_in, action="url")
|
|
165
|
+
del download_name
|
|
166
|
+
provider = self._providers.require("storage")
|
|
167
|
+
url_factory = getattr(provider, "url", None)
|
|
168
|
+
if callable(url_factory):
|
|
169
|
+
return url_factory(key, expires_in=expires_in)
|
|
170
|
+
return None
|
|
171
|
+
|
|
172
|
+
def presign(
|
|
173
|
+
self,
|
|
174
|
+
key: str,
|
|
175
|
+
*,
|
|
176
|
+
method: str = "GET",
|
|
177
|
+
expires_in: int | None = None,
|
|
178
|
+
) -> PresignInfo:
|
|
179
|
+
key = _require_storage_key(key, action="presign")
|
|
180
|
+
method = _require_storage_method(method, action="presign")
|
|
181
|
+
expires_in = _require_storage_expires_in(expires_in, action="presign")
|
|
182
|
+
provider = self._providers.require("storage")
|
|
183
|
+
presign_factory = getattr(provider, "presign", None)
|
|
184
|
+
if callable(presign_factory):
|
|
185
|
+
return presign_factory(key, method=method, expires_in=expires_in)
|
|
186
|
+
if method.upper() == "GET":
|
|
187
|
+
return self._storage().presign_get(
|
|
188
|
+
key,
|
|
189
|
+
expires_in_seconds=expires_in if expires_in is not None else 300,
|
|
190
|
+
)
|
|
191
|
+
raise PzError(
|
|
192
|
+
code="PZ_STORAGE_PRESIGN_UNSUPPORTED",
|
|
193
|
+
message="Registered storage provider does not expose presign() for this method.",
|
|
194
|
+
stage="storage",
|
|
195
|
+
owner="infra.storage",
|
|
196
|
+
action="presign",
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
@dataclass(slots=True)
|
|
201
|
+
class RuntimePresignInfo:
|
|
202
|
+
method: str
|
|
203
|
+
url: str
|
|
204
|
+
expires: int | None = None
|
|
205
|
+
headers: dict[str, str] | None = None
|
|
206
|
+
fields: dict[str, str] | None = None
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
@dataclass(slots=True)
|
|
210
|
+
class RuntimeStoredObject:
|
|
211
|
+
path: str
|
|
212
|
+
size: int | None = None
|
|
213
|
+
content_type: str | None = None
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
@runtime_checkable
|
|
217
|
+
class RuntimeStoragePort(Protocol):
|
|
218
|
+
def open(self, key: str, *, mode: str = "rb"): ...
|
|
219
|
+
|
|
220
|
+
def save(self, key: str, payload: Any, *, content_type: str | None = None) -> RuntimeStoredObject: ...
|
|
221
|
+
|
|
222
|
+
def delete(self, key: str) -> None: ...
|
|
223
|
+
|
|
224
|
+
def url(self, key: str, *, expires_in: int | None = None) -> str | None: ...
|
|
225
|
+
|
|
226
|
+
def presign_upload(
|
|
227
|
+
self,
|
|
228
|
+
key: str,
|
|
229
|
+
*,
|
|
230
|
+
content_type: str | None = None,
|
|
231
|
+
expires_in: int = 300,
|
|
232
|
+
) -> RuntimePresignInfo: ...
|
|
233
|
+
|
|
234
|
+
def presign_download(self, key: str, *, expires_in: int = 300) -> RuntimePresignInfo: ...
|
|
235
|
+
|
|
236
|
+
class StorageClient:
|
|
237
|
+
def __init__(self, namespace: str | None = None, *, request: Any | None = None) -> None:
|
|
238
|
+
self.namespace = namespace
|
|
239
|
+
self._storage = get_runtime(request=request).bindings.storage
|
|
240
|
+
|
|
241
|
+
def open(self, key: str, *, mode: str = "rb"):
|
|
242
|
+
return self._storage.open(key, mode=mode)
|
|
243
|
+
|
|
244
|
+
def save(self, key: str, payload: Any, *, content_type: str | None = None) -> RuntimeStoredObject:
|
|
245
|
+
stored = self._storage.save(key, payload, content_type=content_type)
|
|
246
|
+
object_key = getattr(stored, "object_key", key)
|
|
247
|
+
return RuntimeStoredObject(
|
|
248
|
+
path=str(object_key),
|
|
249
|
+
size=getattr(stored, "size", None),
|
|
250
|
+
content_type=getattr(stored, "content_type", content_type),
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
def delete(self, key: str) -> None:
|
|
254
|
+
self._storage.delete(key)
|
|
255
|
+
|
|
256
|
+
def url(self, key: str, *, expires_in: int | None = None) -> str | None:
|
|
257
|
+
return self._storage.url(key, expires_in=expires_in)
|
|
258
|
+
|
|
259
|
+
def presign_upload(
|
|
260
|
+
self,
|
|
261
|
+
key: str,
|
|
262
|
+
*,
|
|
263
|
+
content_type: str | None = None,
|
|
264
|
+
expires_in: int = 300,
|
|
265
|
+
) -> RuntimePresignInfo:
|
|
266
|
+
del content_type
|
|
267
|
+
presign = self._storage.presign(key, method="PUT", expires_in=expires_in)
|
|
268
|
+
return RuntimePresignInfo(
|
|
269
|
+
method=presign.method,
|
|
270
|
+
url=presign.url,
|
|
271
|
+
expires=presign.expires_in_seconds,
|
|
272
|
+
headers={},
|
|
273
|
+
fields={},
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
def presign_download(self, key: str, *, expires_in: int = 300) -> RuntimePresignInfo:
|
|
277
|
+
presign = self._storage.presign(key, method="GET", expires_in=expires_in)
|
|
278
|
+
return RuntimePresignInfo(
|
|
279
|
+
method=presign.method,
|
|
280
|
+
url=presign.url,
|
|
281
|
+
expires=presign.expires_in_seconds,
|
|
282
|
+
headers={},
|
|
283
|
+
fields={},
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def get_storage(namespace: str | None = None):
|
|
288
|
+
if namespace is None:
|
|
289
|
+
def _dependency(request: Any) -> StorageClient:
|
|
290
|
+
return StorageClient(request=request)
|
|
291
|
+
return _dependency
|
|
292
|
+
|
|
293
|
+
def _dependency(request: Any) -> StorageClient:
|
|
294
|
+
return StorageClient(namespace=namespace, request=request)
|
|
295
|
+
|
|
296
|
+
return _dependency
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Mapping
|
|
5
|
+
|
|
6
|
+
from pz_core.runtime.lifecycle import LifecycleState
|
|
7
|
+
from pz_core.runtime.plan import RuntimePlan
|
|
8
|
+
from pz_core.runtime.registries import CapabilityState, CapabilityStatus
|
|
9
|
+
from pz_core.runtime.errors import PzError
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _capability_map(
|
|
13
|
+
plan: RuntimePlan,
|
|
14
|
+
state: LifecycleState | None,
|
|
15
|
+
) -> tuple[CapabilityState, ...]:
|
|
16
|
+
if state and state.capability_states:
|
|
17
|
+
return state.capability_states
|
|
18
|
+
return plan.capability_registry.capabilities
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _aggregate_status(statuses: tuple[CapabilityStatus, ...], *, active: bool) -> str:
|
|
22
|
+
if any(status == "unavailable" for status in statuses):
|
|
23
|
+
return "unavailable"
|
|
24
|
+
if active and any(status == "ready" for status in statuses):
|
|
25
|
+
return "ok"
|
|
26
|
+
if any(status == "enabled" for status in statuses):
|
|
27
|
+
return "starting"
|
|
28
|
+
if any(status == "ready" for status in statuses):
|
|
29
|
+
return "ok"
|
|
30
|
+
return "disabled"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _normalize_extra_capability_statuses(
|
|
34
|
+
extra_capability_statuses: Mapping[str, CapabilityStatus] | None,
|
|
35
|
+
) -> dict[str, CapabilityStatus]:
|
|
36
|
+
if not extra_capability_statuses:
|
|
37
|
+
return {}
|
|
38
|
+
normalized: dict[str, CapabilityStatus] = {}
|
|
39
|
+
for name, status in extra_capability_statuses.items():
|
|
40
|
+
if not isinstance(name, str) or not name.strip():
|
|
41
|
+
raise PzError(
|
|
42
|
+
code="PZ_CAPABILITY_NAME_INVALID",
|
|
43
|
+
message="extra capability status names must be non-empty strings.",
|
|
44
|
+
stage="health",
|
|
45
|
+
owner="runtime.health",
|
|
46
|
+
action="build_health_snapshot",
|
|
47
|
+
)
|
|
48
|
+
if status not in {"disabled", "enabled", "ready", "unavailable"}:
|
|
49
|
+
raise PzError(
|
|
50
|
+
code="PZ_CAPABILITY_STATUS_INVALID",
|
|
51
|
+
message=(
|
|
52
|
+
f"extra capability status for '{name.strip()}' must be one of: "
|
|
53
|
+
"disabled, enabled, ready, unavailable."
|
|
54
|
+
),
|
|
55
|
+
stage="health",
|
|
56
|
+
owner=name.strip(),
|
|
57
|
+
action="build_health_snapshot",
|
|
58
|
+
)
|
|
59
|
+
normalized[name.strip()] = status
|
|
60
|
+
return normalized
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@dataclass(frozen=True, slots=True)
|
|
64
|
+
class HealthSnapshot:
|
|
65
|
+
status: str
|
|
66
|
+
phase: str
|
|
67
|
+
active: bool
|
|
68
|
+
enabled_components: tuple[str, ...]
|
|
69
|
+
activated_capabilities: tuple[str, ...]
|
|
70
|
+
capability_statuses: dict[str, CapabilityStatus]
|
|
71
|
+
unavailable_capabilities: tuple[str, ...]
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def build_health_snapshot(
|
|
75
|
+
plan: RuntimePlan,
|
|
76
|
+
state: LifecycleState | None = None,
|
|
77
|
+
*,
|
|
78
|
+
extra_capability_statuses: Mapping[str, CapabilityStatus] | None = None,
|
|
79
|
+
) -> HealthSnapshot:
|
|
80
|
+
lifecycle = state or LifecycleState()
|
|
81
|
+
capabilities = _capability_map(plan, lifecycle if state else None)
|
|
82
|
+
capability_statuses = {capability.name: capability.status for capability in capabilities}
|
|
83
|
+
normalized_extra = _normalize_extra_capability_statuses(extra_capability_statuses)
|
|
84
|
+
if normalized_extra:
|
|
85
|
+
capability_statuses.update(normalized_extra)
|
|
86
|
+
statuses = tuple(capability.status for capability in capabilities)
|
|
87
|
+
if normalized_extra:
|
|
88
|
+
statuses += tuple(normalized_extra.values())
|
|
89
|
+
unavailable_capabilities = tuple(
|
|
90
|
+
name
|
|
91
|
+
for name, status in capability_statuses.items()
|
|
92
|
+
if status == "unavailable"
|
|
93
|
+
)
|
|
94
|
+
return HealthSnapshot(
|
|
95
|
+
status=_aggregate_status(statuses, active=lifecycle.active),
|
|
96
|
+
phase=lifecycle.phase,
|
|
97
|
+
active=lifecycle.active,
|
|
98
|
+
enabled_components=plan.infra.enabled_components,
|
|
99
|
+
activated_capabilities=lifecycle.activated_capabilities,
|
|
100
|
+
capability_statuses=capability_statuses,
|
|
101
|
+
unavailable_capabilities=unavailable_capabilities,
|
|
102
|
+
)
|