pycharter 0.0.19__tar.gz → 0.0.22__tar.gz
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-0.0.19 → pycharter-0.0.22}/MANIFEST.in +6 -1
- {pycharter-0.0.19/pycharter.egg-info → pycharter-0.0.22}/PKG-INFO +284 -62
- {pycharter-0.0.19 → pycharter-0.0.22}/README.md +282 -61
- {pycharter-0.0.19 → pycharter-0.0.22}/api/dependencies/__init__.py +2 -1
- {pycharter-0.0.19 → pycharter-0.0.22}/api/dependencies/database.py +71 -5
- {pycharter-0.0.19 → pycharter-0.0.22}/api/main.py +47 -8
- {pycharter-0.0.19 → pycharter-0.0.22}/api/models/contracts.py +6 -4
- {pycharter-0.0.19 → pycharter-0.0.22}/api/models/metadata.py +11 -7
- {pycharter-0.0.19 → pycharter-0.0.22}/api/models/schemas.py +16 -10
- {pycharter-0.0.19 → pycharter-0.0.22}/api/routes/v1/contracts.py +498 -226
- {pycharter-0.0.19 → pycharter-0.0.22}/api/routes/v1/metadata.py +52 -211
- {pycharter-0.0.19 → pycharter-0.0.22}/api/routes/v1/schemas.py +1 -1
- {pycharter-0.0.19 → pycharter-0.0.22}/api/routes/v1/settings.py +88 -1
- pycharter-0.0.22/api/utils.py +224 -0
- pycharter-0.0.22/pycharter/__init__.py +211 -0
- pycharter-0.0.22/pycharter/data/templates/template_transform_advanced.yaml +50 -0
- pycharter-0.0.22/pycharter/data/templates/template_transform_simple.yaml +59 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/models/base.py +1 -2
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/etl_generator/orchestrator.py +463 -487
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/metadata_store/postgres.py +16 -191
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/metadata_store/sqlite.py +12 -41
- {pycharter-0.0.19 → pycharter-0.0.22/pycharter.egg-info}/PKG-INFO +284 -62
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter.egg-info/SOURCES.txt +138 -2
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter.egg-info/requires.txt +1 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pyproject.toml +5 -1
- pycharter-0.0.22/ui/static/404/index.html +1 -0
- pycharter-0.0.22/ui/static/404.html +1 -0
- pycharter-0.0.22/ui/static/__next.__PAGE__.txt +10 -0
- pycharter-0.0.22/ui/static/__next._full.txt +30 -0
- pycharter-0.0.22/ui/static/__next._head.txt +7 -0
- pycharter-0.0.22/ui/static/__next._index.txt +9 -0
- pycharter-0.0.22/ui/static/__next._tree.txt +2 -0
- pycharter-0.0.22/ui/static/_next/static/0rYA78L88aUyD2Uh38hhX/_buildManifest.js +11 -0
- pycharter-0.0.22/ui/static/_next/static/0rYA78L88aUyD2Uh38hhX/_ssgManifest.js +1 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/13d4a0fbd74c1ee4.js +1 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/222442f6da32302a.js +1 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/247eb132b7f7b574.js +1 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/297d55555b71baba.js +1 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/2ab439ce003cd691.js +1 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/2edb43b48432ac04.js +441 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/414e77373f8ff61c.js +1 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/49ca65abd26ae49e.js +1 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/5e04d10c4a7b58a3.js +1 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/652ad0aa26265c47.js +2 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/75d88a058d8ffaa6.js +1 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/8c89634cf6bad76f.js +1 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/9667e7a3d359eb39.js +1 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/9c23f44fff36548a.js +1 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/a6dad97d9634a72d.js +1 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/b32a0963684b9933.js +4 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/c4fa4f4114b7c352.js +1 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/c69f6cba366bd988.js +1 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/d2363397e1b2bcab.css +1 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/db913959c675cea6.js +1 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/f061a4be97bfc3b3.js +1 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/f2e7afeab1178138.js +1 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/f7d1a90dd75d2572.js +1 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/ff1a16fafef87110.js +1 -0
- pycharter-0.0.22/ui/static/_next/static/chunks/turbopack-ffcb7ab6794027ef.js +3 -0
- pycharter-0.0.22/ui/static/_not-found/__next._full.txt +17 -0
- pycharter-0.0.22/ui/static/_not-found/__next._head.txt +7 -0
- pycharter-0.0.22/ui/static/_not-found/__next._index.txt +9 -0
- pycharter-0.0.22/ui/static/_not-found/__next._not-found.__PAGE__.txt +5 -0
- pycharter-0.0.22/ui/static/_not-found/__next._not-found.txt +4 -0
- pycharter-0.0.22/ui/static/_not-found/__next._tree.txt +2 -0
- pycharter-0.0.22/ui/static/_not-found/index.html +1 -0
- pycharter-0.0.22/ui/static/_not-found/index.txt +17 -0
- pycharter-0.0.22/ui/static/contracts/__next._full.txt +21 -0
- pycharter-0.0.22/ui/static/contracts/__next._head.txt +7 -0
- pycharter-0.0.22/ui/static/contracts/__next._index.txt +9 -0
- pycharter-0.0.22/ui/static/contracts/__next._tree.txt +2 -0
- pycharter-0.0.22/ui/static/contracts/__next.contracts.__PAGE__.txt +9 -0
- pycharter-0.0.22/ui/static/contracts/__next.contracts.txt +4 -0
- pycharter-0.0.22/ui/static/contracts/index.html +1 -0
- pycharter-0.0.22/ui/static/contracts/index.txt +21 -0
- pycharter-0.0.22/ui/static/documentation/__next._full.txt +21 -0
- pycharter-0.0.22/ui/static/documentation/__next._head.txt +7 -0
- pycharter-0.0.22/ui/static/documentation/__next._index.txt +9 -0
- pycharter-0.0.22/ui/static/documentation/__next._tree.txt +2 -0
- pycharter-0.0.22/ui/static/documentation/__next.documentation.__PAGE__.txt +9 -0
- pycharter-0.0.22/ui/static/documentation/__next.documentation.txt +4 -0
- pycharter-0.0.22/ui/static/documentation/index.html +93 -0
- pycharter-0.0.22/ui/static/documentation/index.txt +21 -0
- pycharter-0.0.22/ui/static/index.html +1 -0
- pycharter-0.0.22/ui/static/index.txt +30 -0
- pycharter-0.0.22/ui/static/metadata/__next._full.txt +21 -0
- pycharter-0.0.22/ui/static/metadata/__next._head.txt +7 -0
- pycharter-0.0.22/ui/static/metadata/__next._index.txt +9 -0
- pycharter-0.0.22/ui/static/metadata/__next._tree.txt +2 -0
- pycharter-0.0.22/ui/static/metadata/__next.metadata.__PAGE__.txt +9 -0
- pycharter-0.0.22/ui/static/metadata/__next.metadata.txt +4 -0
- pycharter-0.0.22/ui/static/metadata/index.html +1 -0
- pycharter-0.0.22/ui/static/metadata/index.txt +21 -0
- pycharter-0.0.22/ui/static/quality/__next._full.txt +21 -0
- pycharter-0.0.22/ui/static/quality/__next._head.txt +7 -0
- pycharter-0.0.22/ui/static/quality/__next._index.txt +9 -0
- pycharter-0.0.22/ui/static/quality/__next._tree.txt +2 -0
- pycharter-0.0.22/ui/static/quality/__next.quality.__PAGE__.txt +9 -0
- pycharter-0.0.22/ui/static/quality/__next.quality.txt +4 -0
- pycharter-0.0.22/ui/static/quality/index.html +2 -0
- pycharter-0.0.22/ui/static/quality/index.txt +21 -0
- pycharter-0.0.22/ui/static/rules/__next._full.txt +21 -0
- pycharter-0.0.22/ui/static/rules/__next._head.txt +7 -0
- pycharter-0.0.22/ui/static/rules/__next._index.txt +9 -0
- pycharter-0.0.22/ui/static/rules/__next._tree.txt +2 -0
- pycharter-0.0.22/ui/static/rules/__next.rules.__PAGE__.txt +9 -0
- pycharter-0.0.22/ui/static/rules/__next.rules.txt +4 -0
- pycharter-0.0.22/ui/static/rules/index.html +1 -0
- pycharter-0.0.22/ui/static/rules/index.txt +21 -0
- pycharter-0.0.22/ui/static/schemas/__next._full.txt +21 -0
- pycharter-0.0.22/ui/static/schemas/__next._head.txt +7 -0
- pycharter-0.0.22/ui/static/schemas/__next._index.txt +9 -0
- pycharter-0.0.22/ui/static/schemas/__next._tree.txt +2 -0
- pycharter-0.0.22/ui/static/schemas/__next.schemas.__PAGE__.txt +9 -0
- pycharter-0.0.22/ui/static/schemas/__next.schemas.txt +4 -0
- pycharter-0.0.22/ui/static/schemas/index.html +1 -0
- pycharter-0.0.22/ui/static/schemas/index.txt +21 -0
- pycharter-0.0.22/ui/static/settings/__next._full.txt +21 -0
- pycharter-0.0.22/ui/static/settings/__next._head.txt +7 -0
- pycharter-0.0.22/ui/static/settings/__next._index.txt +9 -0
- pycharter-0.0.22/ui/static/settings/__next._tree.txt +2 -0
- pycharter-0.0.22/ui/static/settings/__next.settings.__PAGE__.txt +9 -0
- pycharter-0.0.22/ui/static/settings/__next.settings.txt +4 -0
- pycharter-0.0.22/ui/static/settings/index.html +1 -0
- pycharter-0.0.22/ui/static/settings/index.txt +21 -0
- pycharter-0.0.22/ui/static/static/.gitkeep +0 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/222442f6da32302a.js +1 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/247eb132b7f7b574.js +1 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/297d55555b71baba.js +1 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/2ab439ce003cd691.js +1 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/414e77373f8ff61c.js +1 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/49ca65abd26ae49e.js +1 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/5e04d10c4a7b58a3.js +1 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/5fc14c00a2779dc5.js +1 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/652ad0aa26265c47.js +2 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/75d88a058d8ffaa6.js +1 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/8c89634cf6bad76f.js +1 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/9667e7a3d359eb39.js +1 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/9c23f44fff36548a.js +1 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/a6dad97d9634a72d.js +1 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/b32a0963684b9933.js +4 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/b584574fdc8ab13e.js +1 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/c69f6cba366bd988.js +1 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/d5989c94d3614b3a.js +158 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/db913959c675cea6.js +1 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/f061a4be97bfc3b3.js +1 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/f2e7afeab1178138.js +1 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/ff1a16fafef87110.js +1 -0
- pycharter-0.0.22/ui/static/static/_next/static/chunks/turbopack-ffcb7ab6794027ef.js +3 -0
- pycharter-0.0.22/ui/static/static/_next/static/tNTkVW6puVXC4bAm4WrHl/_buildManifest.js +11 -0
- pycharter-0.0.22/ui/static/static/_next/static/tNTkVW6puVXC4bAm4WrHl/_ssgManifest.js +1 -0
- pycharter-0.0.22/ui/static/validation/__next._full.txt +21 -0
- pycharter-0.0.22/ui/static/validation/__next._head.txt +7 -0
- pycharter-0.0.22/ui/static/validation/__next._index.txt +9 -0
- pycharter-0.0.22/ui/static/validation/__next._tree.txt +2 -0
- pycharter-0.0.22/ui/static/validation/__next.validation.__PAGE__.txt +9 -0
- pycharter-0.0.22/ui/static/validation/__next.validation.txt +4 -0
- pycharter-0.0.22/ui/static/validation/index.html +1 -0
- pycharter-0.0.22/ui/static/validation/index.txt +21 -0
- pycharter-0.0.19/pycharter/__init__.py +0 -155
- pycharter-0.0.19/pycharter/db/schemas/.ipynb_checkpoints/data_contract-checkpoint.py +0 -160
- {pycharter-0.0.19 → pycharter-0.0.22}/LICENSE +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/api/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/api/dependencies/store.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/api/models/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/api/models/metadata_entities.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/api/models/quality.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/api/models/validation.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/api/routes/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/api/routes/v1/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/api/routes/v1/quality.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/api/routes/v1/templates.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/api/routes/v1/validation.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/api/routes/v1/validation_jobs.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/cli.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/config.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/contract_builder/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/contract_builder/builder.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/contract_parser/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/contract_parser/parser.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/data/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/data/templates/template_coercion_rules.yaml +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/data/templates/template_contract.yaml +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/data/templates/template_metadata.yaml +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/data/templates/template_schema.yaml +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/data/templates/template_validation_rules.yaml +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/cli.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/migrations/README +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/migrations/env.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/migrations/script.py.mako +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/migrations/versions/20250115120000_add_tier2_tier3_entities.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/migrations/versions/20251209163657_799b73fe9f6c_initial_schema.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/migrations/versions/20251209164144_ae0efda02aa1_initial_schema.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/migrations/versions/20251217160146_f9995dc0f4b3_add_quality_tables.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/migrations/versions/20251217164915_8b08d78068e3_add_data_version_tracking.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/migrations/versions/20260110083000_a1b2c3d4e5f6_add_dead_letter_queue_table.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/migrations/versions/20260120000000_add_name_title_validation_constraints.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/migrations/versions/20260121000000_remove_artifact_versions_from_data_contracts.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/migrations/versions/20260122000000_change_artifact_unique_constraints_to_title_version.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/migrations/versions/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/models/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/models/api_endpoint.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/models/coercion_rule.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/models/compliance_framework.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/models/data_contract.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/models/data_dependency.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/models/data_feed.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/models/dlq.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/models/domain.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/models/environment.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/models/metadata_record.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/models/owner.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/models/quality_metric.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/models/quality_violation.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/models/schema.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/models/storage_location.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/models/system.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/models/tag.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/models/validation_rule.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/schemas/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/db/schemas/data_contract.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/etl_generator/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/etl_generator/checkpoint.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/etl_generator/config_generator.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/etl_generator/database.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/etl_generator/dlq.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/etl_generator/extraction.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/etl_generator/factory.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/etl_generator/progress.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/integrations/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/integrations/kafka.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/integrations/streaming.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/json_schema_converter/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/json_schema_converter/converter.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/json_schema_converter/reverse_converter.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/metadata_store/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/metadata_store/client.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/metadata_store/in_memory.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/metadata_store/mongodb.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/metadata_store/redis.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/py.typed +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/pydantic_generator/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/pydantic_generator/converter.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/pydantic_generator/generator.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/quality/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/quality/check.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/quality/cli.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/quality/metrics.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/quality/models.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/quality/profiling.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/quality/violations.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/runtime_validator/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/runtime_validator/decorators.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/runtime_validator/utils.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/runtime_validator/validator.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/runtime_validator/validator_core.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/runtime_validator/wrappers.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/shared/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/shared/coercions/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/shared/coercions/builtin.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/shared/json_schema_support.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/shared/json_schema_validator.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/shared/name_validator.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/shared/schema_parser.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/shared/schema_resolver.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/shared/validations/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/shared/validations/builtin.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/utils/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/utils/value_injector.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter/utils/version.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter.egg-info/dependency_links.txt +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter.egg-info/entry_points.txt +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/pycharter.egg-info/top_level.txt +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/setup.cfg +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/setup.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/tests/test_contract_builder.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/tests/test_contract_parser.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/tests/test_integration.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/tests/test_json_schema_compliance.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/tests/test_json_schema_converter.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/tests/test_metadata_stores.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/tests/test_pydantic_generator.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/tests/test_refs_and_definitions.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/tests/test_runtime_validator.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/tests/test_schema_parser.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/tests/test_value_injector.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/tests/test_x_validators.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/ui/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/ui/build.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/ui/dev.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/ui/server.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/ui/static/.gitkeep +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/404/index.html +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/404.html +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/__next.__PAGE__.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/__next._full.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/__next._head.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/__next._index.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/__next._tree.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/_next/static/chunks/4e310fe5005770a3.css +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/_not-found/__next._full.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/_not-found/__next._head.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/_not-found/__next._index.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/_not-found/__next._not-found.__PAGE__.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/_not-found/__next._not-found.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/_not-found/__next._tree.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/_not-found/index.html +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/_not-found/index.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/contracts/__next._full.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/contracts/__next._head.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/contracts/__next._index.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/contracts/__next._tree.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/contracts/__next.contracts.__PAGE__.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/contracts/__next.contracts.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/contracts/index.html +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/contracts/index.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/documentation/__next._full.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/documentation/__next._head.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/documentation/__next._index.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/documentation/__next._tree.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/documentation/__next.documentation.__PAGE__.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/documentation/__next.documentation.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/documentation/index.html +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/documentation/index.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/index.html +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/index.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/metadata/__next._full.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/metadata/__next._head.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/metadata/__next._index.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/metadata/__next._tree.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/metadata/__next.metadata.__PAGE__.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/metadata/__next.metadata.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/metadata/index.html +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/metadata/index.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/quality/__next._full.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/quality/__next._head.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/quality/__next._index.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/quality/__next._tree.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/quality/__next.quality.__PAGE__.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/quality/__next.quality.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/quality/index.html +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/quality/index.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/rules/__next._full.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/rules/__next._head.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/rules/__next._index.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/rules/__next._tree.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/rules/__next.rules.__PAGE__.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/rules/__next.rules.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/rules/index.html +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/rules/index.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/schemas/__next._full.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/schemas/__next._head.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/schemas/__next._index.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/schemas/__next._tree.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/schemas/__next.schemas.__PAGE__.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/schemas/__next.schemas.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/schemas/index.html +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/schemas/index.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/settings/__next._full.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/settings/__next._head.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/settings/__next._index.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/settings/__next._tree.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/settings/__next.settings.__PAGE__.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/settings/__next.settings.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/settings/index.html +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/settings/index.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/validation/__next._full.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/validation/__next._head.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/validation/__next._index.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/validation/__next._tree.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/validation/__next.validation.__PAGE__.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/validation/__next.validation.txt +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/validation/index.html +0 -0
- {pycharter-0.0.19/ui → pycharter-0.0.22/ui/static}/static/validation/index.txt +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/worker/__init__.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/worker/cli.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/worker/models.py +0 -0
- {pycharter-0.0.19 → pycharter-0.0.22}/worker/processor.py +0 -0
|
@@ -16,6 +16,11 @@ prune ui/.next
|
|
|
16
16
|
prune ui/out
|
|
17
17
|
prune ui/src
|
|
18
18
|
prune ui/public
|
|
19
|
-
|
|
19
|
+
# Exclude source files but NOT static build files
|
|
20
|
+
# Note: ui/static is explicitly included above, so these excludes won't affect it
|
|
21
|
+
recursive-exclude ui/src *.ts *.tsx *.js *.json *.md
|
|
22
|
+
recursive-exclude ui/src *.config.*
|
|
23
|
+
# Exclude other UI files (but not ui/static which is already included)
|
|
24
|
+
recursive-exclude ui *.ts *.tsx *.json *.md
|
|
20
25
|
recursive-exclude ui *.config.*
|
|
21
26
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pycharter
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.22
|
|
4
4
|
Summary: A Python package for data contract management with five core services: contract parsing, metadata storage, Pydantic generation, JSON Schema conversion, and runtime validation
|
|
5
5
|
Author-email: semantic developers <na@example.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -25,6 +25,7 @@ Requires-Dist: numpy>=1.24.0
|
|
|
25
25
|
Requires-Dist: pyyaml>=6.0.0
|
|
26
26
|
Requires-Dist: sqlalchemy>=2.0.0
|
|
27
27
|
Requires-Dist: alembic>=1.13.0
|
|
28
|
+
Requires-Dist: jsonata-python>=0.6.0
|
|
28
29
|
Provides-Extra: dev
|
|
29
30
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
30
31
|
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
@@ -158,12 +159,15 @@ pycharter ui dev # Development mode with hot reload
|
|
|
158
159
|
|
|
159
160
|
## 🚀 Quick Start
|
|
160
161
|
|
|
162
|
+
### Quick Start: Convenience Functions (One-off Use)
|
|
163
|
+
|
|
161
164
|
```python
|
|
162
|
-
from pycharter import from_dict
|
|
165
|
+
from pycharter import from_dict, validate
|
|
163
166
|
|
|
164
167
|
# Define your JSON schema
|
|
165
168
|
schema = {
|
|
166
169
|
"type": "object",
|
|
170
|
+
"version": "1.0.0",
|
|
167
171
|
"properties": {
|
|
168
172
|
"name": {"type": "string"},
|
|
169
173
|
"age": {"type": "integer"},
|
|
@@ -172,15 +176,91 @@ schema = {
|
|
|
172
176
|
"required": ["name", "age"]
|
|
173
177
|
}
|
|
174
178
|
|
|
175
|
-
# Generate a Pydantic model
|
|
179
|
+
# Generate a Pydantic model (convenience function)
|
|
176
180
|
Person = from_dict(schema, "Person")
|
|
177
181
|
|
|
178
|
-
#
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
print(
|
|
182
|
+
# Validate data
|
|
183
|
+
result = validate(Person, {"name": "Alice", "age": 30, "email": "alice@example.com"})
|
|
184
|
+
if result.is_valid:
|
|
185
|
+
print(f"Valid: {result.data.name}") # Output: Valid: Alice
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Production Use: Validator Class (Recommended)
|
|
189
|
+
|
|
190
|
+
For production code with multiple validations, use the `Validator` class for better performance:
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
from pycharter import Validator
|
|
194
|
+
|
|
195
|
+
# Create validator from contract directory or file
|
|
196
|
+
validator = Validator(contract_dir="data/contracts/user")
|
|
197
|
+
# Or: validator = Validator(contract_file="user_contract.yaml")
|
|
198
|
+
|
|
199
|
+
# Validate multiple records efficiently (model is cached)
|
|
200
|
+
result1 = validator.validate({"name": "Alice", "age": 30})
|
|
201
|
+
result2 = validator.validate({"name": "Bob", "age": 25})
|
|
202
|
+
|
|
203
|
+
# Batch validation
|
|
204
|
+
results = validator.validate_batch([data1, data2, data3])
|
|
182
205
|
```
|
|
183
206
|
|
|
207
|
+
### With Metadata Store
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
from pycharter import Validator, SQLiteMetadataStore
|
|
211
|
+
|
|
212
|
+
# Connect to metadata store
|
|
213
|
+
store = SQLiteMetadataStore("metadata.db")
|
|
214
|
+
store.connect()
|
|
215
|
+
|
|
216
|
+
# Create validator from store
|
|
217
|
+
validator = Validator(store=store, schema_id="user_schema_v1")
|
|
218
|
+
|
|
219
|
+
# Validate data
|
|
220
|
+
result = validator.validate({"name": "Alice", "age": 30})
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## 📐 API Organization
|
|
224
|
+
|
|
225
|
+
PyCharter's API is organized into **three tiers** to help you choose the right approach for your use case:
|
|
226
|
+
|
|
227
|
+
### Tier 1: Primary Interfaces (⭐ Recommended for Production)
|
|
228
|
+
|
|
229
|
+
**Classes** that provide the best performance and most features:
|
|
230
|
+
- **`Validator`** - Primary validation interface (use for multiple validations)
|
|
231
|
+
- **`QualityCheck`** - Primary quality assurance interface
|
|
232
|
+
- **`MetadataStoreClient`** - Base class for metadata stores
|
|
233
|
+
|
|
234
|
+
**When to use**: Production code, batch processing, when you need to validate multiple records.
|
|
235
|
+
|
|
236
|
+
### Tier 2: Convenience Functions (Quick Start)
|
|
237
|
+
|
|
238
|
+
**Functions** that make common tasks easy and discoverable:
|
|
239
|
+
- **Input helpers**: `from_dict()`, `from_file()`, `from_json()`, `from_url()`
|
|
240
|
+
- **Output helpers**: `to_dict()`, `to_file()`, `to_json()`
|
|
241
|
+
- **Validation helpers**: `validate_with_store()`, `validate_with_contract()`
|
|
242
|
+
- **Contract helpers**: `parse_contract_file()`, `build_contract()`
|
|
243
|
+
|
|
244
|
+
**When to use**: Quick scripts, one-off validations, exploratory work, learning the library.
|
|
245
|
+
|
|
246
|
+
### Tier 3: Low-Level Utilities
|
|
247
|
+
|
|
248
|
+
**Functions** for when you already have models or need fine-grained control:
|
|
249
|
+
- **`validate()`** - Validate with existing Pydantic model
|
|
250
|
+
- **`validate_batch()`** - Batch validate with existing model
|
|
251
|
+
- **`model_to_schema()`** - Core conversion function
|
|
252
|
+
|
|
253
|
+
**When to use**: Advanced use cases, when you've already generated models, custom workflows.
|
|
254
|
+
|
|
255
|
+
### Choosing the Right Approach
|
|
256
|
+
|
|
257
|
+
| Use Case | Recommended Approach | Example |
|
|
258
|
+
|----------|---------------------|---------|
|
|
259
|
+
| **Production pipeline with multiple validations** | `Validator` class | `validator = Validator(store=store, schema_id="schema"); validator.validate(data)` |
|
|
260
|
+
| **Quick one-off validation** | Convenience function | `validate_with_contract("contract.yaml", data)` |
|
|
261
|
+
| **You already have a model** | Low-level function | `validate(UserModel, data)` |
|
|
262
|
+
| **Batch processing** | `Validator.validate_batch()` | `validator.validate_batch([data1, data2, data3])` |
|
|
263
|
+
|
|
184
264
|
## 🏗️ Core Services & Data Production Journey
|
|
185
265
|
|
|
186
266
|
PyCharter provides **eight core services** that work together to support a complete data production journey, from contract specification to quality assurance. Each service plays a critical role in managing data contracts and ensuring data quality throughout your pipeline.
|
|
@@ -291,19 +371,20 @@ result = validate_with_contract(contract, {"name": "Alice", "age": "30"})
|
|
|
291
371
|
|
|
292
372
|
**Available Implementations**:
|
|
293
373
|
- **PostgresMetadataStore** - For PostgreSQL databases (recommended for production)
|
|
374
|
+
- **SQLiteMetadataStore** - For SQLite databases (great for development and small deployments)
|
|
294
375
|
- **MongoDBMetadataStore** - For MongoDB databases
|
|
295
376
|
- **RedisMetadataStore** - For Redis databases
|
|
296
377
|
- **InMemoryMetadataStore** - For testing and development (no persistence)
|
|
297
378
|
|
|
298
379
|
**Example**:
|
|
299
380
|
```python
|
|
300
|
-
from pycharter import
|
|
381
|
+
from pycharter import SQLiteMetadataStore, parse_contract_file
|
|
301
382
|
|
|
302
383
|
# Parse contract
|
|
303
384
|
metadata = parse_contract_file("contract.yaml")
|
|
304
385
|
|
|
305
|
-
# Use
|
|
306
|
-
store =
|
|
386
|
+
# Use SQLite metadata store (or PostgresMetadataStore, MongoDBMetadataStore, RedisMetadataStore, etc.)
|
|
387
|
+
store = SQLiteMetadataStore("metadata.db")
|
|
307
388
|
store.connect()
|
|
308
389
|
|
|
309
390
|
# Store decomposed components
|
|
@@ -415,6 +496,24 @@ ProductModel = from_dict(schema, "Product") # Round-trip
|
|
|
415
496
|
|
|
416
497
|
**When to Use**: In your data processing scripts, ETL pipelines, API endpoints, or any place where you need to validate incoming data against contract specifications.
|
|
417
498
|
|
|
499
|
+
**API Organization**:
|
|
500
|
+
|
|
501
|
+
PyCharter provides validation through three tiers:
|
|
502
|
+
|
|
503
|
+
1. **Tier 1: Validator Class** (⭐ **PRIMARY INTERFACE** - Recommended for production)
|
|
504
|
+
- Best performance for multiple validations (model is cached)
|
|
505
|
+
- Supports all data sources (contract files, directories, stores, dictionaries)
|
|
506
|
+
- Reusable instance for batch processing
|
|
507
|
+
|
|
508
|
+
2. **Tier 2: Convenience Functions** (Quick start - one-off validations)
|
|
509
|
+
- `validate_with_store()` - Quick validation with metadata store
|
|
510
|
+
- `validate_with_contract()` - Quick validation with contract file/dict
|
|
511
|
+
- `get_model_from_store()` / `get_model_from_contract()` - Get model for reuse
|
|
512
|
+
|
|
513
|
+
3. **Tier 3: Low-Level Functions** (When you already have a model)
|
|
514
|
+
- `validate()` - Validate single record with existing model
|
|
515
|
+
- `validate_batch()` - Batch validate with existing model
|
|
516
|
+
|
|
418
517
|
**How It Works**:
|
|
419
518
|
- Takes a Pydantic model (generated from a schema) and raw data
|
|
420
519
|
- Validates data against the model's constraints
|
|
@@ -422,55 +521,60 @@ ProductModel = from_dict(schema, "Product") # Round-trip
|
|
|
422
521
|
- Supports single record and batch validation
|
|
423
522
|
- Can be used in strict mode (raises exceptions) or lenient mode (returns results)
|
|
424
523
|
|
|
425
|
-
**
|
|
524
|
+
**Example - Validator Class (Recommended)**:
|
|
525
|
+
```python
|
|
526
|
+
from pycharter import Validator, SQLiteMetadataStore
|
|
426
527
|
|
|
427
|
-
1
|
|
428
|
-
|
|
429
|
-
|
|
528
|
+
# Option 1: From contract directory (no database)
|
|
529
|
+
validator = Validator(contract_dir="data/contracts/user")
|
|
530
|
+
result = validator.validate({"name": "Alice", "age": 30})
|
|
430
531
|
|
|
431
|
-
2
|
|
432
|
-
|
|
433
|
-
|
|
532
|
+
# Option 2: From metadata store (with database)
|
|
533
|
+
store = SQLiteMetadataStore("metadata.db")
|
|
534
|
+
store.connect()
|
|
535
|
+
validator = Validator(store=store, schema_id="user_schema_v1")
|
|
536
|
+
result = validator.validate({"name": "Alice", "age": 30})
|
|
434
537
|
|
|
435
|
-
|
|
538
|
+
# Option 3: From contract file
|
|
539
|
+
validator = Validator(contract_file="user_contract.yaml")
|
|
540
|
+
result = validator.validate({"name": "Alice", "age": 30})
|
|
541
|
+
|
|
542
|
+
# Batch validation (efficient - model cached)
|
|
543
|
+
results = validator.validate_batch([data1, data2, data3])
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
**Example - Convenience Functions (Quick Start)**:
|
|
436
547
|
```python
|
|
437
|
-
from pycharter import validate_with_store,
|
|
548
|
+
from pycharter import validate_with_store, validate_with_contract, SQLiteMetadataStore
|
|
438
549
|
|
|
439
|
-
#
|
|
440
|
-
store =
|
|
550
|
+
# Quick validation with store
|
|
551
|
+
store = SQLiteMetadataStore("metadata.db")
|
|
441
552
|
store.connect()
|
|
442
|
-
# ... store schema, rules, etc. ...
|
|
443
|
-
|
|
444
|
-
# Validate using store
|
|
445
553
|
result = validate_with_store(store, "user_schema_v1", {"name": "Alice", "age": 30})
|
|
446
|
-
|
|
447
|
-
|
|
554
|
+
|
|
555
|
+
# Quick validation with contract file (no database)
|
|
556
|
+
result = validate_with_contract("user_contract.yaml", {"name": "Alice", "age": 30})
|
|
448
557
|
```
|
|
449
558
|
|
|
450
|
-
**Example -
|
|
559
|
+
**Example - Low-Level (When You Have a Model)**:
|
|
451
560
|
```python
|
|
452
|
-
from pycharter import
|
|
561
|
+
from pycharter import from_dict, validate, validate_batch
|
|
453
562
|
|
|
454
|
-
#
|
|
455
|
-
|
|
456
|
-
"data/examples/book/book_contract.yaml",
|
|
457
|
-
{"isbn": "1234567890", "title": "Book", ...}
|
|
458
|
-
)
|
|
563
|
+
# Generate model
|
|
564
|
+
UserModel = from_dict(schema, "User")
|
|
459
565
|
|
|
460
|
-
#
|
|
461
|
-
|
|
462
|
-
result1 = validate(BookModel, data1)
|
|
463
|
-
result2 = validate(BookModel, data2)
|
|
566
|
+
# Validate single record
|
|
567
|
+
result = validate(UserModel, {"name": "Alice", "age": 30})
|
|
464
568
|
|
|
465
|
-
#
|
|
466
|
-
|
|
467
|
-
"schema": {"type": "object", "properties": {...}},
|
|
468
|
-
"coercion_rules": {"rules": {...}},
|
|
469
|
-
"validation_rules": {"rules": {...}}
|
|
470
|
-
}
|
|
471
|
-
result = validate_with_contract(contract, data)
|
|
569
|
+
# Batch validate
|
|
570
|
+
results = validate_batch(UserModel, [data1, data2, data3])
|
|
472
571
|
```
|
|
473
572
|
|
|
573
|
+
**Performance Tips**:
|
|
574
|
+
- ⚡ **For multiple validations**: Use `Validator` class (model is cached)
|
|
575
|
+
- ⚡ **For one-off validations**: Convenience functions are fine
|
|
576
|
+
- ⚡ **For batch processing**: Use `Validator.validate_batch()` or `validate_batch()`
|
|
577
|
+
|
|
474
578
|
**Contribution to Journey**: The runtime validator is the **enforcement layer** that ensures data quality in production. It validates actual data against contract specifications, catching violations early and preventing bad data from propagating through your systems. It supports both database-backed workflows (for production systems with metadata stores) and contract-based workflows (for simpler use cases without database dependencies).
|
|
475
579
|
|
|
476
580
|
---
|
|
@@ -533,9 +637,9 @@ Here's how all services work together in a complete data production journey:
|
|
|
533
637
|
```python
|
|
534
638
|
from pycharter import (
|
|
535
639
|
parse_contract_file,
|
|
536
|
-
|
|
640
|
+
SQLiteMetadataStore,
|
|
537
641
|
from_dict,
|
|
538
|
-
|
|
642
|
+
Validator,
|
|
539
643
|
to_dict
|
|
540
644
|
)
|
|
541
645
|
|
|
@@ -543,7 +647,7 @@ from pycharter import (
|
|
|
543
647
|
metadata = parse_contract_file("user_contract.yaml")
|
|
544
648
|
|
|
545
649
|
# Step 2: Store metadata in database
|
|
546
|
-
store =
|
|
650
|
+
store = SQLiteMetadataStore("metadata.db")
|
|
547
651
|
store.connect()
|
|
548
652
|
schema_id = store.store_schema("user", metadata.schema, version="1.0")
|
|
549
653
|
|
|
@@ -570,14 +674,27 @@ UserModel = from_dict(schema, "User")
|
|
|
570
674
|
schema_doc = to_dict(UserModel)
|
|
571
675
|
|
|
572
676
|
# Step 5: Validate data in production pipeline
|
|
677
|
+
# Option A: Using Validator class (recommended for production)
|
|
678
|
+
validator = Validator(store=store, schema_id=schema_id)
|
|
679
|
+
|
|
573
680
|
def process_user_data(raw_data):
|
|
574
|
-
result = validate(
|
|
681
|
+
result = validator.validate(raw_data)
|
|
575
682
|
if result.is_valid:
|
|
576
683
|
# Process validated data
|
|
577
684
|
return result.data
|
|
578
685
|
else:
|
|
579
686
|
# Handle validation errors
|
|
580
687
|
raise ValueError(f"Invalid data: {result.errors}")
|
|
688
|
+
|
|
689
|
+
# Option B: Using convenience function (quick start)
|
|
690
|
+
from pycharter import validate_with_store
|
|
691
|
+
|
|
692
|
+
def process_user_data_quick(raw_data):
|
|
693
|
+
result = validate_with_store(store, schema_id, raw_data)
|
|
694
|
+
if result.is_valid:
|
|
695
|
+
return result.data
|
|
696
|
+
else:
|
|
697
|
+
raise ValueError(f"Invalid data: {result.errors}")
|
|
581
698
|
```
|
|
582
699
|
|
|
583
700
|
---
|
|
@@ -646,12 +763,14 @@ Each service is designed to be **independent** yet **composable**, allowing you
|
|
|
646
763
|
|
|
647
764
|
### Basic Usage
|
|
648
765
|
|
|
766
|
+
**Using Convenience Functions** (Quick Start):
|
|
649
767
|
```python
|
|
650
768
|
from pycharter import from_dict, from_json, from_file
|
|
651
769
|
|
|
652
770
|
# From dictionary
|
|
653
771
|
schema = {
|
|
654
772
|
"type": "object",
|
|
773
|
+
"version": "1.0.0",
|
|
655
774
|
"properties": {
|
|
656
775
|
"title": {"type": "string"},
|
|
657
776
|
"published": {"type": "boolean", "default": False}
|
|
@@ -660,13 +779,26 @@ schema = {
|
|
|
660
779
|
Article = from_dict(schema, "Article")
|
|
661
780
|
|
|
662
781
|
# From JSON string
|
|
663
|
-
schema_json = '{"type": "object", "properties": {"name": {"type": "string"}}}'
|
|
782
|
+
schema_json = '{"type": "object", "version": "1.0.0", "properties": {"name": {"type": "string"}}}'
|
|
664
783
|
User = from_json(schema_json, "User")
|
|
665
784
|
|
|
666
785
|
# From file
|
|
667
786
|
Product = from_file("product_schema.json", "Product")
|
|
668
787
|
```
|
|
669
788
|
|
|
789
|
+
**Using Validator Class** (Production):
|
|
790
|
+
```python
|
|
791
|
+
from pycharter import Validator
|
|
792
|
+
|
|
793
|
+
# From contract directory
|
|
794
|
+
validator = Validator(contract_dir="data/contracts/article")
|
|
795
|
+
result = validator.validate({"title": "My Article", "published": True})
|
|
796
|
+
|
|
797
|
+
# From contract file
|
|
798
|
+
validator = Validator(contract_file="article_contract.yaml")
|
|
799
|
+
result = validator.validate({"title": "My Article", "published": True})
|
|
800
|
+
```
|
|
801
|
+
|
|
670
802
|
### Nested Objects
|
|
671
803
|
|
|
672
804
|
```python
|
|
@@ -674,6 +806,7 @@ from pycharter import from_dict
|
|
|
674
806
|
|
|
675
807
|
schema = {
|
|
676
808
|
"type": "object",
|
|
809
|
+
"version": "1.0.0",
|
|
677
810
|
"properties": {
|
|
678
811
|
"name": {"type": "string"},
|
|
679
812
|
"address": {
|
|
@@ -707,6 +840,7 @@ from pycharter import from_dict
|
|
|
707
840
|
|
|
708
841
|
schema = {
|
|
709
842
|
"type": "object",
|
|
843
|
+
"version": "1.0.0",
|
|
710
844
|
"properties": {
|
|
711
845
|
"tags": {
|
|
712
846
|
"type": "array",
|
|
@@ -739,13 +873,14 @@ print(cart.items[0].name) # Output: Apple
|
|
|
739
873
|
|
|
740
874
|
### Coercion and Validation
|
|
741
875
|
|
|
742
|
-
|
|
876
|
+
PyCharter supports **coercion** (pre-validation transformation) and **validation** (post-validation checks):
|
|
743
877
|
|
|
744
878
|
```python
|
|
745
879
|
from pycharter import from_dict
|
|
746
880
|
|
|
747
881
|
schema = {
|
|
748
882
|
"type": "object",
|
|
883
|
+
"version": "1.0.0",
|
|
749
884
|
"properties": {
|
|
750
885
|
"flight_number": {
|
|
751
886
|
"type": "integer",
|
|
@@ -871,13 +1006,88 @@ register_validation("must_be_positive", must_be_positive)
|
|
|
871
1006
|
|
|
872
1007
|
## 📖 API Reference
|
|
873
1008
|
|
|
874
|
-
|
|
1009
|
+
PyCharter's API is organized into three tiers to help you choose the right approach:
|
|
875
1010
|
|
|
1011
|
+
### Tier 1: Primary Interfaces (Classes - Best Performance)
|
|
1012
|
+
|
|
1013
|
+
**Validator** - Primary validation interface (recommended for production)
|
|
1014
|
+
```python
|
|
1015
|
+
from pycharter import Validator
|
|
1016
|
+
|
|
1017
|
+
# Create validator from various sources
|
|
1018
|
+
validator = Validator(contract_dir="data/contracts/user")
|
|
1019
|
+
validator = Validator(contract_file="contract.yaml")
|
|
1020
|
+
validator = Validator(store=store, schema_id="user_schema")
|
|
1021
|
+
validator = Validator(contract_dict={...})
|
|
1022
|
+
|
|
1023
|
+
# Validate data
|
|
1024
|
+
result = validator.validate(data)
|
|
1025
|
+
results = validator.validate_batch([data1, data2])
|
|
1026
|
+
model = validator.get_model() # Get the generated Pydantic model
|
|
1027
|
+
```
|
|
1028
|
+
|
|
1029
|
+
**QualityCheck** - Primary quality assurance interface
|
|
1030
|
+
```python
|
|
1031
|
+
from pycharter import QualityCheck, QualityCheckOptions
|
|
1032
|
+
|
|
1033
|
+
check = QualityCheck(store=store)
|
|
1034
|
+
report = check.run(schema_id="user_schema", data=data, options=QualityCheckOptions(...))
|
|
1035
|
+
```
|
|
1036
|
+
|
|
1037
|
+
**MetadataStoreClient** - Base class for metadata stores
|
|
1038
|
+
```python
|
|
1039
|
+
from pycharter import MetadataStoreClient, SQLiteMetadataStore, PostgresMetadataStore
|
|
1040
|
+
|
|
1041
|
+
store = SQLiteMetadataStore("metadata.db")
|
|
1042
|
+
store.connect()
|
|
1043
|
+
```
|
|
1044
|
+
|
|
1045
|
+
### Tier 2: Convenience Functions (Quick Start)
|
|
1046
|
+
|
|
1047
|
+
**Pydantic Generator** - Input type helpers
|
|
876
1048
|
- **`from_dict(schema: dict, model_name: str = "DynamicModel")`** - Create model from dictionary
|
|
877
1049
|
- **`from_json(json_string: str, model_name: str = "DynamicModel")`** - Create model from JSON string
|
|
878
|
-
- **`from_file(file_path: str, model_name: str = None)`** - Create model from JSON
|
|
1050
|
+
- **`from_file(file_path: str, model_name: str = None)`** - Create model from file (JSON/YAML)
|
|
879
1051
|
- **`from_url(url: str, model_name: str = "DynamicModel")`** - Create model from URL
|
|
880
|
-
- **`
|
|
1052
|
+
- **`generate_model(schema: dict, model_name: str = "DynamicModel")`** - Advanced: more control
|
|
1053
|
+
- **`generate_model_file(schema: dict, output_path: str, model_name: str = "DynamicModel")`** - Generate and save to file
|
|
1054
|
+
|
|
1055
|
+
**JSON Schema Converter** - Output type helpers
|
|
1056
|
+
- **`to_dict(model: Type[BaseModel], ...)`** - Convert model to JSON Schema dictionary
|
|
1057
|
+
- **`to_file(model: Type[BaseModel], file_path: str, ...)`** - Convert model to file
|
|
1058
|
+
- **`to_json(model: Type[BaseModel], ...)`** - Convert model to JSON string
|
|
1059
|
+
- **`model_to_schema(model: Type[BaseModel], ...)`** - Advanced: core conversion function
|
|
1060
|
+
|
|
1061
|
+
**Runtime Validator** - Data source helpers
|
|
1062
|
+
- **`validate_with_store(store, schema_id, data, ...)`** - Quick validation with metadata store
|
|
1063
|
+
- **`validate_batch_with_store(store, schema_id, data_list, ...)`** - Batch validation with store
|
|
1064
|
+
- **`validate_with_contract(contract, data, ...)`** - Quick validation with contract file/dict
|
|
1065
|
+
- **`validate_batch_with_contract(contract, data_list, ...)`** - Batch validation with contract
|
|
1066
|
+
- **`get_model_from_store(store, schema_id, ...)`** - Get model from metadata store
|
|
1067
|
+
- **`get_model_from_contract(contract, ...)`** - Get model from contract
|
|
1068
|
+
- **`validate_input(contract, ...)`** - Decorator for function input validation
|
|
1069
|
+
- **`validate_output(contract, ...)`** - Decorator for function output validation
|
|
1070
|
+
- **`validate_with_contract_decorator(contract, ...)`** - Decorator for contract-based validation
|
|
1071
|
+
|
|
1072
|
+
**Contract Management**
|
|
1073
|
+
- **`parse_contract(contract_dict: dict)`** - Parse contract dictionary
|
|
1074
|
+
- **`parse_contract_file(file_path: str)`** - Parse contract file (YAML/JSON)
|
|
1075
|
+
- **`build_contract(artifacts: ContractArtifacts)`** - Build contract from artifacts
|
|
1076
|
+
- **`build_contract_from_store(store, schema_id, ...)`** - Build contract from metadata store
|
|
1077
|
+
|
|
1078
|
+
### Tier 3: Low-Level Utilities (When You Have Models)
|
|
1079
|
+
|
|
1080
|
+
- **`validate(model: Type[BaseModel], data: dict, strict: bool = False)`** - Validate single record
|
|
1081
|
+
- **`validate_batch(model: Type[BaseModel], data_list: List[dict], strict: bool = False)`** - Batch validate
|
|
1082
|
+
- **`ValidationResult`** - Result class with `is_valid`, `data`, and `errors` attributes
|
|
1083
|
+
|
|
1084
|
+
### Metadata Store Implementations
|
|
1085
|
+
|
|
1086
|
+
- **`InMemoryMetadataStore()`** - In-memory store (testing/development)
|
|
1087
|
+
- **`SQLiteMetadataStore(database_path: str)`** - SQLite database
|
|
1088
|
+
- **`PostgresMetadataStore(connection_string: str)`** - PostgreSQL database
|
|
1089
|
+
- **`MongoDBMetadataStore(connection_string: str)`** - MongoDB database
|
|
1090
|
+
- **`RedisMetadataStore(connection_string: str)`** - Redis database
|
|
881
1091
|
|
|
882
1092
|
## 🎯 Design Principles & Requirements
|
|
883
1093
|
|
|
@@ -979,21 +1189,33 @@ pytest -k "coercion"
|
|
|
979
1189
|
|
|
980
1190
|
## 📦 Publishing to PyPI
|
|
981
1191
|
|
|
1192
|
+
**Automatic publishing via GitHub Releases (Trusted Publishing - no tokens needed!):**
|
|
1193
|
+
|
|
982
1194
|
```bash
|
|
983
|
-
# Update version in pyproject.toml
|
|
984
|
-
#
|
|
985
|
-
|
|
1195
|
+
# 1. Update version in pyproject.toml
|
|
1196
|
+
# version = "0.0.21"
|
|
1197
|
+
|
|
1198
|
+
# 2. Commit and push
|
|
1199
|
+
git add pyproject.toml
|
|
1200
|
+
git commit -m "Bump version to 0.0.21"
|
|
1201
|
+
git push
|
|
986
1202
|
|
|
987
|
-
#
|
|
988
|
-
|
|
1203
|
+
# 3. Create GitHub Release (automatically publishes to PyPI)
|
|
1204
|
+
gh release create v0.0.21 --title "v0.0.21" --notes "Release notes"
|
|
1205
|
+
```
|
|
989
1206
|
|
|
990
|
-
|
|
991
|
-
|
|
1207
|
+
The workflow automatically:
|
|
1208
|
+
- ✅ Builds UI
|
|
1209
|
+
- ✅ Builds Python package
|
|
1210
|
+
- ✅ Publishes to PyPI (using Trusted Publishing)
|
|
992
1211
|
|
|
993
|
-
|
|
994
|
-
|
|
1212
|
+
**Local build:**
|
|
1213
|
+
```bash
|
|
1214
|
+
make build # Builds package (UI built automatically via setup.py)
|
|
995
1215
|
```
|
|
996
1216
|
|
|
1217
|
+
See `PUBLISHING.md` for complete documentation.
|
|
1218
|
+
|
|
997
1219
|
## 📋 JSON Schema Compliance
|
|
998
1220
|
|
|
999
1221
|
PyCharter is fully compliant with **JSON Schema Draft 2020-12** standard:
|