pycharter 0.0.24__py3-none-any.whl → 0.0.26__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.
- pycharter/__init__.py +6 -0
- pycharter/api/README.md +340 -0
- {api → pycharter/api}/__init__.py +1 -1
- {api → pycharter/api}/dependencies/__init__.py +2 -2
- pycharter/api/dependencies/auth.py +158 -0
- {api → pycharter/api}/main.py +32 -4
- {api → pycharter/api}/models/__init__.py +4 -4
- pycharter/api/models/etl.py +66 -0
- {api → pycharter/api}/routes/v1/__init__.py +5 -1
- pycharter/api/routes/v1/auth.py +97 -0
- {api → pycharter/api}/routes/v1/contracts.py +14 -12
- {api → pycharter/api}/routes/v1/docs.py +2 -2
- pycharter/api/routes/v1/etl.py +131 -0
- {api → pycharter/api}/routes/v1/evolution.py +2 -2
- {api → pycharter/api}/routes/v1/metadata.py +5 -5
- {api → pycharter/api}/routes/v1/quality.py +3 -3
- {api → pycharter/api}/routes/v1/schemas.py +1 -1
- {api → pycharter/api}/routes/v1/settings.py +1 -1
- {api → pycharter/api}/routes/v1/tracking.py +1 -1
- {api → pycharter/api}/routes/v1/validation.py +2 -2
- {api → pycharter/api}/routes/v1/validation_jobs.py +3 -3
- pycharter/cli.py +9 -11
- pycharter/config.py +69 -0
- pycharter/contract_builder/builder.py +32 -37
- pycharter/data/seed/compliance_frameworks.yaml +22 -0
- pycharter/data/seed/contracts.yaml +130 -0
- pycharter/data/seed/data_feeds.yaml +22 -0
- pycharter/data/seed/domains.yaml +13 -0
- pycharter/data/seed/environments.yaml +19 -0
- pycharter/data/seed/owners.yaml +21 -0
- pycharter/data/seed/systems.yaml +13 -0
- pycharter/data/seed/tags.yaml +25 -0
- pycharter/data/templates/contract/README.md +161 -0
- pycharter/data/templates/contract/template_contract.yaml +37 -0
- pycharter/data/templates/etl/README.md +1 -1
- pycharter/data/templates/etl/extract_with_validation.yaml +86 -0
- pycharter/data/templates/etl/load_with_validation.yaml +111 -0
- pycharter/data/templates/etl/settings.yaml +55 -0
- pycharter/db/README.md +179 -0
- pycharter/db/cli.py +126 -4
- pycharter/db/migrations/versions/20260122000000_change_artifact_unique_constraints_to_title_version.py +2 -2
- pycharter/db/schemas/README.md +96 -0
- pycharter/etl_generator/ASYNC_AND_EXECUTION.md +91 -0
- pycharter/etl_generator/INTERFACES.md +142 -0
- pycharter/etl_generator/README.md +271 -0
- pycharter/etl_generator/TRANSFORMATION_GUIDE.md +452 -0
- pycharter/etl_generator/__init__.py +47 -11
- pycharter/etl_generator/config_models.py +673 -0
- pycharter/etl_generator/config_validator.py +133 -157
- pycharter/etl_generator/context.py +3 -0
- pycharter/etl_generator/database.py +5 -1
- pycharter/etl_generator/extractors/__init__.py +4 -2
- pycharter/etl_generator/extractors/cloud_storage.py +9 -9
- pycharter/etl_generator/extractors/database.py +2 -2
- pycharter/etl_generator/extractors/factory.py +15 -33
- pycharter/etl_generator/extractors/file.py +2 -2
- pycharter/etl_generator/extractors/http.py +2 -2
- pycharter/etl_generator/extractors/mongodb.py +393 -0
- pycharter/etl_generator/extractors/streaming.py +2 -2
- pycharter/etl_generator/loaders/__init__.py +15 -9
- pycharter/etl_generator/loaders/{cloud_storage_loader.py → cloud_storage.py} +95 -2
- pycharter/etl_generator/loaders/factory.py +16 -29
- pycharter/etl_generator/loaders/file.py +135 -1
- pycharter/etl_generator/loaders/mongodb.py +416 -0
- pycharter/etl_generator/pipeline.py +283 -164
- pycharter/etl_generator/result.py +16 -0
- pycharter/etl_generator/schemas/__init__.py +71 -42
- pycharter/etl_generator/transformers/config.py +3 -2
- pycharter/etl_generator/transformers/simple_operations.py +57 -4
- pycharter/etl_generator/validation.py +551 -0
- pycharter/metadata_store/README.md +229 -0
- pycharter/quality/README.md +235 -0
- pycharter/runtime_validator/__init__.py +7 -0
- pycharter/runtime_validator/utils.py +33 -0
- pycharter/runtime_validator/validator.py +13 -10
- pycharter/ui/.eslintrc.json +4 -0
- pycharter/ui/README.md +186 -0
- {ui → pycharter/ui}/__init__.py +3 -3
- pycharter/ui/components.json +17 -0
- pycharter/ui/package-lock.json +6617 -0
- pycharter/ui/package.json +37 -0
- {ui → pycharter/ui}/server.py +7 -8
- pycharter/ui/static/404/index.html +1 -0
- pycharter/ui/static/404.html +1 -0
- pycharter/ui/static/__next.__PAGE__.txt +10 -0
- pycharter/ui/static/__next._full.txt +30 -0
- pycharter/ui/static/__next._head.txt +7 -0
- pycharter/ui/static/__next._index.txt +9 -0
- pycharter/ui/static/__next._tree.txt +2 -0
- pycharter/ui/static/_next/static/YCnlK66gA7FV5vvcixspB/_clientMiddlewareManifest.json +1 -0
- pycharter/ui/static/_next/static/chunks/0fc1f70b787b8845.js +1 -0
- pycharter/ui/static/_next/static/chunks/17bb8075d7b75663.css +1 -0
- pycharter/ui/static/_next/static/chunks/381932864dcbfdb8.js +1 -0
- pycharter/ui/static/_next/static/chunks/4c951b8e4507e2b3.js +1 -0
- pycharter/ui/static/_next/static/chunks/68b87a6f65abd3ed.js +1 -0
- pycharter/ui/static/_next/static/chunks/78572617b8fae189.js +1 -0
- pycharter/ui/static/_next/static/chunks/8b7be2803e3fe184.js +1 -0
- pycharter/ui/static/_next/static/chunks/a8e529fd1e67f121.js +1 -0
- pycharter/ui/static/_next/static/chunks/c35d998f80be3ff5.js +1 -0
- pycharter/ui/static/_next/static/chunks/e453aa5d01c32c17.js +1 -0
- pycharter/ui/static/_next/static/chunks/f2d240eb057f898a.js +970 -0
- pycharter/ui/static/_next/static/chunks/f7722448f6040846.js +1 -0
- pycharter/ui/static/_not-found/__next._full.txt +17 -0
- pycharter/ui/static/_not-found/__next._head.txt +7 -0
- pycharter/ui/static/_not-found/__next._index.txt +9 -0
- pycharter/ui/static/_not-found/__next._not-found.__PAGE__.txt +5 -0
- pycharter/ui/static/_not-found/__next._not-found.txt +4 -0
- pycharter/ui/static/_not-found/__next._tree.txt +2 -0
- pycharter/ui/static/_not-found/index.html +1 -0
- pycharter/ui/static/_not-found/index.txt +17 -0
- pycharter/ui/static/contracts/__next._full.txt +21 -0
- pycharter/ui/static/contracts/__next._head.txt +7 -0
- pycharter/ui/static/contracts/__next._index.txt +9 -0
- pycharter/ui/static/contracts/__next._tree.txt +2 -0
- pycharter/ui/static/contracts/__next.contracts.__PAGE__.txt +9 -0
- pycharter/ui/static/contracts/__next.contracts.txt +4 -0
- pycharter/ui/static/contracts/index.html +1 -0
- pycharter/ui/static/contracts/index.txt +21 -0
- pycharter/ui/static/documentation/__next._full.txt +21 -0
- pycharter/ui/static/documentation/__next._head.txt +7 -0
- pycharter/ui/static/documentation/__next._index.txt +9 -0
- pycharter/ui/static/documentation/__next._tree.txt +2 -0
- pycharter/ui/static/documentation/__next.documentation.__PAGE__.txt +9 -0
- pycharter/ui/static/documentation/__next.documentation.txt +4 -0
- pycharter/ui/static/documentation/index.html +93 -0
- pycharter/ui/static/documentation/index.txt +21 -0
- pycharter/ui/static/etl/__next._full.txt +21 -0
- pycharter/ui/static/etl/__next._head.txt +7 -0
- pycharter/ui/static/etl/__next._index.txt +9 -0
- pycharter/ui/static/etl/__next._tree.txt +2 -0
- pycharter/ui/static/etl/__next.etl.__PAGE__.txt +9 -0
- pycharter/ui/static/etl/__next.etl.txt +4 -0
- pycharter/ui/static/etl/index.html +2 -0
- pycharter/ui/static/etl/index.txt +21 -0
- pycharter/ui/static/index.html +1 -0
- pycharter/ui/static/index.txt +30 -0
- pycharter/ui/static/metadata/__next._full.txt +21 -0
- pycharter/ui/static/metadata/__next._head.txt +7 -0
- pycharter/ui/static/metadata/__next._index.txt +9 -0
- pycharter/ui/static/metadata/__next._tree.txt +2 -0
- pycharter/ui/static/metadata/__next.metadata.__PAGE__.txt +9 -0
- pycharter/ui/static/metadata/__next.metadata.txt +4 -0
- pycharter/ui/static/metadata/index.html +1 -0
- pycharter/ui/static/metadata/index.txt +21 -0
- pycharter/ui/static/quality/__next._full.txt +21 -0
- pycharter/ui/static/quality/__next._head.txt +7 -0
- pycharter/ui/static/quality/__next._index.txt +9 -0
- pycharter/ui/static/quality/__next._tree.txt +2 -0
- pycharter/ui/static/quality/__next.quality.__PAGE__.txt +9 -0
- pycharter/ui/static/quality/__next.quality.txt +4 -0
- pycharter/ui/static/quality/index.html +2 -0
- pycharter/ui/static/quality/index.txt +21 -0
- pycharter/ui/static/rules/__next._full.txt +21 -0
- pycharter/ui/static/rules/__next._head.txt +7 -0
- pycharter/ui/static/rules/__next._index.txt +9 -0
- pycharter/ui/static/rules/__next._tree.txt +2 -0
- pycharter/ui/static/rules/__next.rules.__PAGE__.txt +9 -0
- pycharter/ui/static/rules/__next.rules.txt +4 -0
- pycharter/ui/static/rules/index.html +1 -0
- pycharter/ui/static/rules/index.txt +21 -0
- pycharter/ui/static/schemas/__next._full.txt +21 -0
- pycharter/ui/static/schemas/__next._head.txt +7 -0
- pycharter/ui/static/schemas/__next._index.txt +9 -0
- pycharter/ui/static/schemas/__next._tree.txt +2 -0
- pycharter/ui/static/schemas/__next.schemas.__PAGE__.txt +9 -0
- pycharter/ui/static/schemas/__next.schemas.txt +4 -0
- pycharter/ui/static/schemas/index.html +1 -0
- pycharter/ui/static/schemas/index.txt +21 -0
- pycharter/ui/static/settings/__next._full.txt +21 -0
- pycharter/ui/static/settings/__next._head.txt +7 -0
- pycharter/ui/static/settings/__next._index.txt +9 -0
- pycharter/ui/static/settings/__next._tree.txt +2 -0
- pycharter/ui/static/settings/__next.settings.__PAGE__.txt +9 -0
- pycharter/ui/static/settings/__next.settings.txt +4 -0
- pycharter/ui/static/settings/index.html +1 -0
- pycharter/ui/static/settings/index.txt +21 -0
- pycharter/ui/static/static/_next/static/2gKjNv6YvE6BcIdFthBLs/_clientMiddlewareManifest.json +1 -0
- pycharter/ui/static/static/static/_next/static/0rYA78L88aUyD2Uh38hhX/_clientMiddlewareManifest.json +1 -0
- pycharter/ui/static/static/static/_next/static/chunks/f7d1a90dd75d2572.js +1 -0
- pycharter/ui/static/static/static/static/.gitkeep +0 -0
- pycharter/ui/static/static/static/static/_next/static/chunks/222442f6da32302a.js +1 -0
- pycharter/ui/static/static/static/static/_next/static/chunks/247eb132b7f7b574.js +1 -0
- pycharter/ui/static/static/static/static/_next/static/chunks/297d55555b71baba.js +1 -0
- pycharter/ui/static/static/static/static/_next/static/chunks/414e77373f8ff61c.js +1 -0
- pycharter/ui/static/static/static/static/_next/static/chunks/652ad0aa26265c47.js +2 -0
- pycharter/ui/static/static/static/static/_next/static/chunks/9c23f44fff36548a.js +1 -0
- pycharter/ui/static/static/static/static/_next/static/chunks/a6dad97d9634a72d.js +1 -0
- pycharter/ui/static/static/static/static/_next/static/chunks/b32a0963684b9933.js +4 -0
- pycharter/ui/static/static/static/static/_next/static/chunks/db913959c675cea6.js +1 -0
- pycharter/ui/static/static/static/static/_next/static/chunks/f2e7afeab1178138.js +1 -0
- pycharter/ui/static/static/static/static/_next/static/chunks/ff1a16fafef87110.js +1 -0
- pycharter/ui/static/static/static/static/_next/static/chunks/turbopack-ffcb7ab6794027ef.js +3 -0
- pycharter/ui/static/static/static/static/_next/static/tNTkVW6puVXC4bAm4WrHl/_buildManifest.js +11 -0
- pycharter/ui/static/static/static/static/_next/static/tNTkVW6puVXC4bAm4WrHl/_clientMiddlewareManifest.json +1 -0
- pycharter/ui/static/static/static/static/_next/static/tNTkVW6puVXC4bAm4WrHl/_ssgManifest.js +1 -0
- pycharter/ui/static/validation/__next._full.txt +21 -0
- pycharter/ui/static/validation/__next._head.txt +7 -0
- pycharter/ui/static/validation/__next._index.txt +9 -0
- pycharter/ui/static/validation/__next._tree.txt +2 -0
- pycharter/ui/static/validation/__next.validation.__PAGE__.txt +9 -0
- pycharter/ui/static/validation/__next.validation.txt +4 -0
- pycharter/ui/static/validation/index.html +1 -0
- pycharter/ui/static/validation/index.txt +21 -0
- pycharter/ui/tsconfig.json +42 -0
- pycharter/worker/README.md +187 -0
- pycharter/worker/backends/__init__.py +8 -0
- pycharter/worker/backends/base.py +46 -0
- pycharter/worker/backends/spark.py +233 -0
- {worker → pycharter/worker}/cli.py +1 -1
- {worker → pycharter/worker}/processor.py +2 -2
- pycharter/worker/queue/__init__.py +8 -0
- pycharter/worker/queue/redis_queue.py +147 -0
- {pycharter-0.0.24.dist-info → pycharter-0.0.26.dist-info}/METADATA +57 -26
- pycharter-0.0.26.dist-info/RECORD +702 -0
- pycharter-0.0.26.dist-info/top_level.txt +1 -0
- pycharter/etl_generator/config_loader.py +0 -394
- pycharter/etl_generator/loaders/cloud.py +0 -87
- pycharter/etl_generator/loaders/file_loader.py +0 -130
- pycharter-0.0.24.dist-info/RECORD +0 -543
- pycharter-0.0.24.dist-info/top_level.txt +0 -4
- {api → pycharter/api}/dependencies/database.py +0 -0
- {api → pycharter/api}/dependencies/store.py +0 -0
- {api → pycharter/api}/models/contracts.py +0 -0
- {api → pycharter/api}/models/docs.py +0 -0
- {api → pycharter/api}/models/evolution.py +0 -0
- {api → pycharter/api}/models/metadata.py +0 -0
- {api → pycharter/api}/models/metadata_entities.py +0 -0
- {api → pycharter/api}/models/quality.py +0 -0
- {api → pycharter/api}/models/schemas.py +0 -0
- {api → pycharter/api}/models/tracking.py +0 -0
- {api → pycharter/api}/models/validation.py +0 -0
- {api → pycharter/api}/routes/__init__.py +0 -0
- {api → pycharter/api}/routes/v1/templates.py +0 -0
- {api → pycharter/api}/utils.py +0 -0
- {ui → pycharter/ui}/build.py +0 -0
- {ui → pycharter/ui}/dev.py +0 -0
- {ui → pycharter/ui}/static/.gitkeep +0 -0
- {ui/static/_next/static/2gKjNv6YvE6BcIdFthBLs → pycharter/ui/static/_next/static/YCnlK66gA7FV5vvcixspB}/_buildManifest.js +0 -0
- {ui/static/_next/static/2gKjNv6YvE6BcIdFthBLs → pycharter/ui/static/_next/static/YCnlK66gA7FV5vvcixspB}/_ssgManifest.js +0 -0
- {ui → pycharter/ui}/static/_next/static/chunks/222442f6da32302a.js +0 -0
- {ui → pycharter/ui}/static/_next/static/chunks/247eb132b7f7b574.js +0 -0
- {ui → pycharter/ui}/static/_next/static/chunks/297d55555b71baba.js +0 -0
- {ui → pycharter/ui}/static/_next/static/chunks/414e77373f8ff61c.js +0 -0
- {ui → pycharter/ui}/static/_next/static/chunks/652ad0aa26265c47.js +0 -0
- {ui → pycharter/ui}/static/_next/static/chunks/9c23f44fff36548a.js +0 -0
- {ui → pycharter/ui}/static/_next/static/chunks/a6dad97d9634a72d.js +0 -0
- {ui → pycharter/ui}/static/_next/static/chunks/b32a0963684b9933.js +0 -0
- {ui → pycharter/ui}/static/_next/static/chunks/db913959c675cea6.js +0 -0
- {ui → pycharter/ui}/static/_next/static/chunks/f2e7afeab1178138.js +0 -0
- {ui → pycharter/ui}/static/_next/static/chunks/f7d1a90dd75d2572.js +0 -0
- {ui → pycharter/ui}/static/_next/static/chunks/ff1a16fafef87110.js +0 -0
- {ui → pycharter/ui}/static/_next/static/chunks/turbopack-ffcb7ab6794027ef.js +0 -0
- {ui → pycharter/ui}/static/static/.gitkeep +0 -0
- {ui → pycharter/ui/static}/static/404/index.html +0 -0
- {ui → pycharter/ui/static}/static/404.html +0 -0
- {ui → pycharter/ui/static}/static/__next.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/__next._tree.txt +0 -0
- {ui/static/static/_next/static/0rYA78L88aUyD2Uh38hhX → pycharter/ui/static/static/_next/static/2gKjNv6YvE6BcIdFthBLs}/_buildManifest.js +0 -0
- {ui/static/static/_next/static/0rYA78L88aUyD2Uh38hhX → pycharter/ui/static/static/_next/static/2gKjNv6YvE6BcIdFthBLs}/_ssgManifest.js +0 -0
- {ui → pycharter/ui/static}/static/_next/static/chunks/13d4a0fbd74c1ee4.js +0 -0
- {ui → pycharter/ui}/static/static/_next/static/chunks/222442f6da32302a.js +0 -0
- {ui → pycharter/ui}/static/static/_next/static/chunks/247eb132b7f7b574.js +0 -0
- {ui → pycharter/ui/static}/static/_next/static/chunks/26dfc590f7714c03.js +0 -0
- {ui → pycharter/ui}/static/static/_next/static/chunks/297d55555b71baba.js +0 -0
- {ui → pycharter/ui/static}/static/_next/static/chunks/2ab439ce003cd691.js +0 -0
- {ui → pycharter/ui/static}/static/_next/static/chunks/2edb43b48432ac04.js +0 -0
- {ui → pycharter/ui/static}/static/_next/static/chunks/34d289e6db2ef551.js +0 -0
- {ui → pycharter/ui}/static/static/_next/static/chunks/414e77373f8ff61c.js +0 -0
- {ui → pycharter/ui/static}/static/_next/static/chunks/49ca65abd26ae49e.js +0 -0
- {ui → pycharter/ui}/static/static/_next/static/chunks/652ad0aa26265c47.js +0 -0
- {ui → pycharter/ui/static}/static/_next/static/chunks/9667e7a3d359eb39.js +0 -0
- {ui → pycharter/ui/static}/static/_next/static/chunks/99508d9d5869cc27.js +0 -0
- {ui → pycharter/ui}/static/static/_next/static/chunks/9c23f44fff36548a.js +0 -0
- {ui → pycharter/ui}/static/static/_next/static/chunks/a6dad97d9634a72d.js +0 -0
- {ui → pycharter/ui/static}/static/_next/static/chunks/b313c35a6ba76574.js +0 -0
- {ui → pycharter/ui}/static/static/_next/static/chunks/b32a0963684b9933.js +0 -0
- {ui → pycharter/ui/static}/static/_next/static/chunks/c69f6cba366bd988.js +0 -0
- {ui → pycharter/ui/static}/static/_next/static/chunks/d2363397e1b2bcab.css +0 -0
- {ui → pycharter/ui}/static/static/_next/static/chunks/db913959c675cea6.js +0 -0
- {ui → pycharter/ui/static}/static/_next/static/chunks/f061a4be97bfc3b3.js +0 -0
- {ui → pycharter/ui}/static/static/_next/static/chunks/f2e7afeab1178138.js +0 -0
- {ui → pycharter/ui}/static/static/_next/static/chunks/f7d1a90dd75d2572.js +0 -0
- {ui → pycharter/ui}/static/static/_next/static/chunks/ff1a16fafef87110.js +0 -0
- {ui → pycharter/ui}/static/static/_next/static/chunks/turbopack-ffcb7ab6794027ef.js +0 -0
- {ui → pycharter/ui/static}/static/_not-found/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/_not-found/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/_not-found/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/_not-found/__next._not-found.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/_not-found/__next._not-found.txt +0 -0
- {ui → pycharter/ui/static}/static/_not-found/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/_not-found/index.html +0 -0
- {ui → pycharter/ui/static}/static/_not-found/index.txt +0 -0
- {ui → pycharter/ui/static}/static/contracts/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/contracts/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/contracts/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/contracts/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/contracts/__next.contracts.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/contracts/__next.contracts.txt +0 -0
- {ui → pycharter/ui/static}/static/contracts/index.html +0 -0
- {ui → pycharter/ui/static}/static/contracts/index.txt +0 -0
- {ui → pycharter/ui/static}/static/documentation/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/documentation/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/documentation/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/documentation/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/documentation/__next.documentation.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/documentation/__next.documentation.txt +0 -0
- {ui → pycharter/ui/static}/static/documentation/index.html +0 -0
- {ui → pycharter/ui/static}/static/documentation/index.txt +0 -0
- {ui → pycharter/ui/static}/static/index.html +0 -0
- {ui → pycharter/ui/static}/static/index.txt +0 -0
- {ui → pycharter/ui/static}/static/metadata/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/metadata/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/metadata/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/metadata/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/metadata/__next.metadata.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/metadata/__next.metadata.txt +0 -0
- {ui → pycharter/ui/static}/static/metadata/index.html +0 -0
- {ui → pycharter/ui/static}/static/metadata/index.txt +0 -0
- {ui → pycharter/ui/static}/static/quality/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/quality/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/quality/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/quality/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/quality/__next.quality.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/quality/__next.quality.txt +0 -0
- {ui → pycharter/ui/static}/static/quality/index.html +0 -0
- {ui → pycharter/ui/static}/static/quality/index.txt +0 -0
- {ui → pycharter/ui/static}/static/rules/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/rules/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/rules/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/rules/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/rules/__next.rules.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/rules/__next.rules.txt +0 -0
- {ui → pycharter/ui/static}/static/rules/index.html +0 -0
- {ui → pycharter/ui/static}/static/rules/index.txt +0 -0
- {ui → pycharter/ui/static}/static/schemas/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/schemas/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/schemas/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/schemas/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/schemas/__next.schemas.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/schemas/__next.schemas.txt +0 -0
- {ui → pycharter/ui/static}/static/schemas/index.html +0 -0
- {ui → pycharter/ui/static}/static/schemas/index.txt +0 -0
- {ui → pycharter/ui/static}/static/settings/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/settings/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/settings/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/settings/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/settings/__next.settings.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/settings/__next.settings.txt +0 -0
- {ui → pycharter/ui/static}/static/settings/index.html +0 -0
- {ui → pycharter/ui/static}/static/settings/index.txt +0 -0
- {ui → pycharter/ui}/static/static/static/.gitkeep +0 -0
- {ui → pycharter/ui/static}/static/static/404/index.html +0 -0
- {ui → pycharter/ui/static}/static/static/404.html +0 -0
- {ui → pycharter/ui/static}/static/static/__next.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/static/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/static/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/static/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/__next._tree.txt +0 -0
- {ui/static/static/static/_next/static/tNTkVW6puVXC4bAm4WrHl → pycharter/ui/static/static/static/_next/static/0rYA78L88aUyD2Uh38hhX}/_buildManifest.js +0 -0
- {ui/static/static/static/_next/static/tNTkVW6puVXC4bAm4WrHl → pycharter/ui/static/static/static/_next/static/0rYA78L88aUyD2Uh38hhX}/_ssgManifest.js +0 -0
- {ui → pycharter/ui/static}/static/static/_next/static/chunks/13d4a0fbd74c1ee4.js +0 -0
- {ui → pycharter/ui}/static/static/static/_next/static/chunks/222442f6da32302a.js +0 -0
- {ui → pycharter/ui}/static/static/static/_next/static/chunks/247eb132b7f7b574.js +0 -0
- {ui → pycharter/ui}/static/static/static/_next/static/chunks/297d55555b71baba.js +0 -0
- {ui → pycharter/ui/static}/static/static/_next/static/chunks/2ab439ce003cd691.js +0 -0
- {ui → pycharter/ui/static}/static/static/_next/static/chunks/2edb43b48432ac04.js +0 -0
- {ui → pycharter/ui}/static/static/static/_next/static/chunks/414e77373f8ff61c.js +0 -0
- {ui → pycharter/ui/static}/static/static/_next/static/chunks/49ca65abd26ae49e.js +0 -0
- {ui → pycharter/ui/static}/static/static/_next/static/chunks/5e04d10c4a7b58a3.js +0 -0
- {ui → pycharter/ui}/static/static/static/_next/static/chunks/652ad0aa26265c47.js +0 -0
- {ui → pycharter/ui/static}/static/static/_next/static/chunks/75d88a058d8ffaa6.js +0 -0
- {ui → pycharter/ui/static}/static/static/_next/static/chunks/8c89634cf6bad76f.js +0 -0
- {ui → pycharter/ui/static}/static/static/_next/static/chunks/9667e7a3d359eb39.js +0 -0
- {ui → pycharter/ui}/static/static/static/_next/static/chunks/9c23f44fff36548a.js +0 -0
- {ui → pycharter/ui}/static/static/static/_next/static/chunks/a6dad97d9634a72d.js +0 -0
- {ui → pycharter/ui}/static/static/static/_next/static/chunks/b32a0963684b9933.js +0 -0
- {ui → pycharter/ui/static}/static/static/_next/static/chunks/c4fa4f4114b7c352.js +0 -0
- {ui → pycharter/ui/static}/static/static/_next/static/chunks/c69f6cba366bd988.js +0 -0
- {ui → pycharter/ui/static}/static/static/_next/static/chunks/d2363397e1b2bcab.css +0 -0
- {ui → pycharter/ui}/static/static/static/_next/static/chunks/db913959c675cea6.js +0 -0
- {ui → pycharter/ui/static}/static/static/_next/static/chunks/f061a4be97bfc3b3.js +0 -0
- {ui → pycharter/ui}/static/static/static/_next/static/chunks/f2e7afeab1178138.js +0 -0
- {ui → pycharter/ui}/static/static/static/_next/static/chunks/ff1a16fafef87110.js +0 -0
- {ui → pycharter/ui}/static/static/static/_next/static/chunks/turbopack-ffcb7ab6794027ef.js +0 -0
- {ui → pycharter/ui/static}/static/static/_not-found/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/static/_not-found/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/static/_not-found/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/_not-found/__next._not-found.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/static/_not-found/__next._not-found.txt +0 -0
- {ui → pycharter/ui/static}/static/static/_not-found/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/static/_not-found/index.html +0 -0
- {ui → pycharter/ui/static}/static/static/_not-found/index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/contracts/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/static/contracts/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/static/contracts/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/contracts/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/static/contracts/__next.contracts.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/static/contracts/__next.contracts.txt +0 -0
- {ui → pycharter/ui/static}/static/static/contracts/index.html +0 -0
- {ui → pycharter/ui/static}/static/static/contracts/index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/documentation/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/static/documentation/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/static/documentation/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/documentation/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/static/documentation/__next.documentation.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/static/documentation/__next.documentation.txt +0 -0
- {ui → pycharter/ui/static}/static/static/documentation/index.html +0 -0
- {ui → pycharter/ui/static}/static/static/documentation/index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/index.html +0 -0
- {ui → pycharter/ui/static}/static/static/index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/metadata/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/static/metadata/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/static/metadata/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/metadata/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/static/metadata/__next.metadata.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/static/metadata/__next.metadata.txt +0 -0
- {ui → pycharter/ui/static}/static/static/metadata/index.html +0 -0
- {ui → pycharter/ui/static}/static/static/metadata/index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/quality/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/static/quality/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/static/quality/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/quality/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/static/quality/__next.quality.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/static/quality/__next.quality.txt +0 -0
- {ui → pycharter/ui/static}/static/static/quality/index.html +0 -0
- {ui → pycharter/ui/static}/static/static/quality/index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/rules/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/static/rules/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/static/rules/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/rules/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/static/rules/__next.rules.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/static/rules/__next.rules.txt +0 -0
- {ui → pycharter/ui/static}/static/static/rules/index.html +0 -0
- {ui → pycharter/ui/static}/static/static/rules/index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/schemas/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/static/schemas/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/static/schemas/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/schemas/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/static/schemas/__next.schemas.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/static/schemas/__next.schemas.txt +0 -0
- {ui → pycharter/ui/static}/static/static/schemas/index.html +0 -0
- {ui → pycharter/ui/static}/static/static/schemas/index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/settings/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/static/settings/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/static/settings/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/settings/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/static/settings/__next.settings.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/static/settings/__next.settings.txt +0 -0
- {ui → pycharter/ui/static}/static/static/settings/index.html +0 -0
- {ui → pycharter/ui/static}/static/static/settings/index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/404/index.html +0 -0
- {ui → pycharter/ui/static}/static/static/static/404.html +0 -0
- {ui → pycharter/ui/static}/static/static/static/__next.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/2ab439ce003cd691.js +0 -0
- {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/49ca65abd26ae49e.js +0 -0
- {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/4e310fe5005770a3.css +0 -0
- {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/5e04d10c4a7b58a3.js +0 -0
- {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/5fc14c00a2779dc5.js +0 -0
- {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/75d88a058d8ffaa6.js +0 -0
- {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/8c89634cf6bad76f.js +0 -0
- {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/9667e7a3d359eb39.js +0 -0
- {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/b584574fdc8ab13e.js +0 -0
- {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/c69f6cba366bd988.js +0 -0
- {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/d5989c94d3614b3a.js +0 -0
- {ui → pycharter/ui/static}/static/static/static/_next/static/chunks/f061a4be97bfc3b3.js +0 -0
- {ui → pycharter/ui/static}/static/static/static/_not-found/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/_not-found/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/_not-found/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/_not-found/__next._not-found.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/_not-found/__next._not-found.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/_not-found/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/_not-found/index.html +0 -0
- {ui → pycharter/ui/static}/static/static/static/_not-found/index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/contracts/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/contracts/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/contracts/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/contracts/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/contracts/__next.contracts.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/contracts/__next.contracts.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/contracts/index.html +0 -0
- {ui → pycharter/ui/static}/static/static/static/contracts/index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/documentation/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/documentation/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/documentation/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/documentation/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/documentation/__next.documentation.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/documentation/__next.documentation.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/documentation/index.html +0 -0
- {ui → pycharter/ui/static}/static/static/static/documentation/index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/index.html +0 -0
- {ui → pycharter/ui/static}/static/static/static/index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/metadata/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/metadata/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/metadata/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/metadata/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/metadata/__next.metadata.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/metadata/__next.metadata.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/metadata/index.html +0 -0
- {ui → pycharter/ui/static}/static/static/static/metadata/index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/quality/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/quality/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/quality/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/quality/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/quality/__next.quality.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/quality/__next.quality.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/quality/index.html +0 -0
- {ui → pycharter/ui/static}/static/static/static/quality/index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/rules/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/rules/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/rules/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/rules/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/rules/__next.rules.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/rules/__next.rules.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/rules/index.html +0 -0
- {ui → pycharter/ui/static}/static/static/static/rules/index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/schemas/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/schemas/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/schemas/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/schemas/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/schemas/__next.schemas.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/schemas/__next.schemas.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/schemas/index.html +0 -0
- {ui → pycharter/ui/static}/static/static/static/schemas/index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/settings/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/settings/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/settings/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/settings/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/settings/__next.settings.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/settings/__next.settings.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/settings/index.html +0 -0
- {ui → pycharter/ui/static}/static/static/static/settings/index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/validation/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/validation/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/validation/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/validation/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/validation/__next.validation.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/validation/__next.validation.txt +0 -0
- {ui → pycharter/ui/static}/static/static/static/validation/index.html +0 -0
- {ui → pycharter/ui/static}/static/static/static/validation/index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/validation/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/static/validation/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/static/validation/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/static/validation/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/static/validation/__next.validation.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/static/validation/__next.validation.txt +0 -0
- {ui → pycharter/ui/static}/static/static/validation/index.html +0 -0
- {ui → pycharter/ui/static}/static/static/validation/index.txt +0 -0
- {ui → pycharter/ui/static}/static/validation/__next._full.txt +0 -0
- {ui → pycharter/ui/static}/static/validation/__next._head.txt +0 -0
- {ui → pycharter/ui/static}/static/validation/__next._index.txt +0 -0
- {ui → pycharter/ui/static}/static/validation/__next._tree.txt +0 -0
- {ui → pycharter/ui/static}/static/validation/__next.validation.__PAGE__.txt +0 -0
- {ui → pycharter/ui/static}/static/validation/__next.validation.txt +0 -0
- {ui → pycharter/ui/static}/static/validation/index.html +0 -0
- {ui → pycharter/ui/static}/static/validation/index.txt +0 -0
- {worker → pycharter/worker}/__init__.py +0 -0
- {worker → pycharter/worker}/models.py +0 -0
- {pycharter-0.0.24.dist-info → pycharter-0.0.26.dist-info}/WHEEL +0 -0
- {pycharter-0.0.24.dist-info → pycharter-0.0.26.dist-info}/entry_points.txt +0 -0
- {pycharter-0.0.24.dist-info → pycharter-0.0.26.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# Metadata Store Implementations
|
|
2
|
+
|
|
3
|
+
PyCharter provides multiple metadata store implementations to suit different use cases:
|
|
4
|
+
|
|
5
|
+
## Available Implementations
|
|
6
|
+
|
|
7
|
+
### 1. InMemoryMetadataStore
|
|
8
|
+
**Use case**: Testing, development, prototyping
|
|
9
|
+
|
|
10
|
+
**Dependencies**: None (built-in)
|
|
11
|
+
|
|
12
|
+
**Example**:
|
|
13
|
+
```python
|
|
14
|
+
from pycharter import InMemoryMetadataStore
|
|
15
|
+
|
|
16
|
+
store = InMemoryMetadataStore()
|
|
17
|
+
store.connect()
|
|
18
|
+
|
|
19
|
+
schema_id = store.store_schema("user", {"type": "object"}, version="1.0")
|
|
20
|
+
schema = store.get_schema(schema_id)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
### 2. MongoDBMetadataStore
|
|
26
|
+
**Use case**: Document-based storage, flexible schema evolution
|
|
27
|
+
|
|
28
|
+
**Dependencies**: `pymongo`
|
|
29
|
+
```bash
|
|
30
|
+
pip install pymongo
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Connection string format**: `mongodb://[username:password@]host[:port][/database]`
|
|
34
|
+
|
|
35
|
+
**Example**:
|
|
36
|
+
```python
|
|
37
|
+
from pycharter import MongoDBMetadataStore
|
|
38
|
+
|
|
39
|
+
store = MongoDBMetadataStore(
|
|
40
|
+
connection_string="mongodb://localhost:27017/pycharter",
|
|
41
|
+
database_name="pycharter"
|
|
42
|
+
)
|
|
43
|
+
store.connect()
|
|
44
|
+
|
|
45
|
+
schema_id = store.store_schema("user", {"type": "object"}, version="1.0")
|
|
46
|
+
schema = store.get_schema(schema_id)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
### 3. PostgresMetadataStore
|
|
52
|
+
**Use case**: Relational data, ACID transactions, complex queries
|
|
53
|
+
|
|
54
|
+
**Dependencies**: `psycopg2-binary`
|
|
55
|
+
```bash
|
|
56
|
+
pip install psycopg2-binary
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Connection string format**: `postgresql://[user[:password]@][host][:port][/database]`
|
|
60
|
+
|
|
61
|
+
**Example**:
|
|
62
|
+
```python
|
|
63
|
+
from pycharter import PostgresMetadataStore
|
|
64
|
+
|
|
65
|
+
store = PostgresMetadataStore(
|
|
66
|
+
connection_string="postgresql://user:password@localhost/pycharter"
|
|
67
|
+
)
|
|
68
|
+
store.connect()
|
|
69
|
+
|
|
70
|
+
schema_id = store.store_schema("user", {"type": "object"}, version="1.0")
|
|
71
|
+
schema = store.get_schema(schema_id)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Schema Management**:
|
|
75
|
+
- Schema is automatically initialized and validated on `connect()`
|
|
76
|
+
- Version tracking ensures schema compatibility
|
|
77
|
+
- Use `store.get_schema_info()` to check schema status
|
|
78
|
+
- See [SCHEMA_MANAGEMENT.md](SCHEMA_MANAGEMENT.md) for details
|
|
79
|
+
|
|
80
|
+
**CLI Tools**:
|
|
81
|
+
```bash
|
|
82
|
+
# Initialize schema manually
|
|
83
|
+
pycharter db init postgresql://user:pass@localhost/pycharter
|
|
84
|
+
|
|
85
|
+
# Upgrade to latest version
|
|
86
|
+
pycharter db upgrade postgresql://user:pass@localhost/pycharter
|
|
87
|
+
|
|
88
|
+
# Check current revision
|
|
89
|
+
pycharter db current postgresql://user:pass@localhost/pycharter
|
|
90
|
+
|
|
91
|
+
# See migration history
|
|
92
|
+
pycharter db history
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
### 4. SQLiteMetadataStore
|
|
98
|
+
**Use case**: Development, testing, small projects, embedded applications
|
|
99
|
+
|
|
100
|
+
**Dependencies**: None (sqlite3 is built into Python)
|
|
101
|
+
|
|
102
|
+
**Connection string format**: `sqlite:///path/to/database.db` or `sqlite:///:memory:`
|
|
103
|
+
|
|
104
|
+
**Example**:
|
|
105
|
+
```python
|
|
106
|
+
from pycharter import SQLiteMetadataStore
|
|
107
|
+
|
|
108
|
+
# File-based database
|
|
109
|
+
store = SQLiteMetadataStore("sqlite:///pycharter.db")
|
|
110
|
+
store.connect()
|
|
111
|
+
|
|
112
|
+
# In-memory database (for testing)
|
|
113
|
+
store = SQLiteMetadataStore("sqlite:///:memory:")
|
|
114
|
+
store.connect()
|
|
115
|
+
|
|
116
|
+
schema_id = store.store_schema("user", {"type": "object"}, version="1.0")
|
|
117
|
+
schema = store.get_schema(schema_id)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Schema Management**:
|
|
121
|
+
- Schema is automatically initialized and validated on `connect()`
|
|
122
|
+
- Uses SQLAlchemy models (same as PostgreSQL)
|
|
123
|
+
- Supports Alembic migrations
|
|
124
|
+
- Use `store.get_schema_info()` to check schema status
|
|
125
|
+
|
|
126
|
+
**CLI Tools**:
|
|
127
|
+
```bash
|
|
128
|
+
# Initialize schema manually
|
|
129
|
+
pycharter db init sqlite:///pycharter.db
|
|
130
|
+
|
|
131
|
+
# Run migrations
|
|
132
|
+
pycharter db upgrade sqlite:///pycharter.db
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Notes**:
|
|
136
|
+
- SQLite databases are file-based - easy to backup, share, and version control
|
|
137
|
+
- Perfect for development and testing (no server setup required)
|
|
138
|
+
- Good for small to medium projects
|
|
139
|
+
- Limited concurrent writes (fine for read-heavy workloads)
|
|
140
|
+
- Single-machine only (no network access)
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
### 5. RedisMetadataStore
|
|
145
|
+
**Use case**: High-performance caching, fast lookups, temporary storage
|
|
146
|
+
|
|
147
|
+
**Dependencies**: `redis`
|
|
148
|
+
```bash
|
|
149
|
+
pip install redis
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**Connection string format**: `redis://[password@]host[:port][/database]`
|
|
153
|
+
|
|
154
|
+
**Example**:
|
|
155
|
+
```python
|
|
156
|
+
from pycharter import RedisMetadataStore
|
|
157
|
+
|
|
158
|
+
store = RedisMetadataStore(
|
|
159
|
+
connection_string="redis://localhost:6379/0",
|
|
160
|
+
key_prefix="pycharter"
|
|
161
|
+
)
|
|
162
|
+
store.connect()
|
|
163
|
+
|
|
164
|
+
schema_id = store.store_schema("user", {"type": "object"}, version="1.0")
|
|
165
|
+
schema = store.get_schema(schema_id)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Common Usage Pattern
|
|
171
|
+
|
|
172
|
+
All implementations follow the same interface:
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
from pycharter import InMemoryMetadataStore # or any other implementation
|
|
176
|
+
|
|
177
|
+
# Initialize and connect
|
|
178
|
+
store = InMemoryMetadataStore()
|
|
179
|
+
store.connect()
|
|
180
|
+
|
|
181
|
+
# Store schema
|
|
182
|
+
schema_id = store.store_schema(
|
|
183
|
+
schema_name="user",
|
|
184
|
+
schema={"type": "object", "properties": {"name": {"type": "string"}}},
|
|
185
|
+
version="1.0"
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
# Store ownership and governance rules via metadata
|
|
189
|
+
metadata = {
|
|
190
|
+
"title": "User Schema",
|
|
191
|
+
"business_owners": ["data-team@example.com"],
|
|
192
|
+
"governance_rules": {
|
|
193
|
+
"pii_encryption": {"type": "encrypt", "fields": ["email"]}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
store.store_metadata(schema_id, metadata, "schema")
|
|
197
|
+
|
|
198
|
+
# Retrieve data
|
|
199
|
+
schema = store.get_schema(schema_id)
|
|
200
|
+
retrieved_metadata = store.get_metadata(schema_id, "schema")
|
|
201
|
+
ownership = retrieved_metadata.get("business_owners") if retrieved_metadata else None
|
|
202
|
+
rules = retrieved_metadata.get("governance_rules") if retrieved_metadata else None
|
|
203
|
+
|
|
204
|
+
# List all schemas
|
|
205
|
+
all_schemas = store.list_schemas()
|
|
206
|
+
|
|
207
|
+
# Disconnect
|
|
208
|
+
store.disconnect()
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Context Manager Usage
|
|
212
|
+
|
|
213
|
+
All stores support context manager syntax:
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
with InMemoryMetadataStore() as store:
|
|
217
|
+
schema_id = store.store_schema("user", {"type": "object"})
|
|
218
|
+
schema = store.get_schema(schema_id)
|
|
219
|
+
# Automatically disconnects on exit
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Choosing the Right Store
|
|
223
|
+
|
|
224
|
+
- **InMemoryMetadataStore**: Testing, development, demos (zero dependencies, no persistence)
|
|
225
|
+
- **SQLiteMetadataStore**: Development, testing, small projects (file-based, no server needed)
|
|
226
|
+
- **MongoDBMetadataStore**: Flexible document storage, schema evolution
|
|
227
|
+
- **PostgresMetadataStore**: Production systems, complex queries, ACID guarantees
|
|
228
|
+
- **RedisMetadataStore**: High-performance caching, temporary storage, fast lookups
|
|
229
|
+
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
# Quality Assurance Module
|
|
2
|
+
|
|
3
|
+
The Quality Assurance module provides comprehensive data quality checking, metrics calculation, violation tracking, and reporting capabilities for PyCharter.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The quality module enables you to:
|
|
8
|
+
- **Run quality checks** against data contracts
|
|
9
|
+
- **Calculate quality metrics** (scores, accuracy, completeness, violation rates)
|
|
10
|
+
- **Track violations** for audit and remediation
|
|
11
|
+
- **Check thresholds** and get alerts when quality degrades
|
|
12
|
+
- **Generate reports** with detailed quality insights
|
|
13
|
+
|
|
14
|
+
## Core Components
|
|
15
|
+
|
|
16
|
+
### QualityCheck
|
|
17
|
+
|
|
18
|
+
The main class for running quality checks. It's orchestrator-agnostic and can be used:
|
|
19
|
+
- Standalone (CLI, API, Python scripts)
|
|
20
|
+
- Within orchestrators (Airflow, Prefect, Dagster)
|
|
21
|
+
- Via API calls
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
from pycharter import QualityCheck, QualityCheckOptions
|
|
25
|
+
|
|
26
|
+
# Create quality check instance
|
|
27
|
+
check = QualityCheck(store=store) # Optional: pass metadata store
|
|
28
|
+
|
|
29
|
+
# Run quality check
|
|
30
|
+
report = check.run(
|
|
31
|
+
schema_id="user_schema_v1", # Or use contract=...
|
|
32
|
+
data="data/users.json", # File path, list, or callable
|
|
33
|
+
options=QualityCheckOptions(
|
|
34
|
+
record_violations=True,
|
|
35
|
+
calculate_metrics=True,
|
|
36
|
+
check_thresholds=True,
|
|
37
|
+
)
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
print(f"Quality Score: {report.quality_score.overall_score:.2f}/100")
|
|
41
|
+
print(f"Passed: {report.passed}")
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### QualityMetrics
|
|
45
|
+
|
|
46
|
+
Calculates quality scores and metrics from validation results:
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
from pycharter.quality import QualityMetrics
|
|
50
|
+
|
|
51
|
+
metrics = QualityMetrics()
|
|
52
|
+
quality_score = metrics.calculate_quality_score(validation_results)
|
|
53
|
+
|
|
54
|
+
print(f"Overall Score: {quality_score.overall_score}")
|
|
55
|
+
print(f"Accuracy: {quality_score.accuracy:.2%}")
|
|
56
|
+
print(f"Completeness: {quality_score.completeness:.2%}")
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### ViolationTracker
|
|
60
|
+
|
|
61
|
+
Tracks and manages data quality violations:
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
from pycharter.quality import ViolationTracker
|
|
65
|
+
|
|
66
|
+
tracker = ViolationTracker(store=store)
|
|
67
|
+
violation = tracker.record_violation(
|
|
68
|
+
schema_id="user_schema_v1",
|
|
69
|
+
record_id="user_123",
|
|
70
|
+
record_data={"name": "Alice", "age": "invalid"},
|
|
71
|
+
validation_result=result,
|
|
72
|
+
severity="warning"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
# Query violations
|
|
76
|
+
violations = tracker.get_violations(
|
|
77
|
+
schema_id="user_schema_v1",
|
|
78
|
+
status="open"
|
|
79
|
+
)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Usage Examples
|
|
83
|
+
|
|
84
|
+
### Standalone Quality Check
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
from pycharter import QualityCheck, QualityCheckOptions, QualityThresholds
|
|
88
|
+
|
|
89
|
+
# Define thresholds
|
|
90
|
+
thresholds = QualityThresholds(
|
|
91
|
+
min_overall_score=95.0,
|
|
92
|
+
max_violation_rate=0.05,
|
|
93
|
+
min_accuracy=0.95
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# Run check
|
|
97
|
+
check = QualityCheck()
|
|
98
|
+
report = check.run(
|
|
99
|
+
contract="contracts/user_contract.yaml",
|
|
100
|
+
data="data/users.json",
|
|
101
|
+
options=QualityCheckOptions(
|
|
102
|
+
check_thresholds=True,
|
|
103
|
+
thresholds=thresholds
|
|
104
|
+
)
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
if not report.passed:
|
|
108
|
+
print("⚠ Quality check failed!")
|
|
109
|
+
for breach in report.threshold_breaches:
|
|
110
|
+
print(f" - {breach}")
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### CLI Usage
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# Run quality check
|
|
117
|
+
pycharter quality check \
|
|
118
|
+
--schema-id user_schema_v1 \
|
|
119
|
+
--data data/users.json \
|
|
120
|
+
--database-url postgresql://user:pass@localhost/db \
|
|
121
|
+
--check-thresholds \
|
|
122
|
+
--output quality_report.json
|
|
123
|
+
|
|
124
|
+
# Query violations
|
|
125
|
+
pycharter quality violations \
|
|
126
|
+
--schema-id user_schema_v1 \
|
|
127
|
+
--status open \
|
|
128
|
+
--output violations.json
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### API Usage
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
# Run quality check via API
|
|
135
|
+
curl -X POST http://localhost:8000/api/v1/quality/check \
|
|
136
|
+
-H "Content-Type: application/json" \
|
|
137
|
+
-d '{
|
|
138
|
+
"schema_id": "user_schema_v1",
|
|
139
|
+
"data": [{"name": "Alice", "age": 30}],
|
|
140
|
+
"calculate_metrics": true,
|
|
141
|
+
"record_violations": true
|
|
142
|
+
}'
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Quality Metrics
|
|
146
|
+
|
|
147
|
+
The quality module calculates several metrics:
|
|
148
|
+
|
|
149
|
+
- **Overall Score** (0-100): Weighted combination of accuracy and completeness
|
|
150
|
+
- **Accuracy** (0-1): Percentage of records that pass validation
|
|
151
|
+
- **Completeness** (0-1): Percentage of required fields present
|
|
152
|
+
- **Violation Rate** (0-1): Percentage of records with violations
|
|
153
|
+
- **Field Scores**: Per-field quality scores
|
|
154
|
+
|
|
155
|
+
## Thresholds and Alerting
|
|
156
|
+
|
|
157
|
+
Define quality thresholds to get alerts when quality degrades:
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
thresholds = QualityThresholds(
|
|
161
|
+
min_overall_score=95.0,
|
|
162
|
+
max_violation_rate=0.05,
|
|
163
|
+
min_completeness=0.95,
|
|
164
|
+
min_accuracy=0.95,
|
|
165
|
+
field_thresholds={
|
|
166
|
+
"email": {"min_score": 98.0},
|
|
167
|
+
"phone": {"min_score": 90.0}
|
|
168
|
+
}
|
|
169
|
+
)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Integration with Orchestrators
|
|
173
|
+
|
|
174
|
+
The quality module works seamlessly with orchestrators:
|
|
175
|
+
|
|
176
|
+
### Airflow
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
from airflow import DAG
|
|
180
|
+
from airflow.operators.python import PythonOperator
|
|
181
|
+
from pycharter import QualityCheck
|
|
182
|
+
|
|
183
|
+
def quality_check_task():
|
|
184
|
+
check = QualityCheck(store=store)
|
|
185
|
+
report = check.run(schema_id="user_schema_v1", data=extract_data())
|
|
186
|
+
if not report.passed:
|
|
187
|
+
raise ValueError("Quality check failed")
|
|
188
|
+
|
|
189
|
+
with DAG("data_pipeline") as dag:
|
|
190
|
+
quality_check = PythonOperator(
|
|
191
|
+
task_id="quality_check",
|
|
192
|
+
python_callable=quality_check_task
|
|
193
|
+
)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Prefect
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
from prefect import flow, task
|
|
200
|
+
from pycharter import QualityCheck
|
|
201
|
+
|
|
202
|
+
@task
|
|
203
|
+
def quality_check_task(schema_id: str, data):
|
|
204
|
+
check = QualityCheck(store=store)
|
|
205
|
+
return check.run(schema_id=schema_id, data=data)
|
|
206
|
+
|
|
207
|
+
@flow
|
|
208
|
+
def data_pipeline():
|
|
209
|
+
data = extract_data()
|
|
210
|
+
report = quality_check_task("user_schema_v1", data)
|
|
211
|
+
return report
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Dagster
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
from dagster import asset, op
|
|
218
|
+
from pycharter import QualityCheck
|
|
219
|
+
|
|
220
|
+
@op
|
|
221
|
+
def quality_check_op(context, data):
|
|
222
|
+
check = QualityCheck(store=store)
|
|
223
|
+
report = check.run(schema_id="user_schema_v1", data=data)
|
|
224
|
+
context.log.info(f"Quality score: {report.quality_score.overall_score}")
|
|
225
|
+
return report
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Future Enhancements
|
|
229
|
+
|
|
230
|
+
- Database persistence for violations and metrics
|
|
231
|
+
- Scheduled quality monitoring jobs
|
|
232
|
+
- Quality dashboards and visualizations
|
|
233
|
+
- Data profiling capabilities
|
|
234
|
+
- Remediation workflows
|
|
235
|
+
|
|
@@ -62,6 +62,10 @@ from pycharter.runtime_validator.validator import (
|
|
|
62
62
|
Validator,
|
|
63
63
|
create_validator,
|
|
64
64
|
)
|
|
65
|
+
from pycharter.runtime_validator.utils import (
|
|
66
|
+
merge_rules_into_schema,
|
|
67
|
+
get_merged_schema_from_contract,
|
|
68
|
+
)
|
|
65
69
|
|
|
66
70
|
__all__ = [
|
|
67
71
|
# PRIMARY INTERFACE: Validator and Builder
|
|
@@ -85,4 +89,7 @@ __all__ = [
|
|
|
85
89
|
"validate_input",
|
|
86
90
|
"validate_output",
|
|
87
91
|
"validate_with_contract_decorator",
|
|
92
|
+
# Schema utilities
|
|
93
|
+
"merge_rules_into_schema",
|
|
94
|
+
"get_merged_schema_from_contract",
|
|
88
95
|
]
|
|
@@ -69,3 +69,36 @@ def merge_rules_into_schema(
|
|
|
69
69
|
|
|
70
70
|
return complete_schema
|
|
71
71
|
|
|
72
|
+
|
|
73
|
+
def get_merged_schema_from_contract(contract: Dict[str, Any]) -> Dict[str, Any]:
|
|
74
|
+
"""
|
|
75
|
+
Get merged schema from a contract dictionary.
|
|
76
|
+
|
|
77
|
+
This is a convenience function for cases where you need the merged schema
|
|
78
|
+
(e.g., for display, documentation generation, or legacy code).
|
|
79
|
+
|
|
80
|
+
For validation, prefer using the Validator class which handles merging
|
|
81
|
+
internally.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
contract: Contract dictionary with 'schema', 'coercion_rules', 'validation_rules' keys
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
Schema dictionary with coercion and validation rules merged into properties
|
|
88
|
+
|
|
89
|
+
Example:
|
|
90
|
+
>>> contract = build_contract(artifacts)
|
|
91
|
+
>>> merged = get_merged_schema_from_contract(contract)
|
|
92
|
+
>>> merged["properties"]["age"]["coercion"] # Rules are now in schema
|
|
93
|
+
'coerce_to_integer'
|
|
94
|
+
|
|
95
|
+
Note:
|
|
96
|
+
The returned schema is a deep copy - modifications won't affect the
|
|
97
|
+
original contract.
|
|
98
|
+
"""
|
|
99
|
+
schema = contract.get("schema", {})
|
|
100
|
+
coercion_rules = contract.get("coercion_rules", {})
|
|
101
|
+
validation_rules = contract.get("validation_rules", {})
|
|
102
|
+
|
|
103
|
+
return merge_rules_into_schema(schema, coercion_rules, validation_rules)
|
|
104
|
+
|
|
@@ -279,8 +279,7 @@ class Validator:
|
|
|
279
279
|
"""
|
|
280
280
|
Load contract from metadata store.
|
|
281
281
|
|
|
282
|
-
|
|
283
|
-
so we skip the merging step.
|
|
282
|
+
Fetches raw schema and rules separately, then merges internally.
|
|
284
283
|
|
|
285
284
|
Args:
|
|
286
285
|
store: MetadataStoreClient instance
|
|
@@ -290,17 +289,21 @@ class Validator:
|
|
|
290
289
|
Raises:
|
|
291
290
|
ValueError: If schema not found in store
|
|
292
291
|
"""
|
|
293
|
-
|
|
294
|
-
|
|
292
|
+
# Fetch raw schema (not merged)
|
|
293
|
+
raw_schema = store.get_schema(schema_id, version)
|
|
294
|
+
if not raw_schema:
|
|
295
295
|
raise ValueError(f"Schema '{schema_id}' not found in store" +
|
|
296
296
|
(f" (version: {version})" if version else ""))
|
|
297
297
|
|
|
298
|
-
#
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
self.
|
|
298
|
+
# Fetch rules separately
|
|
299
|
+
coercion_rules = store.get_coercion_rules(schema_id, version)
|
|
300
|
+
validation_rules = store.get_validation_rules(schema_id, version)
|
|
301
|
+
|
|
302
|
+
# Store raw components - merge will happen in _merge_rules_into_schema()
|
|
303
|
+
self.schema = raw_schema
|
|
304
|
+
self.coercion_rules = self._extract_rules(coercion_rules) if coercion_rules else {}
|
|
305
|
+
self.validation_rules = self._extract_rules(validation_rules) if validation_rules else {}
|
|
306
|
+
self._schema_from_store = False # Let internal merge happen
|
|
304
307
|
|
|
305
308
|
def _load_from_metadata(self, metadata: ContractMetadata) -> None:
|
|
306
309
|
"""
|