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,508 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import asdict, is_dataclass
|
|
4
|
+
import inspect
|
|
5
|
+
from typing import Mapping
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from pz_core.assembly.app_discovery import read_static_app_declaration
|
|
9
|
+
from pz_core.assembly.apps import AppRegistry, load_app_entrypoint_object_from_decl
|
|
10
|
+
from pz_core.assembly.project import active_project_import_root
|
|
11
|
+
from pz_core.assembly.settings import SettingsSnapshot
|
|
12
|
+
from pz_core.core.errors import PzError
|
|
13
|
+
from pz_core.core.middlewares import MiddlewareDecl, MiddlewareManifest
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _read_required_string(
|
|
17
|
+
value: object,
|
|
18
|
+
*,
|
|
19
|
+
code: str,
|
|
20
|
+
message: str,
|
|
21
|
+
owner: str,
|
|
22
|
+
) -> str:
|
|
23
|
+
if not isinstance(value, str) or not value.strip():
|
|
24
|
+
raise PzError(
|
|
25
|
+
code=code,
|
|
26
|
+
message=message,
|
|
27
|
+
stage="middlewares",
|
|
28
|
+
owner=owner,
|
|
29
|
+
action="compile_middleware_manifest",
|
|
30
|
+
)
|
|
31
|
+
return value.strip()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _read_optional_string(
|
|
35
|
+
value: object,
|
|
36
|
+
*,
|
|
37
|
+
default: str | None,
|
|
38
|
+
code: str,
|
|
39
|
+
message: str,
|
|
40
|
+
owner: str,
|
|
41
|
+
) -> str | None:
|
|
42
|
+
if value is None:
|
|
43
|
+
return default
|
|
44
|
+
if not isinstance(value, str) or not value.strip():
|
|
45
|
+
raise PzError(
|
|
46
|
+
code=code,
|
|
47
|
+
message=message,
|
|
48
|
+
stage="middlewares",
|
|
49
|
+
owner=owner,
|
|
50
|
+
action="compile_middleware_manifest",
|
|
51
|
+
)
|
|
52
|
+
return value.strip()
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _read_priority(
|
|
56
|
+
value: object,
|
|
57
|
+
*,
|
|
58
|
+
default: int,
|
|
59
|
+
code: str,
|
|
60
|
+
message: str,
|
|
61
|
+
owner: str,
|
|
62
|
+
) -> int:
|
|
63
|
+
if value is None:
|
|
64
|
+
return int(default)
|
|
65
|
+
if isinstance(value, bool):
|
|
66
|
+
raise PzError(
|
|
67
|
+
code=code,
|
|
68
|
+
message=message,
|
|
69
|
+
stage="middlewares",
|
|
70
|
+
owner=owner,
|
|
71
|
+
action="compile_middleware_manifest",
|
|
72
|
+
)
|
|
73
|
+
if isinstance(value, int):
|
|
74
|
+
return int(value)
|
|
75
|
+
if isinstance(value, str) and value.strip():
|
|
76
|
+
try:
|
|
77
|
+
return int(value.strip())
|
|
78
|
+
except ValueError as exc:
|
|
79
|
+
raise PzError(
|
|
80
|
+
code=code,
|
|
81
|
+
message=message,
|
|
82
|
+
stage="middlewares",
|
|
83
|
+
owner=owner,
|
|
84
|
+
action="compile_middleware_manifest",
|
|
85
|
+
) from exc
|
|
86
|
+
raise PzError(
|
|
87
|
+
code=code,
|
|
88
|
+
message=message,
|
|
89
|
+
stage="middlewares",
|
|
90
|
+
owner=owner,
|
|
91
|
+
action="compile_middleware_manifest",
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _normalize_import_path(import_path: object, *, owner: str) -> str:
|
|
96
|
+
value = _read_required_string(
|
|
97
|
+
import_path,
|
|
98
|
+
code="PZ_MIDDLEWARE_IMPORT_INVALID",
|
|
99
|
+
message=f"Middleware '{owner}' must declare import/factory as a non-empty string path.",
|
|
100
|
+
owner=owner,
|
|
101
|
+
)
|
|
102
|
+
if ":" in value:
|
|
103
|
+
module_name, _, attr_name = value.partition(":")
|
|
104
|
+
else:
|
|
105
|
+
module_name, _, attr_name = value.rpartition(".")
|
|
106
|
+
if not module_name or not attr_name:
|
|
107
|
+
raise PzError(
|
|
108
|
+
code="PZ_MIDDLEWARE_IMPORT_INVALID",
|
|
109
|
+
message=f"Middleware import path '{import_path}' must use '<module>:<attr>' format.",
|
|
110
|
+
stage="middlewares",
|
|
111
|
+
owner=owner,
|
|
112
|
+
action="compile_middleware_manifest",
|
|
113
|
+
)
|
|
114
|
+
return f"{module_name}:{attr_name}"
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _normalize_validated_params(
|
|
118
|
+
validated: object,
|
|
119
|
+
raw_params: Mapping[str, Any],
|
|
120
|
+
*,
|
|
121
|
+
middleware_id: str,
|
|
122
|
+
owner: str,
|
|
123
|
+
) -> dict[str, Any]:
|
|
124
|
+
if validated is None:
|
|
125
|
+
return {}
|
|
126
|
+
model_dump = getattr(validated, "model_dump", None)
|
|
127
|
+
if callable(model_dump):
|
|
128
|
+
payload = model_dump()
|
|
129
|
+
if isinstance(payload, dict):
|
|
130
|
+
return dict(payload)
|
|
131
|
+
dict_method = getattr(validated, "dict", None)
|
|
132
|
+
if callable(dict_method):
|
|
133
|
+
payload = dict_method()
|
|
134
|
+
if isinstance(payload, dict):
|
|
135
|
+
return dict(payload)
|
|
136
|
+
if is_dataclass(validated):
|
|
137
|
+
payload = asdict(validated)
|
|
138
|
+
if isinstance(payload, dict):
|
|
139
|
+
return dict(payload)
|
|
140
|
+
if isinstance(validated, Mapping):
|
|
141
|
+
return dict(validated)
|
|
142
|
+
extracted: dict[str, Any] = {}
|
|
143
|
+
for key in raw_params:
|
|
144
|
+
if hasattr(validated, key):
|
|
145
|
+
extracted[str(key)] = getattr(validated, key)
|
|
146
|
+
if len(extracted) == len(raw_params):
|
|
147
|
+
return extracted
|
|
148
|
+
try:
|
|
149
|
+
payload = vars(validated)
|
|
150
|
+
except TypeError as exc:
|
|
151
|
+
raise PzError(
|
|
152
|
+
code="PZ_MIDDLEWARE_PARAMS_INVALID",
|
|
153
|
+
message=(
|
|
154
|
+
f"Middleware '{middleware_id}' params_model must expose normalized params via "
|
|
155
|
+
"model_dump(), dict(), dataclass fields, Mapping semantics, or matching attributes."
|
|
156
|
+
),
|
|
157
|
+
stage="middlewares",
|
|
158
|
+
owner=owner,
|
|
159
|
+
action="compile_middleware_manifest",
|
|
160
|
+
) from exc
|
|
161
|
+
if isinstance(payload, dict):
|
|
162
|
+
return dict(payload)
|
|
163
|
+
raise PzError(
|
|
164
|
+
code="PZ_MIDDLEWARE_PARAMS_INVALID",
|
|
165
|
+
message=(
|
|
166
|
+
f"Middleware '{middleware_id}' params_model must expose normalized params via "
|
|
167
|
+
"model_dump(), dict(), dataclass fields, Mapping semantics, or matching attributes."
|
|
168
|
+
),
|
|
169
|
+
stage="middlewares",
|
|
170
|
+
owner=owner,
|
|
171
|
+
action="compile_middleware_manifest",
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def _validate_params_model(
|
|
176
|
+
params_model_path: str | None,
|
|
177
|
+
params: dict[str, Any] | None,
|
|
178
|
+
*,
|
|
179
|
+
owner: str,
|
|
180
|
+
middleware_id: str,
|
|
181
|
+
) -> dict[str, Any] | None:
|
|
182
|
+
if not params:
|
|
183
|
+
return None
|
|
184
|
+
if not params_model_path:
|
|
185
|
+
raise PzError(
|
|
186
|
+
code="PZ_MIDDLEWARE_PARAMS_MODEL_MISSING",
|
|
187
|
+
message=(
|
|
188
|
+
f"Middleware '{middleware_id}' declares params but does not declare a params_model."
|
|
189
|
+
),
|
|
190
|
+
stage="middlewares",
|
|
191
|
+
owner=owner,
|
|
192
|
+
action="compile_middleware_manifest",
|
|
193
|
+
)
|
|
194
|
+
try:
|
|
195
|
+
module_name, _, attr_name = _normalize_import_path(params_model_path, owner=middleware_id).partition(":")
|
|
196
|
+
params_model = getattr(__import__(module_name, fromlist=[attr_name]), attr_name)
|
|
197
|
+
validated = params_model(**params)
|
|
198
|
+
return _normalize_validated_params(validated, params, middleware_id=middleware_id, owner=owner)
|
|
199
|
+
except PzError:
|
|
200
|
+
raise
|
|
201
|
+
except Exception as exc:
|
|
202
|
+
raise PzError(
|
|
203
|
+
code="PZ_MIDDLEWARE_PARAMS_INVALID",
|
|
204
|
+
message=f"Middleware '{middleware_id}' params failed validation: {exc}",
|
|
205
|
+
stage="middlewares",
|
|
206
|
+
owner=owner,
|
|
207
|
+
action="compile_middleware_manifest",
|
|
208
|
+
) from exc
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def _compile_decl(item: object, idx: int, *, owner_hint: str = "runtime") -> MiddlewareDecl | None:
|
|
212
|
+
if isinstance(item, MiddlewareDecl):
|
|
213
|
+
return item
|
|
214
|
+
if isinstance(item, str):
|
|
215
|
+
factory = item.strip()
|
|
216
|
+
owner = owner_hint
|
|
217
|
+
mid = f"middleware_{idx}"
|
|
218
|
+
priority = 100
|
|
219
|
+
replace = None
|
|
220
|
+
params_model = None
|
|
221
|
+
params = None
|
|
222
|
+
elif isinstance(item, dict):
|
|
223
|
+
owner = _read_optional_string(
|
|
224
|
+
item.get("owner"),
|
|
225
|
+
default=owner_hint,
|
|
226
|
+
code="PZ_MIDDLEWARE_OWNER_INVALID",
|
|
227
|
+
message="Middleware owner must be a non-empty string when provided.",
|
|
228
|
+
owner="runtime.middlewares",
|
|
229
|
+
) or owner_hint
|
|
230
|
+
mid = _read_optional_string(
|
|
231
|
+
item.get("id"),
|
|
232
|
+
default=f"middleware_{idx}",
|
|
233
|
+
code="PZ_MIDDLEWARE_ID_INVALID",
|
|
234
|
+
message="Middleware id must be a non-empty string when provided.",
|
|
235
|
+
owner=owner,
|
|
236
|
+
) or f"middleware_{idx}"
|
|
237
|
+
priority = _read_priority(
|
|
238
|
+
item.get("priority"),
|
|
239
|
+
default=100,
|
|
240
|
+
code="PZ_MIDDLEWARE_PRIORITY_INVALID",
|
|
241
|
+
message=f"Middleware '{mid}' priority must be an integer when provided.",
|
|
242
|
+
owner=owner,
|
|
243
|
+
)
|
|
244
|
+
factory = _read_optional_string(
|
|
245
|
+
item.get("factory"),
|
|
246
|
+
default=None,
|
|
247
|
+
code="PZ_MIDDLEWARE_IMPORT_INVALID",
|
|
248
|
+
message=f"Middleware '{mid}' factory must be a non-empty string when provided.",
|
|
249
|
+
owner=owner,
|
|
250
|
+
)
|
|
251
|
+
replace = _read_optional_string(
|
|
252
|
+
item.get("replace"),
|
|
253
|
+
default=None,
|
|
254
|
+
code="PZ_MIDDLEWARE_REPLACE_INVALID",
|
|
255
|
+
message=f"Middleware '{mid}' replace target must be a non-empty string when provided.",
|
|
256
|
+
owner=owner,
|
|
257
|
+
)
|
|
258
|
+
params_model = _read_optional_string(
|
|
259
|
+
item.get("params_model"),
|
|
260
|
+
default=None,
|
|
261
|
+
code="PZ_MIDDLEWARE_PARAMS_MODEL_INVALID",
|
|
262
|
+
message=f"Middleware '{mid}' params_model must be a non-empty string when provided.",
|
|
263
|
+
owner=owner,
|
|
264
|
+
)
|
|
265
|
+
raw_params = item.get("params")
|
|
266
|
+
if raw_params in (None, {}):
|
|
267
|
+
params = None
|
|
268
|
+
elif not isinstance(raw_params, dict):
|
|
269
|
+
raise PzError(
|
|
270
|
+
code="PZ_MIDDLEWARE_PARAMS_INVALID",
|
|
271
|
+
message=f"Middleware '{mid}' params must be a table.",
|
|
272
|
+
stage="middlewares",
|
|
273
|
+
owner=owner,
|
|
274
|
+
action="compile_middleware_manifest",
|
|
275
|
+
)
|
|
276
|
+
else:
|
|
277
|
+
params = dict(raw_params)
|
|
278
|
+
else:
|
|
279
|
+
raise PzError(
|
|
280
|
+
code="PZ_MIDDLEWARE_ITEM_INVALID",
|
|
281
|
+
message="Each middleware declaration must be a string import path or a table.",
|
|
282
|
+
stage="middlewares",
|
|
283
|
+
owner="runtime.middlewares",
|
|
284
|
+
action="compile_middleware_manifest",
|
|
285
|
+
)
|
|
286
|
+
if not factory:
|
|
287
|
+
raise PzError(
|
|
288
|
+
code="PZ_MIDDLEWARE_IMPORT_INVALID",
|
|
289
|
+
message=f"Middleware '{mid}' must declare a non-empty import/factory path.",
|
|
290
|
+
stage="middlewares",
|
|
291
|
+
owner=owner,
|
|
292
|
+
action="compile_middleware_manifest",
|
|
293
|
+
)
|
|
294
|
+
factory = _normalize_import_path(factory, owner=mid)
|
|
295
|
+
params = _validate_params_model(params_model, params, owner=owner, middleware_id=mid)
|
|
296
|
+
return MiddlewareDecl(
|
|
297
|
+
id=mid,
|
|
298
|
+
factory=factory,
|
|
299
|
+
owner=owner,
|
|
300
|
+
priority=priority,
|
|
301
|
+
replace=replace,
|
|
302
|
+
params_model=params_model,
|
|
303
|
+
params=params,
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def _load_app_declared_middlewares(
|
|
308
|
+
settings: SettingsSnapshot,
|
|
309
|
+
app_registry: AppRegistry,
|
|
310
|
+
) -> tuple[object, ...]:
|
|
311
|
+
out: list[object] = []
|
|
312
|
+
for app in app_registry.apps:
|
|
313
|
+
static_decl = read_static_app_declaration(
|
|
314
|
+
app.module_path,
|
|
315
|
+
action="compile_middleware_manifest",
|
|
316
|
+
)
|
|
317
|
+
if "middlewares" not in static_decl.method_names:
|
|
318
|
+
continue
|
|
319
|
+
app_obj = load_app_entrypoint_object_from_decl(app)
|
|
320
|
+
middlewares_factory = getattr(app_obj, "middlewares", None)
|
|
321
|
+
if middlewares_factory is None:
|
|
322
|
+
continue
|
|
323
|
+
if not callable(middlewares_factory):
|
|
324
|
+
raise PzError(
|
|
325
|
+
code="PZ_APP_MIDDLEWARES_INVALID",
|
|
326
|
+
message=f"App '{app.app_id}' exposes non-callable middlewares().",
|
|
327
|
+
stage="middlewares",
|
|
328
|
+
owner=app.app_id,
|
|
329
|
+
action="compile_middleware_manifest",
|
|
330
|
+
)
|
|
331
|
+
signature = inspect.signature(middlewares_factory)
|
|
332
|
+
if len(signature.parameters) == 0:
|
|
333
|
+
declared = middlewares_factory()
|
|
334
|
+
else:
|
|
335
|
+
declared = middlewares_factory(settings)
|
|
336
|
+
if declared in (None, (), []):
|
|
337
|
+
continue
|
|
338
|
+
if not isinstance(declared, (list, tuple)):
|
|
339
|
+
raise PzError(
|
|
340
|
+
code="PZ_APP_MIDDLEWARES_INVALID",
|
|
341
|
+
message=f"App '{app.app_id}' middlewares() must return a list or tuple.",
|
|
342
|
+
stage="middlewares",
|
|
343
|
+
owner=app.app_id,
|
|
344
|
+
action="compile_middleware_manifest",
|
|
345
|
+
)
|
|
346
|
+
for item in declared:
|
|
347
|
+
if not isinstance(item, MiddlewareDecl):
|
|
348
|
+
raise PzError(
|
|
349
|
+
code="PZ_APP_MIDDLEWARE_DECL_INVALID",
|
|
350
|
+
message=(
|
|
351
|
+
f"App '{app.app_id}' middlewares() must return MiddlewareDecl objects. "
|
|
352
|
+
"Legacy string/table declarations are not accepted in app code."
|
|
353
|
+
),
|
|
354
|
+
stage="middlewares",
|
|
355
|
+
owner=app.app_id,
|
|
356
|
+
action="compile_middleware_manifest",
|
|
357
|
+
)
|
|
358
|
+
out.append((app.app_id, item))
|
|
359
|
+
return tuple(out)
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
def sort_middleware_declarations(
|
|
363
|
+
declarations: tuple[tuple[str, object], ...],
|
|
364
|
+
) -> MiddlewareManifest:
|
|
365
|
+
out: list[MiddlewareDecl] = []
|
|
366
|
+
active_ids: dict[str, int] = {}
|
|
367
|
+
|
|
368
|
+
for idx, (owner_hint, item) in enumerate(declarations):
|
|
369
|
+
decl = _compile_decl(item, idx, owner_hint=owner_hint)
|
|
370
|
+
if decl is None:
|
|
371
|
+
continue
|
|
372
|
+
if decl.replace:
|
|
373
|
+
replaced_idx = active_ids.get(decl.replace)
|
|
374
|
+
if replaced_idx is None:
|
|
375
|
+
raise PzError(
|
|
376
|
+
code="PZ_MIDDLEWARE_REPLACE_TARGET_MISSING",
|
|
377
|
+
message=(
|
|
378
|
+
f"Middleware '{decl.id}' cannot replace missing middleware "
|
|
379
|
+
f"'{decl.replace}'."
|
|
380
|
+
),
|
|
381
|
+
stage="middlewares",
|
|
382
|
+
owner=decl.owner,
|
|
383
|
+
action="compile_middleware_manifest",
|
|
384
|
+
)
|
|
385
|
+
out.pop(replaced_idx)
|
|
386
|
+
active_ids = {item.id: current for current, item in enumerate(out)}
|
|
387
|
+
|
|
388
|
+
current_idx = active_ids.get(decl.id)
|
|
389
|
+
if current_idx is not None:
|
|
390
|
+
previous = out[current_idx]
|
|
391
|
+
raise PzError(
|
|
392
|
+
code="PZ_MIDDLEWARE_DUPLICATE_ID",
|
|
393
|
+
message=(
|
|
394
|
+
f"Middleware id '{decl.id}' is declared more than once "
|
|
395
|
+
f"by owners '{previous.owner}' and '{decl.owner}'."
|
|
396
|
+
),
|
|
397
|
+
stage="middlewares",
|
|
398
|
+
owner=decl.owner,
|
|
399
|
+
action="compile_middleware_manifest",
|
|
400
|
+
)
|
|
401
|
+
out.append(decl)
|
|
402
|
+
active_ids[decl.id] = len(out) - 1
|
|
403
|
+
return MiddlewareManifest(middlewares=tuple(out))
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
def compile_conventional_middleware_manifest(
|
|
407
|
+
settings: SettingsSnapshot,
|
|
408
|
+
app_registry: AppRegistry,
|
|
409
|
+
) -> MiddlewareManifest:
|
|
410
|
+
project_dir = getattr(settings, "project_dir", None)
|
|
411
|
+
import_roots = getattr(settings, "import_roots", ())
|
|
412
|
+
with active_project_import_root(
|
|
413
|
+
project_dir,
|
|
414
|
+
extra_import_roots=import_roots,
|
|
415
|
+
):
|
|
416
|
+
owner_order = {app.app_id: idx for idx, app in enumerate(app_registry.apps)}
|
|
417
|
+
declarations = list(_load_app_declared_middlewares(settings, app_registry))
|
|
418
|
+
declarations.sort(
|
|
419
|
+
key=lambda item: (
|
|
420
|
+
int(100 if getattr(item[1], "priority", 100) is None else getattr(item[1], "priority", 100)),
|
|
421
|
+
owner_order.get(item[0], len(owner_order)),
|
|
422
|
+
str(getattr(item[1], "id", "") or ""),
|
|
423
|
+
)
|
|
424
|
+
)
|
|
425
|
+
return sort_middleware_declarations(tuple(declarations))
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
def merge_explicit_middleware_order(
|
|
429
|
+
existing_ids: tuple[str, ...] | list[str],
|
|
430
|
+
conventional_manifest: MiddlewareManifest,
|
|
431
|
+
) -> MiddlewareManifest:
|
|
432
|
+
conventional_ids = tuple(item.id for item in conventional_manifest.middlewares)
|
|
433
|
+
conventional_set = set(conventional_ids)
|
|
434
|
+
existing: list[str] = []
|
|
435
|
+
seen_existing: set[str] = set()
|
|
436
|
+
for item in existing_ids:
|
|
437
|
+
candidate = str(item).strip()
|
|
438
|
+
if not candidate or candidate not in conventional_set or candidate in seen_existing:
|
|
439
|
+
continue
|
|
440
|
+
existing.append(candidate)
|
|
441
|
+
seen_existing.add(candidate)
|
|
442
|
+
existing = tuple(existing)
|
|
443
|
+
if not existing:
|
|
444
|
+
return conventional_manifest
|
|
445
|
+
|
|
446
|
+
by_id = {item.id: item for item in conventional_manifest.middlewares}
|
|
447
|
+
existing_set = set(existing)
|
|
448
|
+
ordered_ids = list(existing)
|
|
449
|
+
for index, candidate in enumerate(conventional_ids):
|
|
450
|
+
if candidate in existing_set:
|
|
451
|
+
continue
|
|
452
|
+
anchor: str | None = None
|
|
453
|
+
for following in conventional_ids[index + 1 :]:
|
|
454
|
+
if following in existing_set:
|
|
455
|
+
anchor = following
|
|
456
|
+
break
|
|
457
|
+
if anchor is None:
|
|
458
|
+
ordered_ids.append(candidate)
|
|
459
|
+
continue
|
|
460
|
+
ordered_ids.insert(ordered_ids.index(anchor), candidate)
|
|
461
|
+
return MiddlewareManifest(middlewares=tuple(by_id[item_id] for item_id in ordered_ids))
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
def compile_middleware_manifest(
|
|
465
|
+
settings: SettingsSnapshot,
|
|
466
|
+
app_registry: AppRegistry | None = None,
|
|
467
|
+
) -> MiddlewareManifest:
|
|
468
|
+
raw_middlewares = settings.get("middlewares", default=[])
|
|
469
|
+
if not isinstance(raw_middlewares, list):
|
|
470
|
+
raise PzError(
|
|
471
|
+
code="PZ_MIDDLEWARES_CONFIG_INVALID",
|
|
472
|
+
message="middlewares must be declared as an array of middleware declarations.",
|
|
473
|
+
stage="middlewares",
|
|
474
|
+
owner="runtime.middlewares",
|
|
475
|
+
action="compile_middleware_manifest",
|
|
476
|
+
)
|
|
477
|
+
|
|
478
|
+
explicit_manifest = sort_middleware_declarations(tuple(("runtime", item) for item in raw_middlewares))
|
|
479
|
+
if app_registry is None:
|
|
480
|
+
return explicit_manifest
|
|
481
|
+
|
|
482
|
+
conventional_manifest = compile_conventional_middleware_manifest(settings, app_registry)
|
|
483
|
+
if not explicit_manifest.middlewares:
|
|
484
|
+
return conventional_manifest
|
|
485
|
+
|
|
486
|
+
explicit_by_id = {item.id: item for item in explicit_manifest.middlewares}
|
|
487
|
+
explicit_ids = tuple(item.id for item in explicit_manifest.middlewares)
|
|
488
|
+
explicit_set = set(explicit_ids)
|
|
489
|
+
merged_ids = list(explicit_ids)
|
|
490
|
+
conventional_ids = tuple(item.id for item in conventional_manifest.middlewares)
|
|
491
|
+
for index, candidate in enumerate(conventional_ids):
|
|
492
|
+
if candidate in explicit_set:
|
|
493
|
+
continue
|
|
494
|
+
anchor: str | None = None
|
|
495
|
+
for following in conventional_ids[index + 1 :]:
|
|
496
|
+
if following in explicit_set:
|
|
497
|
+
anchor = following
|
|
498
|
+
break
|
|
499
|
+
if anchor is None:
|
|
500
|
+
merged_ids.append(candidate)
|
|
501
|
+
continue
|
|
502
|
+
merged_ids.insert(merged_ids.index(anchor), candidate)
|
|
503
|
+
conventional_by_id = {item.id: item for item in conventional_manifest.middlewares}
|
|
504
|
+
merged: list[MiddlewareDecl] = [
|
|
505
|
+
explicit_by_id[item_id] if item_id in explicit_by_id else conventional_by_id[item_id]
|
|
506
|
+
for item_id in merged_ids
|
|
507
|
+
]
|
|
508
|
+
return MiddlewareManifest(middlewares=tuple(merged))
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .context import ProjectContext
|
|
4
|
+
from .compiler import compile_project_context
|
|
5
|
+
from .discovery import active_project_import_root, resolve_project_context
|
|
6
|
+
|
|
7
|
+
__all__ = ["ProjectContext", "active_project_import_root", "compile_project_context", "resolve_project_context"]
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from pz_core.assembly.project.context import ProjectContext
|
|
5
|
+
from pz_core.assembly.project.discovery import resolve_project_context
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def compile_project_context(project_dir: str | os.PathLike[str] | None = None) -> ProjectContext:
|
|
9
|
+
return resolve_project_context(project_dir=project_dir)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass(frozen=True, slots=True)
|
|
8
|
+
class ProjectContext:
|
|
9
|
+
project_dir: Path
|
|
10
|
+
project_config_path: Path
|
|
11
|
+
env_file_path: Path
|
|
12
|
+
cache_dir: Path
|
|
13
|
+
runtime_dir: Path
|
|
14
|
+
asset_dir: Path
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
__all__ = ["ProjectContext"]
|