sqllocks-shape 0.9.0__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.
- sqllocks_shape-0.9.0/.devcontainer/devcontainer.json +6 -0
- sqllocks_shape-0.9.0/.env.example +1 -0
- sqllocks_shape-0.9.0/.github/ISSUE_TEMPLATE/bug.md +10 -0
- sqllocks_shape-0.9.0/.github/pull_request_template.md +6 -0
- sqllocks_shape-0.9.0/.github/workflows/ci.yml +109 -0
- sqllocks_shape-0.9.0/.github/workflows/nightly.yml +42 -0
- sqllocks_shape-0.9.0/.github/workflows/publish.yml +80 -0
- sqllocks_shape-0.9.0/.github/workflows/release.yml +24 -0
- sqllocks_shape-0.9.0/.github/workflows/security.yml +17 -0
- sqllocks_shape-0.9.0/.gitignore +25 -0
- sqllocks_shape-0.9.0/CHANGELOG.md +11 -0
- sqllocks_shape-0.9.0/CLAUDE.md +41 -0
- sqllocks_shape-0.9.0/CODEOWNERS +4 -0
- sqllocks_shape-0.9.0/CONTRIBUTING.md +3 -0
- sqllocks_shape-0.9.0/GOVERNANCE.md +3 -0
- sqllocks_shape-0.9.0/LICENSE +21 -0
- sqllocks_shape-0.9.0/Makefile +17 -0
- sqllocks_shape-0.9.0/PKG-INFO +105 -0
- sqllocks_shape-0.9.0/README.md +55 -0
- sqllocks_shape-0.9.0/SECURITY.md +11 -0
- sqllocks_shape-0.9.0/THIRD_PARTY_NOTICES.md +20 -0
- sqllocks_shape-0.9.0/benchmarks/baselines/2026-09-29/profile_bench.json +620 -0
- sqllocks_shape-0.9.0/benchmarks/baselines/2026-09-29/profile_verify.txt +718 -0
- sqllocks_shape-0.9.0/benchmarks/baselines/2026-09-29/retail_bench.json +1933 -0
- sqllocks_shape-0.9.0/benchmarks/baselines/2026-09-29/retail_large_seed_study.json +1 -0
- sqllocks_shape-0.9.0/benchmarks/baselines/2026-09-29/retail_verify_large.json +4684 -0
- sqllocks_shape-0.9.0/benchmarks/baselines/2026-09-29/retail_verify_large.txt +144 -0
- sqllocks_shape-0.9.0/benchmarks/baselines/2026-09-29/retail_verify_medium.json +4679 -0
- sqllocks_shape-0.9.0/benchmarks/baselines/2026-09-29/retail_verify_medium.txt +144 -0
- sqllocks_shape-0.9.0/benchmarks/baselines/2026-09-29/retail_verify_medium_sameseed.json +4453 -0
- sqllocks_shape-0.9.0/benchmarks/baselines/2026-09-29/retail_verify_medium_sameseed.txt +144 -0
- sqllocks_shape-0.9.0/benchmarks/baselines/2026-09-29/retail_verify_small.json +4718 -0
- sqllocks_shape-0.9.0/benchmarks/baselines/2026-09-29/retail_verify_small.txt +144 -0
- sqllocks_shape-0.9.0/benchmarks/vs_spindle/README.md +40 -0
- sqllocks_shape-0.9.0/benchmarks/vs_spindle/check_coverage.py +89 -0
- sqllocks_shape-0.9.0/benchmarks/vs_spindle/common.py +58 -0
- sqllocks_shape-0.9.0/benchmarks/vs_spindle/domain_1to1/README.md +437 -0
- sqllocks_shape-0.9.0/benchmarks/vs_spindle/domain_1to1/bench.py +199 -0
- sqllocks_shape-0.9.0/benchmarks/vs_spindle/domain_1to1/generate.py +209 -0
- sqllocks_shape-0.9.0/benchmarks/vs_spindle/domain_1to1/port.py +1432 -0
- sqllocks_shape-0.9.0/benchmarks/vs_spindle/domain_1to1/verify.py +880 -0
- sqllocks_shape-0.9.0/benchmarks/vs_spindle/dump_schema.py +64 -0
- sqllocks_shape-0.9.0/benchmarks/vs_spindle/paths.py +24 -0
- sqllocks_shape-0.9.0/benchmarks/vs_spindle/profile_1to1/README.md +208 -0
- sqllocks_shape-0.9.0/benchmarks/vs_spindle/profile_1to1/bench.py +268 -0
- sqllocks_shape-0.9.0/benchmarks/vs_spindle/profile_1to1/datasets.py +436 -0
- sqllocks_shape-0.9.0/benchmarks/vs_spindle/profile_1to1/port.py +1917 -0
- sqllocks_shape-0.9.0/benchmarks/vs_spindle/profile_1to1/spindle_cli_profile.py +40 -0
- sqllocks_shape-0.9.0/benchmarks/vs_spindle/profile_1to1/spindle_dump.py +138 -0
- sqllocks_shape-0.9.0/benchmarks/vs_spindle/profile_1to1/verify.py +289 -0
- sqllocks_shape-0.9.0/benchmarks/vs_spindle/results.json +241 -0
- sqllocks_shape-0.9.0/benchmarks/vs_spindle/results.schema.json +61 -0
- sqllocks_shape-0.9.0/benchmarks/vs_spindle/run.py +521 -0
- sqllocks_shape-0.9.0/benchmarks/vs_spindle/setup_spindle.sh +32 -0
- sqllocks_shape-0.9.0/docs/API_STABILITY.md +7 -0
- sqllocks_shape-0.9.0/docs/BRANDING.md +17 -0
- sqllocks_shape-0.9.0/docs/CONTRIBUTING.md +13 -0
- sqllocks_shape-0.9.0/docs/DETERMINISM.md +7 -0
- sqllocks_shape-0.9.0/docs/EXTERNAL_REFERENCE_ASSETS.md +8 -0
- sqllocks_shape-0.9.0/docs/INSTALL.md +21 -0
- sqllocks_shape-0.9.0/docs/LOCATION_AS_CODE.md +8 -0
- sqllocks_shape-0.9.0/docs/PRIVACY_MODEL.md +2 -0
- sqllocks_shape-0.9.0/docs/PRODUCT_ARCHITECTURE.md +202 -0
- sqllocks_shape-0.9.0/docs/QUICKSTART.md +23 -0
- sqllocks_shape-0.9.0/docs/RELEASE_POLICY.md +2 -0
- sqllocks_shape-0.9.0/docs/SECURITY_SPECIFICATION.md +322 -0
- sqllocks_shape-0.9.0/docs/SHAPE_MANIFESTO.md +27 -0
- sqllocks_shape-0.9.0/docs/THREAT_MODEL.md +11 -0
- sqllocks_shape-0.9.0/docs/TUTORIAL.md +12 -0
- sqllocks_shape-0.9.0/docs/plans/COMPLETION_PLAN.md +2456 -0
- sqllocks_shape-0.9.0/docs/plans/demo_status/DM-00.md +29 -0
- sqllocks_shape-0.9.0/docs/plans/demo_status/DM-01.md +62 -0
- sqllocks_shape-0.9.0/docs/plans/demo_status/DM-01_verify_output.txt +67 -0
- sqllocks_shape-0.9.0/docs/plans/demo_status/DM-02.md +62 -0
- sqllocks_shape-0.9.0/docs/plans/demo_status/DM-03.md +54 -0
- sqllocks_shape-0.9.0/docs/plans/demo_status/DM-03b.md +60 -0
- sqllocks_shape-0.9.0/docs/plans/demo_status/DM-04.md +24 -0
- sqllocks_shape-0.9.0/docs/plans/demo_status/DM-05.md +22 -0
- sqllocks_shape-0.9.0/docs/plans/demo_status/DM-05b.md +20 -0
- sqllocks_shape-0.9.0/docs/plans/demo_status/DM-06.md +25 -0
- sqllocks_shape-0.9.0/docs/plans/demo_status/DM-07.md +26 -0
- sqllocks_shape-0.9.0/docs/plans/demo_status/DM-08-talk.md +25 -0
- sqllocks_shape-0.9.0/docs/plans/demo_status/DM-08.md +16 -0
- sqllocks_shape-0.9.0/docs/plans/demo_status/GATE-G0.md +70 -0
- sqllocks_shape-0.9.0/docs/plans/demo_status/MORNING_SUMMARY.md +44 -0
- sqllocks_shape-0.9.0/docs/plans/spindle_coverage.tsv +149 -0
- sqllocks_shape-0.9.0/docs/specs/LOCATION_SPEC.md +3 -0
- sqllocks_shape-0.9.0/docs/specs/ONE_ZERO_CONTRACT.md +14 -0
- sqllocks_shape-0.9.0/docs/specs/PACK_SPEC.md +3 -0
- sqllocks_shape-0.9.0/docs/specs/PLUGIN_PROTOCOL.md +5 -0
- sqllocks_shape-0.9.0/docs/specs/SHAPE_1_0.md +17 -0
- sqllocks_shape-0.9.0/docs/specs/SHAPE_1_0_GA.md +49 -0
- sqllocks_shape-0.9.0/docs/specs/SHAPE_ARTIFACT_SPEC.md +13 -0
- sqllocks_shape-0.9.0/docs/specs/STREAMING_SEMANTICS.md +3 -0
- sqllocks_shape-0.9.0/docs/specs/requirements.yaml +719 -0
- sqllocks_shape-0.9.0/docs/specs/shape-v1-ga.schema.json +83 -0
- sqllocks_shape-0.9.0/docs/specs/shape-v1.schema.json +82 -0
- sqllocks_shape-0.9.0/examples/classified_release.py +5 -0
- sqllocks_shape-0.9.0/examples/customer.shape.json +36 -0
- sqllocks_shape-0.9.0/examples/shape_as_code.py +8 -0
- sqllocks_shape-0.9.0/pyproject.toml +159 -0
- sqllocks_shape-0.9.0/scripts/build_pure_wheel.py +285 -0
- sqllocks_shape-0.9.0/scripts/check_requirements.py +15 -0
- sqllocks_shape-0.9.0/scripts/check_secrets.py +15 -0
- sqllocks_shape-0.9.0/scripts/env.sh +8 -0
- sqllocks_shape-0.9.0/security/CLASSIFICATION_PROPAGATION.md +11 -0
- sqllocks_shape-0.9.0/security/THREAT_MODEL.md +8 -0
- sqllocks_shape-0.9.0/src/shape/__init__.py +84 -0
- sqllocks_shape-0.9.0/src/shape/api.py +65 -0
- sqllocks_shape-0.9.0/src/shape/artifact/__init__.py +36 -0
- sqllocks_shape-0.9.0/src/shape/artifact/canonical.py +30 -0
- sqllocks_shape-0.9.0/src/shape/artifact/io.py +120 -0
- sqllocks_shape-0.9.0/src/shape/artifact/migrate.py +53 -0
- sqllocks_shape-0.9.0/src/shape/artifact/secure.py +58 -0
- sqllocks_shape-0.9.0/src/shape/artifact/shape_file.py +63 -0
- sqllocks_shape-0.9.0/src/shape/capture/__init__.py +5 -0
- sqllocks_shape-0.9.0/src/shape/capture/core.py +75 -0
- sqllocks_shape-0.9.0/src/shape/capture/vectorized.py +82 -0
- sqllocks_shape-0.9.0/src/shape/cli/__init__.py +1 -0
- sqllocks_shape-0.9.0/src/shape/cli/main.py +320 -0
- sqllocks_shape-0.9.0/src/shape/connectors/__init__.py +31 -0
- sqllocks_shape-0.9.0/src/shape/connectors/dbapi.py +55 -0
- sqllocks_shape-0.9.0/src/shape/connectors/eventhubs.py +34 -0
- sqllocks_shape-0.9.0/src/shape/connectors/files.py +69 -0
- sqllocks_shape-0.9.0/src/shape/connectors/kafka.py +36 -0
- sqllocks_shape-0.9.0/src/shape/connectors/qualification.py +70 -0
- sqllocks_shape-0.9.0/src/shape/connectors/registry.py +22 -0
- sqllocks_shape-0.9.0/src/shape/contracts/__init__.py +18 -0
- sqllocks_shape-0.9.0/src/shape/contracts/core.py +147 -0
- sqllocks_shape-0.9.0/src/shape/contracts/v1.py +350 -0
- sqllocks_shape-0.9.0/src/shape/diff/__init__.py +4 -0
- sqllocks_shape-0.9.0/src/shape/diff/core.py +29 -0
- sqllocks_shape-0.9.0/src/shape/drift/__init__.py +6 -0
- sqllocks_shape-0.9.0/src/shape/drift/core.py +62 -0
- sqllocks_shape-0.9.0/src/shape/drift/policy.py +22 -0
- sqllocks_shape-0.9.0/src/shape/errors.py +21 -0
- sqllocks_shape-0.9.0/src/shape/generation/__init__.py +195 -0
- sqllocks_shape-0.9.0/src/shape/generation/address_vectorized.py +77 -0
- sqllocks_shape-0.9.0/src/shape/generation/advanced.py +60 -0
- sqllocks_shape-0.9.0/src/shape/generation/certificate.py +109 -0
- sqllocks_shape-0.9.0/src/shape/generation/compiler.py +154 -0
- sqllocks_shape-0.9.0/src/shape/generation/core.py +43 -0
- sqllocks_shape-0.9.0/src/shape/generation/distribution_fidelity.py +30 -0
- sqllocks_shape-0.9.0/src/shape/generation/evolution.py +33 -0
- sqllocks_shape-0.9.0/src/shape/generation/fidelity.py +127 -0
- sqllocks_shape-0.9.0/src/shape/generation/future.py +14 -0
- sqllocks_shape-0.9.0/src/shape/generation/geo_fidelity.py +21 -0
- sqllocks_shape-0.9.0/src/shape/generation/joint.py +49 -0
- sqllocks_shape-0.9.0/src/shape/generation/levels.py +51 -0
- sqllocks_shape-0.9.0/src/shape/generation/relational.py +83 -0
- sqllocks_shape-0.9.0/src/shape/generation/relational_fidelity.py +33 -0
- sqllocks_shape-0.9.0/src/shape/generation/release.py +18 -0
- sqllocks_shape-0.9.0/src/shape/generation/strategies.py +144 -0
- sqllocks_shape-0.9.0/src/shape/generation/timeline.py +63 -0
- sqllocks_shape-0.9.0/src/shape/generation/vectorized.py +31 -0
- sqllocks_shape-0.9.0/src/shape/geospatial/__init__.py +5 -0
- sqllocks_shape-0.9.0/src/shape/geospatial/core.py +40 -0
- sqllocks_shape-0.9.0/src/shape/kernel/__init__.py +4 -0
- sqllocks_shape-0.9.0/src/shape/kernel/batches.py +25 -0
- sqllocks_shape-0.9.0/src/shape/location/__init__.py +51 -0
- sqllocks_shape-0.9.0/src/shape/location/core.py +167 -0
- sqllocks_shape-0.9.0/src/shape/location/reference.py +106 -0
- sqllocks_shape-0.9.0/src/shape/model/__init__.py +14 -0
- sqllocks_shape-0.9.0/src/shape/model/core.py +69 -0
- sqllocks_shape-0.9.0/src/shape/packs/__init__.py +86 -0
- sqllocks_shape-0.9.0/src/shape/packs/address.py +228 -0
- sqllocks_shape-0.9.0/src/shape/packs/base.py +35 -0
- sqllocks_shape-0.9.0/src/shape/packs/domains.py +241 -0
- sqllocks_shape-0.9.0/src/shape/packs/person.py +20 -0
- sqllocks_shape-0.9.0/src/shape/packs/sdk.py +26 -0
- sqllocks_shape-0.9.0/src/shape/packs/verify.py +17 -0
- sqllocks_shape-0.9.0/src/shape/plugins/__init__.py +13 -0
- sqllocks_shape-0.9.0/src/shape/plugins/core.py +52 -0
- sqllocks_shape-0.9.0/src/shape/plugins/runtime.py +53 -0
- sqllocks_shape-0.9.0/src/shape/privacy/__init__.py +77 -0
- sqllocks_shape-0.9.0/src/shape/privacy/advanced.py +8 -0
- sqllocks_shape-0.9.0/src/shape/privacy/classification.py +17 -0
- sqllocks_shape-0.9.0/src/shape/privacy/core.py +35 -0
- sqllocks_shape-0.9.0/src/shape/privacy/detect.py +59 -0
- sqllocks_shape-0.9.0/src/shape/privacy/measure.py +58 -0
- sqllocks_shape-0.9.0/src/shape/privacy/policy.py +100 -0
- sqllocks_shape-0.9.0/src/shape/privacy/propagate.py +14 -0
- sqllocks_shape-0.9.0/src/shape/privacy/release.py +54 -0
- sqllocks_shape-0.9.0/src/shape/profile/__init__.py +57 -0
- sqllocks_shape-0.9.0/src/shape/profile/advanced.py +81 -0
- sqllocks_shape-0.9.0/src/shape/profile/bounded_dependencies.py +67 -0
- sqllocks_shape-0.9.0/src/shape/profile/datetime.py +28 -0
- sqllocks_shape-0.9.0/src/shape/profile/dependence.py +52 -0
- sqllocks_shape-0.9.0/src/shape/profile/dependencies.py +61 -0
- sqllocks_shape-0.9.0/src/shape/profile/error.py +22 -0
- sqllocks_shape-0.9.0/src/shape/profile/numeric.py +104 -0
- sqllocks_shape-0.9.0/src/shape/profile/reference/__init__.py +13 -0
- sqllocks_shape-0.9.0/src/shape/profile/reference/column.py +626 -0
- sqllocks_shape-0.9.0/src/shape/profile/reference/model.py +70 -0
- sqllocks_shape-0.9.0/src/shape/profile/reference/numerics.py +805 -0
- sqllocks_shape-0.9.0/src/shape/profile/reference/profile.py +300 -0
- sqllocks_shape-0.9.0/src/shape/profile/reference/readers.py +152 -0
- sqllocks_shape-0.9.0/src/shape/profile/reference/sources.py +125 -0
- sqllocks_shape-0.9.0/src/shape/profile/reference/table.py +328 -0
- sqllocks_shape-0.9.0/src/shape/profile/semantic_future.py +16 -0
- sqllocks_shape-0.9.0/src/shape/profile/sketches.py +173 -0
- sqllocks_shape-0.9.0/src/shape/profile/temporal.py +12 -0
- sqllocks_shape-0.9.0/src/shape/profile/text.py +37 -0
- sqllocks_shape-0.9.0/src/shape/profile/text_vectorized.py +49 -0
- sqllocks_shape-0.9.0/src/shape/py.typed +0 -0
- sqllocks_shape-0.9.0/src/shape/quality/__init__.py +18 -0
- sqllocks_shape-0.9.0/src/shape/quality/core.py +39 -0
- sqllocks_shape-0.9.0/src/shape/quality/infer.py +21 -0
- sqllocks_shape-0.9.0/src/shape/quality/policy.py +71 -0
- sqllocks_shape-0.9.0/src/shape/query/__init__.py +3 -0
- sqllocks_shape-0.9.0/src/shape/query/core.py +75 -0
- sqllocks_shape-0.9.0/src/shape/registry/__init__.py +2 -0
- sqllocks_shape-0.9.0/src/shape/registry/local.py +104 -0
- sqllocks_shape-0.9.0/src/shape/relations/__init__.py +3 -0
- sqllocks_shape-0.9.0/src/shape/relations/core.py +62 -0
- sqllocks_shape-0.9.0/src/shape/report/__init__.py +7 -0
- sqllocks_shape-0.9.0/src/shape/report/html.py +232 -0
- sqllocks_shape-0.9.0/src/shape/security/__init__.py +87 -0
- sqllocks_shape-0.9.0/src/shape/security/crypto.py +57 -0
- sqllocks_shape-0.9.0/src/shape/security/hardening.py +100 -0
- sqllocks_shape-0.9.0/src/shape/security/labels.py +31 -0
- sqllocks_shape-0.9.0/src/shape/spec/__init__.py +11 -0
- sqllocks_shape-0.9.0/src/shape/spec/capabilities.py +18 -0
- sqllocks_shape-0.9.0/src/shape/spec/io.py +35 -0
- sqllocks_shape-0.9.0/src/shape/spec/migrate.py +13 -0
- sqllocks_shape-0.9.0/src/shape/spec/model.py +58 -0
- sqllocks_shape-0.9.0/src/shape/streaming/__init__.py +107 -0
- sqllocks_shape-0.9.0/src/shape/streaming/aggregate_windows.py +85 -0
- sqllocks_shape-0.9.0/src/shape/streaming/checkpoint.py +38 -0
- sqllocks_shape-0.9.0/src/shape/streaming/core.py +47 -0
- sqllocks_shape-0.9.0/src/shape/streaming/evidence.py +110 -0
- sqllocks_shape-0.9.0/src/shape/streaming/failure.py +20 -0
- sqllocks_shape-0.9.0/src/shape/streaming/full_engine.py +72 -0
- sqllocks_shape-0.9.0/src/shape/streaming/keyed.py +103 -0
- sqllocks_shape-0.9.0/src/shape/streaming/monitor.py +27 -0
- sqllocks_shape-0.9.0/src/shape/streaming/online.py +26 -0
- sqllocks_shape-0.9.0/src/shape/streaming/platinum.py +343 -0
- sqllocks_shape-0.9.0/src/shape/streaming/vectorized.py +51 -0
- sqllocks_shape-0.9.0/src/shape/streaming/windows.py +72 -0
- sqllocks_shape-0.9.0/src/shape/types.py +110 -0
- sqllocks_shape-0.9.0/src/shape/validation/__init__.py +23 -0
- sqllocks_shape-0.9.0/src/shape/validation/adversarial.py +35 -0
- sqllocks_shape-0.9.0/src/shape/validation/conformance.py +24 -0
- sqllocks_shape-0.9.0/src/shape/validation/fuzz.py +26 -0
- sqllocks_shape-0.9.0/src/shape/validation/invariants.py +46 -0
- sqllocks_shape-0.9.0/src/shape/validation/statistics.py +51 -0
- sqllocks_shape-0.9.0/src/shape/validation/suite.py +36 -0
- sqllocks_shape-0.9.0/tests/artifact/test_artifact.py +8 -0
- sqllocks_shape-0.9.0/tests/artifact/test_hardening.py +23 -0
- sqllocks_shape-0.9.0/tests/artifact/test_migration.py +9 -0
- sqllocks_shape-0.9.0/tests/artifact/test_rc_shape_file.py +26 -0
- sqllocks_shape-0.9.0/tests/artifact/test_secure.py +29 -0
- sqllocks_shape-0.9.0/tests/benchmarks/test_vs_spindle_harness.py +146 -0
- sqllocks_shape-0.9.0/tests/capture/test_capture.py +6 -0
- sqllocks_shape-0.9.0/tests/capture/test_late_columns.py +6 -0
- sqllocks_shape-0.9.0/tests/capture/test_vectorized.py +14 -0
- sqllocks_shape-0.9.0/tests/cli/test_cli.py +16 -0
- sqllocks_shape-0.9.0/tests/cli/test_cli_e2e.py +17 -0
- sqllocks_shape-0.9.0/tests/cli/test_five_cli.py +33 -0
- sqllocks_shape-0.9.0/tests/cli/test_product_cli.py +13 -0
- sqllocks_shape-0.9.0/tests/conformance/test_repository_constitution.py +17 -0
- sqllocks_shape-0.9.0/tests/conftest.py +13 -0
- sqllocks_shape-0.9.0/tests/connectors/test_adapters.py +12 -0
- sqllocks_shape-0.9.0/tests/connectors/test_dbapi.py +14 -0
- sqllocks_shape-0.9.0/tests/connectors/test_files.py +12 -0
- sqllocks_shape-0.9.0/tests/connectors/test_qualification.py +63 -0
- sqllocks_shape-0.9.0/tests/connectors/test_registry.py +7 -0
- sqllocks_shape-0.9.0/tests/contracts/test_contracts.py +32 -0
- sqllocks_shape-0.9.0/tests/demo/content/test_demo_data.py +201 -0
- sqllocks_shape-0.9.0/tests/demo/content/test_talk_kit.py +111 -0
- sqllocks_shape-0.9.0/tests/demo/core/conftest.py +45 -0
- sqllocks_shape-0.9.0/tests/demo/core/test_artifact.py +114 -0
- sqllocks_shape-0.9.0/tests/demo/core/test_cli.py +145 -0
- sqllocks_shape-0.9.0/tests/demo/core/test_contract.py +199 -0
- sqllocks_shape-0.9.0/tests/demo/core/test_diff.py +148 -0
- sqllocks_shape-0.9.0/tests/demo/core/test_profile.py +251 -0
- sqllocks_shape-0.9.0/tests/demo/core/test_publish_workflow.py +77 -0
- sqllocks_shape-0.9.0/tests/demo/core/test_report.py +46 -0
- sqllocks_shape-0.9.0/tests/demo/core/test_wheel.py +100 -0
- sqllocks_shape-0.9.0/tests/demo/core/test_wheel_license.py +33 -0
- sqllocks_shape-0.9.0/tests/demo/fabric/conftest.py +47 -0
- sqllocks_shape-0.9.0/tests/demo/fabric/fabric_helpers.py +165 -0
- sqllocks_shape-0.9.0/tests/demo/fabric/requirements.txt +13 -0
- sqllocks_shape-0.9.0/tests/demo/fabric/test_notebooks.py +278 -0
- sqllocks_shape-0.9.0/tests/demo/fabric/test_pipelines.py +307 -0
- sqllocks_shape-0.9.0/tests/demo/fabric/test_udf.py +414 -0
- sqllocks_shape-0.9.0/tests/diff/test_diff.py +6 -0
- sqllocks_shape-0.9.0/tests/drift/test_drift.py +8 -0
- sqllocks_shape-0.9.0/tests/drift/test_drift_gate_new.py +8 -0
- sqllocks_shape-0.9.0/tests/generation/test_address_partition_weights.py +37 -0
- sqllocks_shape-0.9.0/tests/generation/test_certificate.py +22 -0
- sqllocks_shape-0.9.0/tests/generation/test_distribution_fidelity.py +10 -0
- sqllocks_shape-0.9.0/tests/generation/test_fidelity_categorical.py +11 -0
- sqllocks_shape-0.9.0/tests/generation/test_fidelity_complete.py +36 -0
- sqllocks_shape-0.9.0/tests/generation/test_generation.py +15 -0
- sqllocks_shape-0.9.0/tests/generation/test_levels_evolution.py +24 -0
- sqllocks_shape-0.9.0/tests/generation/test_random_access.py +25 -0
- sqllocks_shape-0.9.0/tests/generation/test_relational.py +19 -0
- sqllocks_shape-0.9.0/tests/generation/test_shape_compiler.py +54 -0
- sqllocks_shape-0.9.0/tests/generation/test_strategies.py +36 -0
- sqllocks_shape-0.9.0/tests/generation/test_timeline.py +30 -0
- sqllocks_shape-0.9.0/tests/generation/test_vectorized_generation.py +55 -0
- sqllocks_shape-0.9.0/tests/geospatial/test_geo.py +7 -0
- sqllocks_shape-0.9.0/tests/kernel/test_batches.py +28 -0
- sqllocks_shape-0.9.0/tests/location/test_location.py +55 -0
- sqllocks_shape-0.9.0/tests/location/test_reference.py +8 -0
- sqllocks_shape-0.9.0/tests/model/test_model.py +34 -0
- sqllocks_shape-0.9.0/tests/packs/test_address.py +34 -0
- sqllocks_shape-0.9.0/tests/packs/test_domain_sdk.py +30 -0
- sqllocks_shape-0.9.0/tests/packs/test_domains.py +29 -0
- sqllocks_shape-0.9.0/tests/packs/test_person.py +11 -0
- sqllocks_shape-0.9.0/tests/packs/test_sdk.py +6 -0
- sqllocks_shape-0.9.0/tests/packs/test_verify.py +13 -0
- sqllocks_shape-0.9.0/tests/platform12/test_features_05_08.py +12 -0
- sqllocks_shape-0.9.0/tests/platform12/test_hardening.py +9 -0
- sqllocks_shape-0.9.0/tests/plugins/test_plugins.py +11 -0
- sqllocks_shape-0.9.0/tests/plugins/test_runtime.py +27 -0
- sqllocks_shape-0.9.0/tests/privacy/test_advanced.py +17 -0
- sqllocks_shape-0.9.0/tests/privacy/test_classification.py +8 -0
- sqllocks_shape-0.9.0/tests/privacy/test_detect.py +12 -0
- sqllocks_shape-0.9.0/tests/privacy/test_measure.py +13 -0
- sqllocks_shape-0.9.0/tests/privacy/test_propagate.py +7 -0
- sqllocks_shape-0.9.0/tests/privacy/test_release_controls.py +8 -0
- sqllocks_shape-0.9.0/tests/privacy/test_release_policy_new.py +74 -0
- sqllocks_shape-0.9.0/tests/profile/test_advanced.py +13 -0
- sqllocks_shape-0.9.0/tests/profile/test_bounded_dependencies.py +12 -0
- sqllocks_shape-0.9.0/tests/profile/test_dependence_temporal.py +10 -0
- sqllocks_shape-0.9.0/tests/profile/test_dependencies.py +13 -0
- sqllocks_shape-0.9.0/tests/profile/test_error_models.py +5 -0
- sqllocks_shape-0.9.0/tests/profile/test_merge_invariants.py +22 -0
- sqllocks_shape-0.9.0/tests/profile/test_merge_properties.py +24 -0
- sqllocks_shape-0.9.0/tests/profile/test_numeric.py +36 -0
- sqllocks_shape-0.9.0/tests/quality/test_infer.py +8 -0
- sqllocks_shape-0.9.0/tests/quality/test_policy.py +7 -0
- sqllocks_shape-0.9.0/tests/query/test_query.py +21 -0
- sqllocks_shape-0.9.0/tests/registry/test_local_registry.py +56 -0
- sqllocks_shape-0.9.0/tests/relations/test_covariance.py +8 -0
- sqllocks_shape-0.9.0/tests/release/test_rc1_hardening.py +49 -0
- sqllocks_shape-0.9.0/tests/security/test_crypto.py +27 -0
- sqllocks_shape-0.9.0/tests/security/test_fuzz_boundaries.py +47 -0
- sqllocks_shape-0.9.0/tests/security/test_ga_security.py +112 -0
- sqllocks_shape-0.9.0/tests/security/test_ga_security_extended.py +128 -0
- sqllocks_shape-0.9.0/tests/security/test_rc1_leakage.py +15 -0
- sqllocks_shape-0.9.0/tests/security/test_sensitivity.py +13 -0
- sqllocks_shape-0.9.0/tests/security/test_zero_network.py +16 -0
- sqllocks_shape-0.9.0/tests/spec/test_capabilities.py +8 -0
- sqllocks_shape-0.9.0/tests/spec/test_ga_freeze.py +42 -0
- sqllocks_shape-0.9.0/tests/spec/test_io.py +11 -0
- sqllocks_shape-0.9.0/tests/spec/test_shape_contract.py +8 -0
- sqllocks_shape-0.9.0/tests/streaming/test_checkpoint_store.py +10 -0
- sqllocks_shape-0.9.0/tests/streaming/test_failure_replay.py +13 -0
- sqllocks_shape-0.9.0/tests/streaming/test_monitor.py +8 -0
- sqllocks_shape-0.9.0/tests/streaming/test_online.py +9 -0
- sqllocks_shape-0.9.0/tests/streaming/test_rc1_evidence.py +72 -0
- sqllocks_shape-0.9.0/tests/streaming/test_rq6.py +32 -0
- sqllocks_shape-0.9.0/tests/streaming/test_rq7.py +21 -0
- sqllocks_shape-0.9.0/tests/streaming/test_rq8.py +20 -0
- sqllocks_shape-0.9.0/tests/streaming/test_windows.py +13 -0
- sqllocks_shape-0.9.0/tests/test_adversarial_invariants.py +28 -0
- sqllocks_shape-0.9.0/tests/test_removed_modules.py +45 -0
- sqllocks_shape-0.9.0/tests/test_streaming_async.py +14 -0
- sqllocks_shape-0.9.0/tests/torture/test_all_modules.py +30 -0
- sqllocks_shape-0.9.0/tests/torture/test_cross_feature_torture.py +105 -0
- sqllocks_shape-0.9.0/tests/types/test_types.py +31 -0
- sqllocks_shape-0.9.0/tests/validation/test_adversarial.py +5 -0
- sqllocks_shape-0.9.0/tests/validation/test_fuzz_artifact.py +14 -0
- sqllocks_shape-0.9.0/tests/validation/test_suite.py +6 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Shape core requires no credentials or network service.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on: [push, pull_request]
|
|
3
|
+
permissions: {contents: read}
|
|
4
|
+
jobs:
|
|
5
|
+
test:
|
|
6
|
+
# T-06: the full Python 3.11-3.14 matrix on Linux; 3.11 and 3.14 on macOS and Windows.
|
|
7
|
+
strategy:
|
|
8
|
+
fail-fast: false
|
|
9
|
+
matrix:
|
|
10
|
+
os: [ubuntu-latest]
|
|
11
|
+
python: ['3.11', '3.12', '3.13', '3.14']
|
|
12
|
+
include:
|
|
13
|
+
- {os: macos-latest, python: '3.11'}
|
|
14
|
+
- {os: macos-latest, python: '3.14'}
|
|
15
|
+
- {os: windows-latest, python: '3.11'}
|
|
16
|
+
- {os: windows-latest, python: '3.14'}
|
|
17
|
+
runs-on: ${{ matrix.os }}
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
- uses: actions/setup-python@v5
|
|
21
|
+
with: {python-version: '${{ matrix.python }}', allow-prereleases: true}
|
|
22
|
+
- run: python -m pip install -U pip
|
|
23
|
+
- run: pip install -e '.[dev,streaming]'
|
|
24
|
+
# T-27 scope: src tests plugins benchmarks/vs_spindle rust (only the paths that exist yet).
|
|
25
|
+
- run: ruff check src tests benchmarks/vs_spindle
|
|
26
|
+
- run: ruff format --check src tests benchmarks/vs_spindle
|
|
27
|
+
# [tool.mypy] targets python_version 3.11. On 3.12+ legs pip installs a numpy whose
|
|
28
|
+
# stubs use 3.12-only syntax (`type` statements), which mypy rejects under a 3.11
|
|
29
|
+
# target, so the type check runs on the 3.11 legs (every OS).
|
|
30
|
+
- if: matrix.python == '3.11'
|
|
31
|
+
run: mypy
|
|
32
|
+
- run: python -m compileall -q src/shape
|
|
33
|
+
# The Fabric demo tests need Java, PySpark and unixODBC, and the demo content tests need
|
|
34
|
+
# the pinned Spindle checkout; both run in the fabric-demo job below.
|
|
35
|
+
# --cov-fail-under is the measured coverage (86.55% on P0-06), rounded down.
|
|
36
|
+
- run: >-
|
|
37
|
+
python -m pytest -q -m "not emulator and not live"
|
|
38
|
+
--ignore=tests/demo/fabric --ignore=tests/demo/content
|
|
39
|
+
--cov=shape --cov-fail-under=86
|
|
40
|
+
audit:
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
steps:
|
|
43
|
+
- uses: actions/checkout@v4
|
|
44
|
+
- uses: actions/setup-python@v5
|
|
45
|
+
with: {python-version: '3.13'}
|
|
46
|
+
- run: python -m pip install -U pip
|
|
47
|
+
- run: pip install -e '.[dev,streaming]'
|
|
48
|
+
- run: pip-audit --skip-editable
|
|
49
|
+
fabric-demo:
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
steps:
|
|
52
|
+
- uses: actions/checkout@v4
|
|
53
|
+
- uses: actions/setup-python@v5
|
|
54
|
+
with: {python-version: '3.11'}
|
|
55
|
+
- uses: actions/setup-java@v4
|
|
56
|
+
with: {distribution: temurin, java-version: '17'}
|
|
57
|
+
- run: sudo apt-get update -q && sudo apt-get install -y -q unixodbc
|
|
58
|
+
- run: python -m pip install -U pip
|
|
59
|
+
- run: pip install -e '.[dev]' -r tests/demo/fabric/requirements.txt
|
|
60
|
+
# demo/make_data.py reads Spindle's schema and reference data (plan section 1.2); read only.
|
|
61
|
+
- name: Pinned Spindle checkout
|
|
62
|
+
run: |
|
|
63
|
+
git init -q "$RUNNER_TEMP/spindle"
|
|
64
|
+
git -C "$RUNNER_TEMP/spindle" fetch -q --depth 1 https://github.com/sqllocks/spindle 422e78df2267e73bb2fa976267e48cb437861e2f
|
|
65
|
+
git -C "$RUNNER_TEMP/spindle" checkout -q FETCH_HEAD
|
|
66
|
+
echo "SPINDLE_ROOT=$RUNNER_TEMP/spindle" >> "$GITHUB_ENV"
|
|
67
|
+
- run: python -m pytest -q tests/demo/fabric tests/demo/content
|
|
68
|
+
bench-quick:
|
|
69
|
+
# Verifiers, then the quick benchmark (D1, D2, retail small+medium; 3 runs) against the
|
|
70
|
+
# pinned Spindle. On a private repository the standard runner has 2 vCPUs, so ratios are
|
|
71
|
+
# informational until the repository is public (O-05).
|
|
72
|
+
runs-on: ubuntu-latest
|
|
73
|
+
timeout-minutes: 90
|
|
74
|
+
env: {BENCH_OUT_DIR: "${{ github.workspace }}/bench-out"}
|
|
75
|
+
steps:
|
|
76
|
+
- uses: actions/checkout@v4
|
|
77
|
+
- uses: actions/setup-python@v5
|
|
78
|
+
with: {python-version: '3.11'}
|
|
79
|
+
- name: Pinned Spindle baseline and venv (plan section 1.2)
|
|
80
|
+
run: source scripts/env.sh && bash benchmarks/vs_spindle/setup_spindle.sh
|
|
81
|
+
- name: Shape venv (pyarrow pinned like the Spindle venv)
|
|
82
|
+
run: |
|
|
83
|
+
source scripts/env.sh
|
|
84
|
+
python -m venv "$SHAPE_VENV"
|
|
85
|
+
"$SHAPE_VENV/bin/pip" install -U pip
|
|
86
|
+
"$SHAPE_VENV/bin/pip" install -e '.[dev]' 'pyarrow==25.0.1'
|
|
87
|
+
- run: source scripts/env.sh && python benchmarks/vs_spindle/check_coverage.py
|
|
88
|
+
- run: source scripts/env.sh && python benchmarks/vs_spindle/run.py --quick --out "$BENCH_OUT_DIR/results.json"
|
|
89
|
+
- uses: actions/upload-artifact@v4
|
|
90
|
+
if: always()
|
|
91
|
+
with:
|
|
92
|
+
name: benchmark-results-quick
|
|
93
|
+
path: |
|
|
94
|
+
${{ github.workspace }}/bench-out/results.json
|
|
95
|
+
${{ github.workspace }}/bench-out/verify/
|
|
96
|
+
build:
|
|
97
|
+
runs-on: ubuntu-latest
|
|
98
|
+
steps:
|
|
99
|
+
- uses: actions/checkout@v4
|
|
100
|
+
- uses: actions/setup-python@v5
|
|
101
|
+
with: {python-version: '3.13'}
|
|
102
|
+
- run: pip install build twine pip-audit
|
|
103
|
+
- run: python -m pip install --upgrade pip
|
|
104
|
+
- run: pip install .
|
|
105
|
+
- run: python -m build
|
|
106
|
+
- run: python -m twine check dist/*
|
|
107
|
+
- run: pip-audit
|
|
108
|
+
- uses: actions/upload-artifact@v4
|
|
109
|
+
with: {name: distributions, path: dist/*}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: Nightly
|
|
2
|
+
on:
|
|
3
|
+
schedule: [{cron: '17 3 * * *'}]
|
|
4
|
+
workflow_dispatch: {}
|
|
5
|
+
permissions: {contents: read}
|
|
6
|
+
jobs:
|
|
7
|
+
benchmarks-full:
|
|
8
|
+
# Every workload of plan section 3.4 (5 runs each): verifiers first, then timings.
|
|
9
|
+
# Timings are ratios measured in this one job (T-19). A public repository gets 4-vCPU
|
|
10
|
+
# standard runners; on a private repository use a 4-vCPU larger runner (O-05).
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
timeout-minutes: 360
|
|
13
|
+
env: {BENCH_OUT_DIR: "${{ github.workspace }}/bench-out"}
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with: {python-version: '3.11'}
|
|
18
|
+
- name: Pinned Spindle baseline and venv (plan section 1.2)
|
|
19
|
+
run: source scripts/env.sh && bash benchmarks/vs_spindle/setup_spindle.sh
|
|
20
|
+
- name: Shape venv (pyarrow pinned like the Spindle venv, so timings share one pyarrow)
|
|
21
|
+
run: |
|
|
22
|
+
source scripts/env.sh
|
|
23
|
+
python -m venv "$SHAPE_VENV"
|
|
24
|
+
"$SHAPE_VENV/bin/pip" install -U pip
|
|
25
|
+
"$SHAPE_VENV/bin/pip" install -e '.[dev]' 'pyarrow==25.0.1'
|
|
26
|
+
- run: source scripts/env.sh && python benchmarks/vs_spindle/check_coverage.py
|
|
27
|
+
- run: source scripts/env.sh && python benchmarks/vs_spindle/run.py --full
|
|
28
|
+
- uses: actions/upload-artifact@v4
|
|
29
|
+
if: always()
|
|
30
|
+
with:
|
|
31
|
+
name: benchmark-results-full
|
|
32
|
+
path: |
|
|
33
|
+
benchmarks/vs_spindle/results.json
|
|
34
|
+
${{ github.workspace }}/bench-out/verify/
|
|
35
|
+
${{ github.workspace }}/bench-out/spindle_freeze.txt
|
|
36
|
+
emulator-compose:
|
|
37
|
+
# The emulator-backed test jobs (Kafka, Event Hubs + Azurite, SQL Server) arrive with the
|
|
38
|
+
# work packages that own those connectors; until then, keep the compose file valid.
|
|
39
|
+
runs-on: ubuntu-latest
|
|
40
|
+
steps:
|
|
41
|
+
- uses: actions/checkout@v4
|
|
42
|
+
- run: docker compose -f ci/emulators/docker-compose.yml config --quiet
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Early-access publish of the pure-Python wheel and an sdist (plan DM-03b).
|
|
2
|
+
#
|
|
3
|
+
# Trusted publishing only: no API tokens and no passwords. The PyPI (and TestPyPI) project
|
|
4
|
+
# "sqllocks-shape" must have a trusted publisher registered for this repository, workflow file
|
|
5
|
+
# "publish.yml" and environment "pypi" (TestPyPI: environment "testpypi").
|
|
6
|
+
#
|
|
7
|
+
# Owner triggers it: Actions > "Publish" > Run workflow, repository = testpypi first, then pypi.
|
|
8
|
+
# Pushing a tag "v<version>" publishes to PyPI (the tag must equal the package version).
|
|
9
|
+
name: Publish
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
inputs:
|
|
14
|
+
repository:
|
|
15
|
+
description: "Where to publish"
|
|
16
|
+
required: true
|
|
17
|
+
default: testpypi
|
|
18
|
+
type: choice
|
|
19
|
+
options:
|
|
20
|
+
- testpypi
|
|
21
|
+
- pypi
|
|
22
|
+
push:
|
|
23
|
+
tags:
|
|
24
|
+
- "v*"
|
|
25
|
+
|
|
26
|
+
permissions:
|
|
27
|
+
contents: read
|
|
28
|
+
|
|
29
|
+
jobs:
|
|
30
|
+
build:
|
|
31
|
+
name: Build and test the wheel and sdist
|
|
32
|
+
runs-on: ubuntu-latest
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
- uses: actions/setup-python@v5
|
|
36
|
+
with:
|
|
37
|
+
python-version: "3.11"
|
|
38
|
+
- run: python -m pip install --upgrade pip build twine
|
|
39
|
+
- name: Tag must match the package version
|
|
40
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
41
|
+
run: |
|
|
42
|
+
version="$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")"
|
|
43
|
+
test "v${version}" = "${GITHUB_REF_NAME}" || {
|
|
44
|
+
echo "tag ${GITHUB_REF_NAME} does not match version ${version}"; exit 1; }
|
|
45
|
+
- name: README must say this is early access
|
|
46
|
+
run: grep -qi "early access" README.md
|
|
47
|
+
- name: Build the pure wheel, install it in a clean venv and run tests/demo/core
|
|
48
|
+
run: python scripts/build_pure_wheel.py --verify --python python3.11
|
|
49
|
+
- name: Build the sdist
|
|
50
|
+
run: python -m build --sdist
|
|
51
|
+
- name: twine check
|
|
52
|
+
run: python -m twine check dist/*
|
|
53
|
+
- run: ls -l dist
|
|
54
|
+
- uses: actions/upload-artifact@v4
|
|
55
|
+
with:
|
|
56
|
+
name: dist
|
|
57
|
+
path: dist/*
|
|
58
|
+
if-no-files-found: error
|
|
59
|
+
|
|
60
|
+
publish:
|
|
61
|
+
name: Publish to ${{ (github.event_name == 'workflow_dispatch' && inputs.repository == 'testpypi') && 'TestPyPI' || 'PyPI' }}
|
|
62
|
+
needs: build
|
|
63
|
+
runs-on: ubuntu-latest
|
|
64
|
+
environment: ${{ (github.event_name == 'workflow_dispatch' && inputs.repository == 'testpypi') && 'testpypi' || 'pypi' }}
|
|
65
|
+
permissions:
|
|
66
|
+
id-token: write
|
|
67
|
+
contents: read
|
|
68
|
+
steps:
|
|
69
|
+
- uses: actions/download-artifact@v4
|
|
70
|
+
with:
|
|
71
|
+
name: dist
|
|
72
|
+
path: dist
|
|
73
|
+
- name: Publish to TestPyPI
|
|
74
|
+
if: github.event_name == 'workflow_dispatch' && inputs.repository == 'testpypi'
|
|
75
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
76
|
+
with:
|
|
77
|
+
repository-url: https://test.pypi.org/legacy/
|
|
78
|
+
- name: Publish to PyPI
|
|
79
|
+
if: github.event_name != 'workflow_dispatch' || inputs.repository == 'pypi'
|
|
80
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: Release candidate
|
|
2
|
+
on: {workflow_dispatch: {}}
|
|
3
|
+
permissions: {contents: read, id-token: write}
|
|
4
|
+
jobs:
|
|
5
|
+
release:
|
|
6
|
+
runs-on: ubuntu-latest
|
|
7
|
+
steps:
|
|
8
|
+
- uses: actions/checkout@v4
|
|
9
|
+
- uses: actions/setup-python@v5
|
|
10
|
+
with: {python-version: '3.13'}
|
|
11
|
+
- run: python -m pip install --upgrade pip
|
|
12
|
+
- run: pip install build twine pip-audit cyclonedx-bom
|
|
13
|
+
- run: pip install '.[dev]'
|
|
14
|
+
- run: make check
|
|
15
|
+
- run: python -m build
|
|
16
|
+
- run: python -m twine check dist/*
|
|
17
|
+
- run: pip-audit
|
|
18
|
+
- run: cyclonedx-py environment -o sbom.json
|
|
19
|
+
- uses: actions/upload-artifact@v4
|
|
20
|
+
with:
|
|
21
|
+
name: release-candidate
|
|
22
|
+
path: |
|
|
23
|
+
dist/*
|
|
24
|
+
sbom.json
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
name: Security
|
|
2
|
+
on: [push, pull_request]
|
|
3
|
+
permissions: {contents: read}
|
|
4
|
+
jobs:
|
|
5
|
+
security:
|
|
6
|
+
runs-on: ubuntu-latest
|
|
7
|
+
steps:
|
|
8
|
+
- uses: actions/checkout@v4
|
|
9
|
+
- uses: actions/setup-python@v5
|
|
10
|
+
with: {python-version: "3.12"}
|
|
11
|
+
- run: python -m pip install --upgrade pip
|
|
12
|
+
- run: python -m pip install -e ".[dev,streaming]"
|
|
13
|
+
- run: pip-audit --skip-editable
|
|
14
|
+
- run: bandit -q -r src -ll
|
|
15
|
+
- run: python scripts/check_secrets.py
|
|
16
|
+
# The Fabric demo tests need extra packages and run in ci.yml's fabric-demo job.
|
|
17
|
+
- run: pytest -m security --ignore=tests/demo/fabric
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
.venv/
|
|
4
|
+
.pytest_cache/
|
|
5
|
+
.mypy_cache/
|
|
6
|
+
.ruff_cache/
|
|
7
|
+
dist/
|
|
8
|
+
build/
|
|
9
|
+
*.egg-info/
|
|
10
|
+
.env
|
|
11
|
+
.env.*
|
|
12
|
+
!.env.example
|
|
13
|
+
*.pem
|
|
14
|
+
*.key
|
|
15
|
+
*.p12
|
|
16
|
+
*.pfx
|
|
17
|
+
.hypothesis/
|
|
18
|
+
.coverage
|
|
19
|
+
htmlcov/
|
|
20
|
+
.DS_Store
|
|
21
|
+
Thumbs.db
|
|
22
|
+
*.swp
|
|
23
|
+
|
|
24
|
+
# benchmark scratch output in CI
|
|
25
|
+
/bench-out/
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Shape is in **early access**. Profiling is available now; data generation and
|
|
4
|
+
pipeline integration are in progress. See `docs/plans/COMPLETION_PLAN.md`.
|
|
5
|
+
|
|
6
|
+
## Unreleased
|
|
7
|
+
|
|
8
|
+
- Relicensed under the MIT license.
|
|
9
|
+
- Repository cleaned up for public release: removed internal milestone and
|
|
10
|
+
qualification records.
|
|
11
|
+
- README and changelog rewritten to describe the current state.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This repository is being rebuilt against a fixed, fully decided plan:
|
|
4
|
+
**`docs/plans/COMPLETION_PLAN.md`**.
|
|
5
|
+
|
|
6
|
+
Before doing anything in this repo:
|
|
7
|
+
|
|
8
|
+
1. Read §0 (Builder guide), §1 (Environment setup) and §6 (Execution rules) of the
|
|
9
|
+
plan, in full.
|
|
10
|
+
2. Find the next work package in §11 (Status tracker). It is the first `todo` whose
|
|
11
|
+
`Depends` are all `done`.
|
|
12
|
+
3. Build exactly that work package to its acceptance criteria in §7. Then update the
|
|
13
|
+
tracker, commit with the work-package ID as the message prefix, and push.
|
|
14
|
+
|
|
15
|
+
**48-hour Fabric demo lanes:** if your session prompt names a demo lane (L1, L2 or
|
|
16
|
+
L3), follow §12 of the plan instead of step 2. Edit only the paths that §12.5 gives
|
|
17
|
+
your lane, and record completion in `docs/plans/demo_status/<WP>.md`, never in the
|
|
18
|
+
plan's tables.
|
|
19
|
+
|
|
20
|
+
Rules that override everything else:
|
|
21
|
+
|
|
22
|
+
- Every decision in §2 (D-xx and T-xx), every gate and every tolerance is fixed. Do
|
|
23
|
+
not change one; escalate instead (§0.4).
|
|
24
|
+
- Never lower a gate, loosen a tolerance, skip or xfail a test, or fabricate
|
|
25
|
+
benchmark results.
|
|
26
|
+
- Equivalence verification comes before any timing (§6.4).
|
|
27
|
+
- Never modify the pinned Spindle checkout (`$SPINDLE_ROOT`).
|
|
28
|
+
- Never report something as done without running its checks in this session.
|
|
29
|
+
- Shell state does not persist between tool calls. Start every command that uses the
|
|
30
|
+
plan's environment variables with `source scripts/env.sh &&`, run from the repo
|
|
31
|
+
root. P0-00 creates that file; until then, use the §1 block from the plan.
|
|
32
|
+
- Performance numbers count only after the equivalence verifier for that workload
|
|
33
|
+
exits 0.
|
|
34
|
+
|
|
35
|
+
Useful commands (once P0-06 and P0-07 are done):
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
make check # lint, format, types, tests (T-27 scope)
|
|
39
|
+
pytest -m "not emulator and not live" # local test run
|
|
40
|
+
source scripts/env.sh && python benchmarks/vs_spindle/run.py --quick # verifiers + benchmarks vs pinned Spindle
|
|
41
|
+
```
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Changes should preserve deterministic behavior, bounded-memory semantics where promised, sensitivity/provenance propagation and fail-closed handling of ambiguous or unsafe input. Add tests and requirement traceability for new normative behavior. Avoid mandatory network dependencies in core.
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
# Governance
|
|
2
|
+
|
|
3
|
+
Shape uses specification-first governance. Public behavior is defined by versioned specifications and conformance tests, not incidental Python implementation details. Breaking changes require a major specification version and migration path. Security fixes may tighten previously permissive behavior.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026 SQLLocks (Jonathan Stewart)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
PYTHON ?= python
|
|
2
|
+
.PHONY: bootstrap check test security
|
|
3
|
+
bootstrap:
|
|
4
|
+
$(PYTHON) -m pip install -e ".[dev]"
|
|
5
|
+
# Same commands as the `test` job in .github/workflows/ci.yml (T-27 scope: only paths that exist).
|
|
6
|
+
check:
|
|
7
|
+
ruff check src tests benchmarks/vs_spindle
|
|
8
|
+
ruff format --check src tests benchmarks/vs_spindle
|
|
9
|
+
mypy
|
|
10
|
+
$(PYTHON) -m compileall -q src/shape
|
|
11
|
+
$(PYTHON) scripts/check_requirements.py
|
|
12
|
+
$(PYTHON) scripts/check_secrets.py
|
|
13
|
+
pytest -q -m "not emulator and not live" --ignore=tests/demo/fabric --ignore=tests/demo/content --cov=shape --cov-fail-under=86
|
|
14
|
+
test:
|
|
15
|
+
pytest -m "not emulator and not live"
|
|
16
|
+
security:
|
|
17
|
+
pytest -m security
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: sqllocks-shape
|
|
3
|
+
Version: 0.9.0
|
|
4
|
+
Summary: Shape by SQLLocks — Shape as Code: profile, check and compare how your data behaves. Early access.
|
|
5
|
+
Project-URL: Homepage, https://github.com/sqllocks/shape
|
|
6
|
+
Project-URL: Repository, https://github.com/sqllocks/shape
|
|
7
|
+
Project-URL: Issues, https://github.com/sqllocks/shape/issues
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
License-File: THIRD_PARTY_NOTICES.md
|
|
11
|
+
Requires-Python: >=3.11
|
|
12
|
+
Requires-Dist: numpy<3,>=2.0
|
|
13
|
+
Requires-Dist: pyarrow>=14.0.1
|
|
14
|
+
Provides-Extra: delta
|
|
15
|
+
Requires-Dist: deltalake>=0.17; extra == 'delta'
|
|
16
|
+
Provides-Extra: dev
|
|
17
|
+
Requires-Dist: bandit>=1.8; extra == 'dev'
|
|
18
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
19
|
+
Requires-Dist: cryptography<51,>=50; extra == 'dev'
|
|
20
|
+
Requires-Dist: deltalake>=0.17; extra == 'dev'
|
|
21
|
+
Requires-Dist: hypothesis>=6.115; extra == 'dev'
|
|
22
|
+
Requires-Dist: import-linter>=2; extra == 'dev'
|
|
23
|
+
Requires-Dist: maturin<2,>=1.15; extra == 'dev'
|
|
24
|
+
Requires-Dist: mypy>=1.13; extra == 'dev'
|
|
25
|
+
Requires-Dist: pandas>=2; extra == 'dev'
|
|
26
|
+
Requires-Dist: pip-audit>=2.7; extra == 'dev'
|
|
27
|
+
Requires-Dist: py-spy>=0.4; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest-cov>=6; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=8.3; extra == 'dev'
|
|
30
|
+
Requires-Dist: pyyaml>=6; extra == 'dev'
|
|
31
|
+
Requires-Dist: ruff>=0.8; extra == 'dev'
|
|
32
|
+
Requires-Dist: sqlglot>=25; extra == 'dev'
|
|
33
|
+
Requires-Dist: twine>=5; extra == 'dev'
|
|
34
|
+
Requires-Dist: vulture>=2.11; extra == 'dev'
|
|
35
|
+
Requires-Dist: xxhash>=3.5; extra == 'dev'
|
|
36
|
+
Provides-Extra: eventhubs
|
|
37
|
+
Requires-Dist: azure-eventhub<6,>=5.12; extra == 'eventhubs'
|
|
38
|
+
Provides-Extra: kafka
|
|
39
|
+
Requires-Dist: confluent-kafka<4,>=2.5; extra == 'kafka'
|
|
40
|
+
Provides-Extra: pandas
|
|
41
|
+
Requires-Dist: pandas>=2; extra == 'pandas'
|
|
42
|
+
Provides-Extra: sign
|
|
43
|
+
Requires-Dist: cryptography<51,>=50; extra == 'sign'
|
|
44
|
+
Provides-Extra: streaming
|
|
45
|
+
Requires-Dist: azure-eventhub<6,>=5.12; extra == 'streaming'
|
|
46
|
+
Requires-Dist: confluent-kafka<4,>=2.5; extra == 'streaming'
|
|
47
|
+
Provides-Extra: yaml
|
|
48
|
+
Requires-Dist: pyyaml>=6; extra == 'yaml'
|
|
49
|
+
Description-Content-Type: text/markdown
|
|
50
|
+
|
|
51
|
+
# Shape
|
|
52
|
+
|
|
53
|
+
[](LICENSE)
|
|
54
|
+
|
|
55
|
+
**Shape by SQLLocks** — Shape as Code: a portable, executable description of how
|
|
56
|
+
data behaves, not merely its schema.
|
|
57
|
+
|
|
58
|
+
> **Early access.** Profiling is available now; data generation and pipeline
|
|
59
|
+
> integration are in progress. See `docs/plans/COMPLETION_PLAN.md`.
|
|
60
|
+
|
|
61
|
+
Install with `pip install sqllocks-shape`. Python imports use `import shape`, the
|
|
62
|
+
command is `shape`, and artifacts use the `.shape` extension.
|
|
63
|
+
|
|
64
|
+
## Quick start
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
import shape
|
|
68
|
+
|
|
69
|
+
p = shape.profile("customers.csv") # also: Parquet, JSONL, Delta tables, pandas, pyarrow
|
|
70
|
+
shape.save(p, "customers.shape")
|
|
71
|
+
print(p.summary()) # small JSON-safe summary per column
|
|
72
|
+
|
|
73
|
+
result = shape.check(p, {"columns": {"customer_id": {"unique": True, "nullable": False}}})
|
|
74
|
+
print(result.passed, result.violations)
|
|
75
|
+
|
|
76
|
+
drift = shape.diff(shape.load("customers.shape"), shape.profile("customers_next.csv"))
|
|
77
|
+
print(drift.drifted, drift.changes)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
shape profile customers.csv -o customers.shape --html report.html --json summary.json
|
|
82
|
+
shape check customers.shape contract.json # exit code 1 if the contract fails
|
|
83
|
+
shape diff customers.shape customers_next.shape --fail-on-drift
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## What a `.shape` file contains
|
|
87
|
+
|
|
88
|
+
A profile keeps real values from your data, as Spindle's profiler does: up to the 500
|
|
89
|
+
most frequent values per column with their counts, and each column's minimum and maximum.
|
|
90
|
+
Treat a `.shape` file, its HTML report and its JSON summary as you would the source data,
|
|
91
|
+
and don't share one from a sensitive table. A privacy-safe profile, with rare values
|
|
92
|
+
suppressed, is planned.
|
|
93
|
+
|
|
94
|
+
## Design principles
|
|
95
|
+
|
|
96
|
+
- evidence carries provenance and algorithm parameters
|
|
97
|
+
- deterministic generation and replay
|
|
98
|
+
- offline by default: no network access or cloud service is required
|
|
99
|
+
- `.shape` readers fail closed on unsafe or corrupt containers
|
|
100
|
+
|
|
101
|
+
See `docs/PRODUCT_ARCHITECTURE.md` and `docs/specs/`.
|
|
102
|
+
|
|
103
|
+
## License
|
|
104
|
+
|
|
105
|
+
MIT. See `LICENSE` and `THIRD_PARTY_NOTICES.md`.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Shape
|
|
2
|
+
|
|
3
|
+
[](LICENSE)
|
|
4
|
+
|
|
5
|
+
**Shape by SQLLocks** — Shape as Code: a portable, executable description of how
|
|
6
|
+
data behaves, not merely its schema.
|
|
7
|
+
|
|
8
|
+
> **Early access.** Profiling is available now; data generation and pipeline
|
|
9
|
+
> integration are in progress. See `docs/plans/COMPLETION_PLAN.md`.
|
|
10
|
+
|
|
11
|
+
Install with `pip install sqllocks-shape`. Python imports use `import shape`, the
|
|
12
|
+
command is `shape`, and artifacts use the `.shape` extension.
|
|
13
|
+
|
|
14
|
+
## Quick start
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
import shape
|
|
18
|
+
|
|
19
|
+
p = shape.profile("customers.csv") # also: Parquet, JSONL, Delta tables, pandas, pyarrow
|
|
20
|
+
shape.save(p, "customers.shape")
|
|
21
|
+
print(p.summary()) # small JSON-safe summary per column
|
|
22
|
+
|
|
23
|
+
result = shape.check(p, {"columns": {"customer_id": {"unique": True, "nullable": False}}})
|
|
24
|
+
print(result.passed, result.violations)
|
|
25
|
+
|
|
26
|
+
drift = shape.diff(shape.load("customers.shape"), shape.profile("customers_next.csv"))
|
|
27
|
+
print(drift.drifted, drift.changes)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
shape profile customers.csv -o customers.shape --html report.html --json summary.json
|
|
32
|
+
shape check customers.shape contract.json # exit code 1 if the contract fails
|
|
33
|
+
shape diff customers.shape customers_next.shape --fail-on-drift
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## What a `.shape` file contains
|
|
37
|
+
|
|
38
|
+
A profile keeps real values from your data, as Spindle's profiler does: up to the 500
|
|
39
|
+
most frequent values per column with their counts, and each column's minimum and maximum.
|
|
40
|
+
Treat a `.shape` file, its HTML report and its JSON summary as you would the source data,
|
|
41
|
+
and don't share one from a sensitive table. A privacy-safe profile, with rare values
|
|
42
|
+
suppressed, is planned.
|
|
43
|
+
|
|
44
|
+
## Design principles
|
|
45
|
+
|
|
46
|
+
- evidence carries provenance and algorithm parameters
|
|
47
|
+
- deterministic generation and replay
|
|
48
|
+
- offline by default: no network access or cloud service is required
|
|
49
|
+
- `.shape` readers fail closed on unsafe or corrupt containers
|
|
50
|
+
|
|
51
|
+
See `docs/PRODUCT_ARCHITECTURE.md` and `docs/specs/`.
|
|
52
|
+
|
|
53
|
+
## License
|
|
54
|
+
|
|
55
|
+
MIT. See `LICENSE` and `THIRD_PARTY_NOTICES.md`.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
Report suspected vulnerabilities privately to the maintainer at
|
|
4
|
+
**sqllocks@sqlbites.com**, or through GitHub's private vulnerability reporting on
|
|
5
|
+
this repository, rather than opening a public issue. Do not include real secrets,
|
|
6
|
+
PII or customer datasets in reports.
|
|
7
|
+
|
|
8
|
+
Shape is in early access; only the latest release receives fixes.
|
|
9
|
+
|
|
10
|
+
Shape treats artifacts, packs, plugins, connector responses and reference assets as
|
|
11
|
+
untrusted inputs. See `docs/THREAT_MODEL.md`.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Third-Party Notices
|
|
2
|
+
|
|
3
|
+
Shape is released under the MIT license (see `LICENSE`).
|
|
4
|
+
|
|
5
|
+
## Spindle
|
|
6
|
+
|
|
7
|
+
Parts of Shape's reference data and behaviour are derived from Spindle.
|
|
8
|
+
|
|
9
|
+
Spindle: MIT, Copyright (c) 2025-2026 SQLLocks (Jonathan Stewart). Where code or
|
|
10
|
+
data copied or substantially derived from Spindle is included, its MIT notice is
|
|
11
|
+
retained.
|
|
12
|
+
|
|
13
|
+
## GeoNames
|
|
14
|
+
|
|
15
|
+
Postal-code and place reference data is derived from GeoNames (https://www.geonames.org/).
|
|
16
|
+
|
|
17
|
+
GeoNames data is licensed under the Creative Commons Attribution 4.0 International
|
|
18
|
+
license (CC-BY-4.0), https://creativecommons.org/licenses/by/4.0/. Attribution:
|
|
19
|
+
"This work includes data from GeoNames (https://www.geonames.org/), licensed under
|
|
20
|
+
CC-BY-4.0." Any distribution that includes this data must retain this attribution.
|