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,157 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Iterable, Mapping
|
|
4
|
+
from importlib import metadata as importlib_metadata
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
import re
|
|
7
|
+
|
|
8
|
+
from pz_core.runtime.errors import PzError
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
PROJECT_CONFIG_NAME = "pz.jsonc"
|
|
12
|
+
PROJECT_ENV_CONFIG_PATTERN = "pz.{environment}.jsonc"
|
|
13
|
+
PZ_ENV_PREFIX = "PZ_"
|
|
14
|
+
_FORMAL_ENVIRONMENTS = ("develop", "test", "product")
|
|
15
|
+
|
|
16
|
+
_LEGACY_STEM = "pyz" + "za"
|
|
17
|
+
_LEGACY_ENV_PREFIX = _LEGACY_STEM.upper() + "_"
|
|
18
|
+
_LEGACY_APP_PREFIX = _LEGACY_STEM + "_"
|
|
19
|
+
_LEGACY_DISTRIBUTION_PREFIX = _LEGACY_STEM + "-"
|
|
20
|
+
_RETIRED_BASE_DISTRIBUTIONS = frozenset(
|
|
21
|
+
{"pz-core", "pz-settings-center", "pz-foundation", "pz-contrib"}
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _canonicalize_distribution_name(value: object) -> str:
|
|
26
|
+
return re.sub(r"[-_.]+", "-", str(value or "").strip()).lower()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _distribution_name(distribution: importlib_metadata.Distribution) -> str:
|
|
30
|
+
metadata = getattr(distribution, "metadata", None)
|
|
31
|
+
raw_name = metadata.get("Name") if metadata is not None and hasattr(metadata, "get") else None
|
|
32
|
+
if raw_name is None:
|
|
33
|
+
raw_name = getattr(distribution, "name", None)
|
|
34
|
+
return _canonicalize_distribution_name(raw_name)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def validate_process_environment(environ: Mapping[str, str]) -> None:
|
|
38
|
+
"""Reject every framework-owned v4 environment key."""
|
|
39
|
+
|
|
40
|
+
legacy_keys = sorted(
|
|
41
|
+
str(key)
|
|
42
|
+
for key in environ
|
|
43
|
+
if str(key).startswith(_LEGACY_ENV_PREFIX)
|
|
44
|
+
)
|
|
45
|
+
if not legacy_keys:
|
|
46
|
+
return
|
|
47
|
+
raise PzError(
|
|
48
|
+
code="PZ_LEGACY_ENV_UNSUPPORTED",
|
|
49
|
+
message=(
|
|
50
|
+
"Legacy framework environment keys are not supported. "
|
|
51
|
+
f"Use {PZ_ENV_PREFIX}* keys only."
|
|
52
|
+
),
|
|
53
|
+
stage="environment",
|
|
54
|
+
owner="runtime.environment_integrity",
|
|
55
|
+
action="validate_process_environment",
|
|
56
|
+
detail=", ".join(legacy_keys),
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def validate_installed_distributions(
|
|
61
|
+
distributions: Iterable[importlib_metadata.Distribution],
|
|
62
|
+
) -> None:
|
|
63
|
+
"""Reject every installed v4 framework distribution."""
|
|
64
|
+
|
|
65
|
+
unsupported_names = sorted(
|
|
66
|
+
{
|
|
67
|
+
name
|
|
68
|
+
for distribution in distributions
|
|
69
|
+
if (name := _distribution_name(distribution))
|
|
70
|
+
and (
|
|
71
|
+
name == _LEGACY_STEM
|
|
72
|
+
or name.startswith(_LEGACY_DISTRIBUTION_PREFIX)
|
|
73
|
+
or name in _RETIRED_BASE_DISTRIBUTIONS
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
)
|
|
77
|
+
if not unsupported_names:
|
|
78
|
+
return
|
|
79
|
+
raise PzError(
|
|
80
|
+
code="PZ_ENVIRONMENT_MIXED_GENERATIONS",
|
|
81
|
+
message=(
|
|
82
|
+
"The current Python environment contains unsupported legacy or "
|
|
83
|
+
"retired split-wheel distributions. Recreate it with pz-cli==5.0.0."
|
|
84
|
+
),
|
|
85
|
+
stage="environment",
|
|
86
|
+
owner="runtime.environment_integrity",
|
|
87
|
+
action="validate_installed_distributions",
|
|
88
|
+
detail=", ".join(unsupported_names),
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def validate_installed_app_identities(app_ids: Iterable[object]) -> None:
|
|
93
|
+
legacy_app_ids = sorted(
|
|
94
|
+
{
|
|
95
|
+
value
|
|
96
|
+
for raw_value in app_ids
|
|
97
|
+
if isinstance(raw_value, str)
|
|
98
|
+
and (value := raw_value.strip())
|
|
99
|
+
and any(part.startswith(_LEGACY_APP_PREFIX) for part in value.split("."))
|
|
100
|
+
}
|
|
101
|
+
)
|
|
102
|
+
if not legacy_app_ids:
|
|
103
|
+
return
|
|
104
|
+
raise PzError(
|
|
105
|
+
code="PZ_LEGACY_APP_ID_UNSUPPORTED",
|
|
106
|
+
message="installed_apps contains unsupported v4 app identities.",
|
|
107
|
+
stage="apps",
|
|
108
|
+
owner="runtime.environment_integrity",
|
|
109
|
+
action="validate_installed_app_identities",
|
|
110
|
+
detail=", ".join(legacy_app_ids),
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def validate_project_config_identity(project_dir: str | Path) -> None:
|
|
115
|
+
root = Path(project_dir).expanduser().resolve()
|
|
116
|
+
legacy_paths = [root / (_LEGACY_STEM + ".jsonc")]
|
|
117
|
+
legacy_paths.extend(
|
|
118
|
+
root / f"{_LEGACY_STEM}.{environment}.jsonc"
|
|
119
|
+
for environment in _FORMAL_ENVIRONMENTS
|
|
120
|
+
)
|
|
121
|
+
existing = sorted({path.resolve() for path in legacy_paths if path.is_file()})
|
|
122
|
+
if not existing:
|
|
123
|
+
return
|
|
124
|
+
raise PzError(
|
|
125
|
+
code="PZ_PROJECT_CONFIG_LEGACY_UNSUPPORTED",
|
|
126
|
+
message=(
|
|
127
|
+
"Legacy project configuration files are not supported. "
|
|
128
|
+
f"Use {PROJECT_CONFIG_NAME} and {PROJECT_ENV_CONFIG_PATTERN}."
|
|
129
|
+
),
|
|
130
|
+
stage="project",
|
|
131
|
+
owner="runtime.environment_integrity",
|
|
132
|
+
action="validate_project_config_identity",
|
|
133
|
+
detail=", ".join(path.name for path in existing),
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def validate_current_environment(
|
|
138
|
+
environ: Mapping[str, str],
|
|
139
|
+
*,
|
|
140
|
+
distributions: Iterable[importlib_metadata.Distribution] | None = None,
|
|
141
|
+
) -> None:
|
|
142
|
+
validate_process_environment(environ)
|
|
143
|
+
validate_installed_distributions(
|
|
144
|
+
importlib_metadata.distributions() if distributions is None else distributions
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
__all__ = [
|
|
149
|
+
"PROJECT_CONFIG_NAME",
|
|
150
|
+
"PROJECT_ENV_CONFIG_PATTERN",
|
|
151
|
+
"PZ_ENV_PREFIX",
|
|
152
|
+
"validate_current_environment",
|
|
153
|
+
"validate_installed_app_identities",
|
|
154
|
+
"validate_installed_distributions",
|
|
155
|
+
"validate_process_environment",
|
|
156
|
+
"validate_project_config_identity",
|
|
157
|
+
]
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from pz_core.runtime.errors import PzError
|
|
6
|
+
from pz_core.runtime.access import get_bindings
|
|
7
|
+
from pz_core.runtime.bindings import RuntimeBindings
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _resolve_runtime_bindings(
|
|
11
|
+
*,
|
|
12
|
+
bindings: RuntimeBindings | None = None,
|
|
13
|
+
request: Any | None = None,
|
|
14
|
+
runtime: Any | None = None,
|
|
15
|
+
) -> RuntimeBindings:
|
|
16
|
+
if bindings is not None:
|
|
17
|
+
if not isinstance(bindings, RuntimeBindings):
|
|
18
|
+
raise PzError(
|
|
19
|
+
code="PZ_RUNTIME_BINDINGS_INVALID",
|
|
20
|
+
message="runtime events bindings must be a RuntimeBindings instance.",
|
|
21
|
+
stage="events",
|
|
22
|
+
owner="runtime.events",
|
|
23
|
+
action="resolve_bindings",
|
|
24
|
+
)
|
|
25
|
+
return bindings
|
|
26
|
+
return get_bindings(request=request, runtime=runtime)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def publish_nowait(
|
|
30
|
+
event_name: str,
|
|
31
|
+
payload: dict[str, Any] | None = None,
|
|
32
|
+
*,
|
|
33
|
+
owner: str = "pz_core.runtime.events",
|
|
34
|
+
bindings: RuntimeBindings | None = None,
|
|
35
|
+
request: Any | None = None,
|
|
36
|
+
runtime: Any | None = None,
|
|
37
|
+
):
|
|
38
|
+
resolved_bindings = _resolve_runtime_bindings(
|
|
39
|
+
bindings=bindings,
|
|
40
|
+
request=request,
|
|
41
|
+
runtime=runtime,
|
|
42
|
+
)
|
|
43
|
+
return resolved_bindings.events.publish_nowait(event_name, payload, owner=owner)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
async def publish(
|
|
47
|
+
event_name: str,
|
|
48
|
+
payload: dict[str, Any] | None = None,
|
|
49
|
+
*,
|
|
50
|
+
owner: str = "pz_core.runtime.events",
|
|
51
|
+
bindings: RuntimeBindings | None = None,
|
|
52
|
+
request: Any | None = None,
|
|
53
|
+
runtime: Any | None = None,
|
|
54
|
+
):
|
|
55
|
+
resolved_bindings = _resolve_runtime_bindings(
|
|
56
|
+
bindings=bindings,
|
|
57
|
+
request=request,
|
|
58
|
+
runtime=runtime,
|
|
59
|
+
)
|
|
60
|
+
return await resolved_bindings.events.publish(event_name, payload, owner=owner)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def subscribe(
|
|
64
|
+
event_name: str,
|
|
65
|
+
handler,
|
|
66
|
+
*,
|
|
67
|
+
owner: str | None = None,
|
|
68
|
+
wildcard: bool = False,
|
|
69
|
+
bindings: RuntimeBindings | None = None,
|
|
70
|
+
request: Any | None = None,
|
|
71
|
+
runtime: Any | None = None,
|
|
72
|
+
):
|
|
73
|
+
normalized_owner = owner or getattr(handler, "__module__", "pz_core.runtime.events")
|
|
74
|
+
resolved_bindings = _resolve_runtime_bindings(
|
|
75
|
+
bindings=bindings,
|
|
76
|
+
request=request,
|
|
77
|
+
runtime=runtime,
|
|
78
|
+
)
|
|
79
|
+
return resolved_bindings.events.subscribe(
|
|
80
|
+
event_name,
|
|
81
|
+
handler,
|
|
82
|
+
owner=normalized_owner,
|
|
83
|
+
wildcard=wildcard,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
__all__ = ["publish", "publish_nowait", "subscribe"]
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .cache import CacheFacade
|
|
4
|
+
from .database import DatabaseFacade
|
|
5
|
+
from .events import EventBusFacade, EventDispatchResult, EventDispatchTicket, EventSubscription
|
|
6
|
+
from .health import HealthFacade
|
|
7
|
+
from .mail import MailFacade
|
|
8
|
+
from .observability import ObservabilityFacade
|
|
9
|
+
from .providers import ProviderFacade
|
|
10
|
+
from .resources import ResourceFacade
|
|
11
|
+
from .storage import StorageFacade
|
|
12
|
+
from .storage import (
|
|
13
|
+
RuntimePresignInfo,
|
|
14
|
+
RuntimeStoragePort,
|
|
15
|
+
RuntimeStoredObject,
|
|
16
|
+
StorageClient,
|
|
17
|
+
get_storage,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"CacheFacade",
|
|
22
|
+
"DatabaseFacade",
|
|
23
|
+
"EventBusFacade",
|
|
24
|
+
"EventDispatchResult",
|
|
25
|
+
"EventDispatchTicket",
|
|
26
|
+
"EventSubscription",
|
|
27
|
+
"HealthFacade",
|
|
28
|
+
"MailFacade",
|
|
29
|
+
"ObservabilityFacade",
|
|
30
|
+
"ProviderFacade",
|
|
31
|
+
"ResourceFacade",
|
|
32
|
+
"StorageFacade",
|
|
33
|
+
"RuntimePresignInfo",
|
|
34
|
+
"RuntimeStoragePort",
|
|
35
|
+
"RuntimeStoredObject",
|
|
36
|
+
"StorageClient",
|
|
37
|
+
"get_storage",
|
|
38
|
+
]
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pz_core.runtime.facades.providers import ProviderFacade
|
|
4
|
+
from pz_core.runtime.plan import RuntimePlan
|
|
5
|
+
from pz_core.runtime.registries import CapabilityStatus
|
|
6
|
+
from pz_core.runtime.errors import PzError
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def merged_capability_status(
|
|
10
|
+
plan: RuntimePlan,
|
|
11
|
+
providers: ProviderFacade,
|
|
12
|
+
capability: str,
|
|
13
|
+
) -> CapabilityStatus:
|
|
14
|
+
if not isinstance(plan, RuntimePlan):
|
|
15
|
+
raise PzError(
|
|
16
|
+
code="PZ_CAPABILITY_PLAN_INVALID",
|
|
17
|
+
message="capability status merge requires a RuntimePlan instance.",
|
|
18
|
+
stage="capabilities",
|
|
19
|
+
owner="runtime.capabilities",
|
|
20
|
+
action="merged_capability_status",
|
|
21
|
+
)
|
|
22
|
+
if not hasattr(providers, "declared_for") or not hasattr(providers, "status"):
|
|
23
|
+
raise PzError(
|
|
24
|
+
code="PZ_CAPABILITY_PROVIDERS_INVALID",
|
|
25
|
+
message="capability status merge requires providers with declared_for() and status().",
|
|
26
|
+
stage="capabilities",
|
|
27
|
+
owner="runtime.capabilities",
|
|
28
|
+
action="merged_capability_status",
|
|
29
|
+
)
|
|
30
|
+
if not isinstance(capability, str) or not capability.strip():
|
|
31
|
+
raise PzError(
|
|
32
|
+
code="PZ_CAPABILITY_NAME_INVALID",
|
|
33
|
+
message="capability name must be a non-empty string.",
|
|
34
|
+
stage="capabilities",
|
|
35
|
+
owner="runtime.capabilities",
|
|
36
|
+
action="merged_capability_status",
|
|
37
|
+
)
|
|
38
|
+
normalized = capability.strip()
|
|
39
|
+
base = plan.capability_registry.get(normalized)
|
|
40
|
+
base_status: CapabilityStatus = base.status if base is not None else "disabled"
|
|
41
|
+
if not providers.declared_for(normalized):
|
|
42
|
+
return base_status
|
|
43
|
+
provider_status = providers.status(normalized)
|
|
44
|
+
if provider_status == "disabled":
|
|
45
|
+
return base_status
|
|
46
|
+
return provider_status
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from pz_core.runtime.errors import PzError
|
|
6
|
+
from pz_core.infra.kv import CacheClientFactory, CachePort
|
|
7
|
+
from pz_core.runtime.facades._capabilities import merged_capability_status
|
|
8
|
+
from pz_core.runtime.facades.providers import ProviderFacade
|
|
9
|
+
from pz_core.runtime.plan import RuntimePlan
|
|
10
|
+
from pz_core.runtime.registries import CapabilityStatus
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _require_cache_key(key: str, *, action: str) -> str:
|
|
14
|
+
if not isinstance(key, str) or not key.strip():
|
|
15
|
+
raise PzError(
|
|
16
|
+
code="PZ_CACHE_KEY_INVALID",
|
|
17
|
+
message="Cache key must be a non-empty string.",
|
|
18
|
+
stage="cache",
|
|
19
|
+
owner="runtime.cache",
|
|
20
|
+
action=action,
|
|
21
|
+
)
|
|
22
|
+
return key
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _require_cache_ttl(ttl: int | None, *, action: str) -> int | None:
|
|
26
|
+
if ttl is None:
|
|
27
|
+
return None
|
|
28
|
+
if isinstance(ttl, bool) or not isinstance(ttl, int) or ttl <= 0:
|
|
29
|
+
raise PzError(
|
|
30
|
+
code="PZ_CACHE_TTL_INVALID",
|
|
31
|
+
message="Cache ttl must be a positive integer when configured.",
|
|
32
|
+
stage="cache",
|
|
33
|
+
owner="runtime.cache",
|
|
34
|
+
action=action,
|
|
35
|
+
)
|
|
36
|
+
return ttl
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class CacheFacade:
|
|
40
|
+
def __init__(self, plan: RuntimePlan, providers: ProviderFacade) -> None:
|
|
41
|
+
if not isinstance(plan, RuntimePlan):
|
|
42
|
+
raise PzError(
|
|
43
|
+
code="PZ_CACHE_PLAN_INVALID",
|
|
44
|
+
message="CacheFacade requires a RuntimePlan instance.",
|
|
45
|
+
stage="cache",
|
|
46
|
+
owner="runtime.cache",
|
|
47
|
+
action="bind_cache_facade",
|
|
48
|
+
)
|
|
49
|
+
if not hasattr(providers, "require"):
|
|
50
|
+
raise PzError(
|
|
51
|
+
code="PZ_CACHE_PROVIDERS_INVALID",
|
|
52
|
+
message="CacheFacade providers must expose require().",
|
|
53
|
+
stage="cache",
|
|
54
|
+
owner="runtime.cache",
|
|
55
|
+
action="bind_cache_facade",
|
|
56
|
+
)
|
|
57
|
+
self._plan = plan
|
|
58
|
+
self._providers = providers
|
|
59
|
+
|
|
60
|
+
def status(self) -> CapabilityStatus:
|
|
61
|
+
return merged_capability_status(self._plan, self._providers, "cache")
|
|
62
|
+
|
|
63
|
+
def _cache(self) -> CachePort:
|
|
64
|
+
provider = self._providers.require("cache")
|
|
65
|
+
if isinstance(provider, CachePort):
|
|
66
|
+
return provider
|
|
67
|
+
if isinstance(provider, CacheClientFactory):
|
|
68
|
+
return provider.create_cache()
|
|
69
|
+
raise PzError(
|
|
70
|
+
code="PZ_CACHE_PROVIDER_INVALID",
|
|
71
|
+
message="Registered cache provider does not implement CachePort or CacheClientFactory.",
|
|
72
|
+
stage="cache",
|
|
73
|
+
owner="infra.cache",
|
|
74
|
+
action="resolve_cache",
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
def get(self, key: str) -> Any:
|
|
78
|
+
key = _require_cache_key(key, action="get")
|
|
79
|
+
return self._cache().get(key)
|
|
80
|
+
|
|
81
|
+
def set(self, key: str, value: object, *, ttl: int | None = None) -> None:
|
|
82
|
+
key = _require_cache_key(key, action="set")
|
|
83
|
+
ttl = _require_cache_ttl(ttl, action="set")
|
|
84
|
+
self._cache().set(key, value, ttl_seconds=ttl)
|
|
85
|
+
|
|
86
|
+
def delete(self, key: str) -> None:
|
|
87
|
+
key = _require_cache_key(key, action="delete")
|
|
88
|
+
self._cache().delete(key)
|
|
89
|
+
|
|
90
|
+
def lock(self, key: str, *, ttl: int | None = None) -> object:
|
|
91
|
+
key = _require_cache_key(key, action="lock")
|
|
92
|
+
ttl = _require_cache_ttl(ttl, action="lock")
|
|
93
|
+
provider = self._providers.require("cache")
|
|
94
|
+
lock_factory = getattr(provider, "lock", None)
|
|
95
|
+
if not callable(lock_factory):
|
|
96
|
+
raise PzError(
|
|
97
|
+
code="PZ_CACHE_LOCK_UNSUPPORTED",
|
|
98
|
+
message="Registered cache provider does not expose lock().",
|
|
99
|
+
stage="cache",
|
|
100
|
+
owner="infra.cache",
|
|
101
|
+
action="lock",
|
|
102
|
+
)
|
|
103
|
+
return lock_factory(key, ttl=ttl)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pz_core.runtime.errors import PzError
|
|
4
|
+
from pz_core.infra.db import DatabaseAdapter
|
|
5
|
+
from pz_core.runtime.facades._capabilities import merged_capability_status
|
|
6
|
+
from pz_core.runtime.facades.providers import ProviderFacade
|
|
7
|
+
from pz_core.runtime.plan import RuntimePlan
|
|
8
|
+
from pz_core.runtime.registries import CapabilityStatus
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class DatabaseFacade:
|
|
12
|
+
def __init__(self, plan: RuntimePlan, providers: ProviderFacade) -> None:
|
|
13
|
+
if not isinstance(plan, RuntimePlan):
|
|
14
|
+
raise PzError(
|
|
15
|
+
code="PZ_DATABASE_PLAN_INVALID",
|
|
16
|
+
message="DatabaseFacade requires a RuntimePlan instance.",
|
|
17
|
+
stage="database",
|
|
18
|
+
owner="runtime.database",
|
|
19
|
+
action="bind_database_facade",
|
|
20
|
+
)
|
|
21
|
+
if not hasattr(providers, "require"):
|
|
22
|
+
raise PzError(
|
|
23
|
+
code="PZ_DATABASE_PROVIDERS_INVALID",
|
|
24
|
+
message="DatabaseFacade providers must expose require().",
|
|
25
|
+
stage="database",
|
|
26
|
+
owner="runtime.database",
|
|
27
|
+
action="bind_database_facade",
|
|
28
|
+
)
|
|
29
|
+
self._plan = plan
|
|
30
|
+
self._providers = providers
|
|
31
|
+
|
|
32
|
+
def status(self) -> CapabilityStatus:
|
|
33
|
+
return merged_capability_status(self._plan, self._providers, "database")
|
|
34
|
+
|
|
35
|
+
def connection(self) -> DatabaseAdapter:
|
|
36
|
+
provider = self._providers.require("database")
|
|
37
|
+
if not isinstance(provider, DatabaseAdapter):
|
|
38
|
+
raise PzError(
|
|
39
|
+
code="PZ_DATABASE_PROVIDER_INVALID",
|
|
40
|
+
message="Registered database provider does not implement DatabaseAdapter.",
|
|
41
|
+
stage="database",
|
|
42
|
+
owner="infra.database",
|
|
43
|
+
action="connection",
|
|
44
|
+
)
|
|
45
|
+
return provider
|
|
46
|
+
|
|
47
|
+
def session(self):
|
|
48
|
+
connection = self.connection()
|
|
49
|
+
factory = getattr(connection, "create_session", None)
|
|
50
|
+
if not callable(factory):
|
|
51
|
+
raise PzError(
|
|
52
|
+
code="PZ_DATABASE_SESSION_UNSUPPORTED",
|
|
53
|
+
message="Registered database adapter does not expose create_session().",
|
|
54
|
+
stage="database",
|
|
55
|
+
owner="infra.database",
|
|
56
|
+
action="session",
|
|
57
|
+
)
|
|
58
|
+
return factory()
|
|
59
|
+
|
|
60
|
+
def transaction(self):
|
|
61
|
+
session = self.session()
|
|
62
|
+
begin = getattr(session, "begin", None)
|
|
63
|
+
if not callable(begin):
|
|
64
|
+
raise PzError(
|
|
65
|
+
code="PZ_DATABASE_TRANSACTION_UNSUPPORTED",
|
|
66
|
+
message="Database session does not expose begin().",
|
|
67
|
+
stage="database",
|
|
68
|
+
owner="infra.database",
|
|
69
|
+
action="transaction",
|
|
70
|
+
)
|
|
71
|
+
return begin()
|