datasluice 0.2.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.
- datasluice-0.2.0/.editorconfig +37 -0
- datasluice-0.2.0/.env.example +21 -0
- datasluice-0.2.0/.gitattributes +1 -0
- datasluice-0.2.0/.github/FUNDING.yml +15 -0
- datasluice-0.2.0/.github/ISSUE_TEMPLATE/bug_report.yml +61 -0
- datasluice-0.2.0/.github/ISSUE_TEMPLATE/config.yml +1 -0
- datasluice-0.2.0/.github/ISSUE_TEMPLATE/feature_request.yml +30 -0
- datasluice-0.2.0/.github/codeql/codeql-config.yml +5 -0
- datasluice-0.2.0/.github/workflows/ci.yml +304 -0
- datasluice-0.2.0/.github/workflows/codeql.yml +44 -0
- datasluice-0.2.0/.github/workflows/docs.yml +72 -0
- datasluice-0.2.0/.github/workflows/ocr-review.yml +59 -0
- datasluice-0.2.0/.github/workflows/pr-agent.yml +30 -0
- datasluice-0.2.0/.github/workflows/publish.yml +147 -0
- datasluice-0.2.0/.github/workflows/release-please.yml +115 -0
- datasluice-0.2.0/.github/workflows/zizmor.yml +38 -0
- datasluice-0.2.0/.gitignore +72 -0
- datasluice-0.2.0/.graphifyignore +8 -0
- datasluice-0.2.0/.opencodereview/rule.json +100 -0
- datasluice-0.2.0/.pr_agent.toml +12 -0
- datasluice-0.2.0/.pre-commit-config.yaml +52 -0
- datasluice-0.2.0/.release-please-manifest.json +4 -0
- datasluice-0.2.0/AGENTS.md +83 -0
- datasluice-0.2.0/CHANGELOG.md +43 -0
- datasluice-0.2.0/CNAME +1 -0
- datasluice-0.2.0/CODE_OF_CONDUCT.md +89 -0
- datasluice-0.2.0/CONTRIBUTING.md +141 -0
- datasluice-0.2.0/LICENSE +21 -0
- datasluice-0.2.0/Makefile +69 -0
- datasluice-0.2.0/PKG-INFO +197 -0
- datasluice-0.2.0/README.md +147 -0
- datasluice-0.2.0/SECURITY.md +32 -0
- datasluice-0.2.0/docs/adapters.md +45 -0
- datasluice-0.2.0/docs/api.md +3 -0
- datasluice-0.2.0/docs/architecture.md +93 -0
- datasluice-0.2.0/docs/assets/datasluice-logo-nbg.png +0 -0
- datasluice-0.2.0/docs/assets/datasluice-logo.png +0 -0
- datasluice-0.2.0/docs/assets/datasluice.png +0 -0
- datasluice-0.2.0/docs/examples/airflow.md +73 -0
- datasluice-0.2.0/docs/examples/application.md +86 -0
- datasluice-0.2.0/docs/examples/ckan.md +19 -0
- datasluice-0.2.0/docs/examples/datagouv.md +15 -0
- datasluice-0.2.0/docs/examples/dlt.md +23 -0
- datasluice-0.2.0/docs/examples/pandas.md +18 -0
- datasluice-0.2.0/docs/examples/socrata.md +15 -0
- datasluice-0.2.0/docs/index.md +23 -0
- datasluice-0.2.0/docs/install.md +49 -0
- datasluice-0.2.0/docs/supported-portals.md +61 -0
- datasluice-0.2.0/graphify-out/.graphify_labels.json +97 -0
- datasluice-0.2.0/graphify-out/GRAPH_REPORT.md +514 -0
- datasluice-0.2.0/graphify-out/graph.html +320 -0
- datasluice-0.2.0/graphify-out/graph.json +59557 -0
- datasluice-0.2.0/graphify-out/manifest.json +652 -0
- datasluice-0.2.0/justfile +103 -0
- datasluice-0.2.0/providers/apache-airflow/CHANGELOG.md +8 -0
- datasluice-0.2.0/providers/apache-airflow/compatibility.json +5 -0
- datasluice-0.2.0/providers/apache-airflow/pyproject.toml +59 -0
- datasluice-0.2.0/providers/apache-airflow/src/airflow/providers/datasluice/__init__.py +1 -0
- datasluice-0.2.0/providers/apache-airflow/src/airflow/providers/datasluice/get_provider_info.py +46 -0
- datasluice-0.2.0/providers/apache-airflow/src/airflow/providers/datasluice/hooks/__init__.py +5 -0
- datasluice-0.2.0/providers/apache-airflow/src/airflow/providers/datasluice/hooks/datasluice.py +377 -0
- datasluice-0.2.0/providers/apache-airflow/src/airflow/providers/datasluice/operators/__init__.py +6 -0
- datasluice-0.2.0/providers/apache-airflow/src/airflow/providers/datasluice/operators/_xcom.py +26 -0
- datasluice-0.2.0/providers/apache-airflow/src/airflow/providers/datasluice/operators/materialize.py +62 -0
- datasluice-0.2.0/providers/apache-airflow/src/airflow/providers/datasluice/operators/search.py +59 -0
- datasluice-0.2.0/providers/apache-airflow/src/airflow/providers/datasluice/provider.yaml +23 -0
- datasluice-0.2.0/providers/apache-airflow/tests/dags/example_datasluice.py +26 -0
- datasluice-0.2.0/providers/apache-airflow/tests/measure_coverage.py +96 -0
- datasluice-0.2.0/providers/apache-airflow/tests/run_candidate.py +282 -0
- datasluice-0.2.0/providers/apache-airflow/tests/smoke.py +34 -0
- datasluice-0.2.0/providers/apache-airflow/tests/test_hook.py +366 -0
- datasluice-0.2.0/providers/apache-airflow/tests/test_materialize_operator.py +205 -0
- datasluice-0.2.0/providers/apache-airflow/tests/test_provider_metadata.py +150 -0
- datasluice-0.2.0/providers/apache-airflow/tests/test_public_boundary.py +44 -0
- datasluice-0.2.0/providers/apache-airflow/tests/test_search_operator.py +160 -0
- datasluice-0.2.0/providers/registry.json +12 -0
- datasluice-0.2.0/pyproject.toml +140 -0
- datasluice-0.2.0/release-please-config.json +31 -0
- datasluice-0.2.0/renovate.json +44 -0
- datasluice-0.2.0/src/datasluice/__init__.py +103 -0
- datasluice-0.2.0/src/datasluice/_uri.py +77 -0
- datasluice-0.2.0/src/datasluice/_version.py +15 -0
- datasluice-0.2.0/src/datasluice/application.py +658 -0
- datasluice-0.2.0/src/datasluice/auth/__init__.py +17 -0
- datasluice-0.2.0/src/datasluice/auth/api_key.py +57 -0
- datasluice-0.2.0/src/datasluice/auth/base.py +28 -0
- datasluice-0.2.0/src/datasluice/auth/basic.py +32 -0
- datasluice-0.2.0/src/datasluice/auth/bearer.py +30 -0
- datasluice-0.2.0/src/datasluice/auth/headers.py +31 -0
- datasluice-0.2.0/src/datasluice/auth/none.py +19 -0
- datasluice-0.2.0/src/datasluice/cli/__init__.py +5 -0
- datasluice-0.2.0/src/datasluice/cli/_output.py +26 -0
- datasluice-0.2.0/src/datasluice/cli/_resolver.py +76 -0
- datasluice-0.2.0/src/datasluice/cli/app.py +56 -0
- datasluice-0.2.0/src/datasluice/cli/detect.py +82 -0
- datasluice-0.2.0/src/datasluice/cli/download.py +52 -0
- datasluice-0.2.0/src/datasluice/cli/inspect.py +81 -0
- datasluice-0.2.0/src/datasluice/cli/materialize.py +53 -0
- datasluice-0.2.0/src/datasluice/cli/open.py +69 -0
- datasluice-0.2.0/src/datasluice/cli/scan.py +80 -0
- datasluice-0.2.0/src/datasluice/cli/search.py +74 -0
- datasluice-0.2.0/src/datasluice/config/__init__.py +21 -0
- datasluice-0.2.0/src/datasluice/config/defaults.py +11 -0
- datasluice-0.2.0/src/datasluice/connectors/__init__.py +6 -0
- datasluice-0.2.0/src/datasluice/connectors/_reject.py +71 -0
- datasluice-0.2.0/src/datasluice/connectors/base.py +69 -0
- datasluice-0.2.0/src/datasluice/connectors/ckan/__init__.py +9 -0
- datasluice-0.2.0/src/datasluice/connectors/ckan/adapter.py +116 -0
- datasluice-0.2.0/src/datasluice/connectors/ckan/errors.py +30 -0
- datasluice-0.2.0/src/datasluice/connectors/ckan/factory.py +21 -0
- datasluice-0.2.0/src/datasluice/connectors/ckan/mapper.py +139 -0
- datasluice-0.2.0/src/datasluice/connectors/ckan/pagination.py +24 -0
- datasluice-0.2.0/src/datasluice/connectors/datagouv/__init__.py +9 -0
- datasluice-0.2.0/src/datasluice/connectors/datagouv/adapter.py +107 -0
- datasluice-0.2.0/src/datasluice/connectors/datagouv/errors.py +20 -0
- datasluice-0.2.0/src/datasluice/connectors/datagouv/factory.py +21 -0
- datasluice-0.2.0/src/datasluice/connectors/datagouv/mapper.py +127 -0
- datasluice-0.2.0/src/datasluice/connectors/datagouv/pagination.py +24 -0
- datasluice-0.2.0/src/datasluice/connectors/socrata/__init__.py +9 -0
- datasluice-0.2.0/src/datasluice/connectors/socrata/adapter.py +134 -0
- datasluice-0.2.0/src/datasluice/connectors/socrata/errors.py +20 -0
- datasluice-0.2.0/src/datasluice/connectors/socrata/factory.py +21 -0
- datasluice-0.2.0/src/datasluice/connectors/socrata/mapper.py +125 -0
- datasluice-0.2.0/src/datasluice/connectors/socrata/pagination.py +24 -0
- datasluice-0.2.0/src/datasluice/contracts/__init__.py +22 -0
- datasluice-0.2.0/src/datasluice/contracts/checks.py +242 -0
- datasluice-0.2.0/src/datasluice/contracts/fixtures.py +38 -0
- datasluice-0.2.0/src/datasluice/credentials/__init__.py +5 -0
- datasluice-0.2.0/src/datasluice/credentials/host_provider.py +139 -0
- datasluice-0.2.0/src/datasluice/data/__init__.py +45 -0
- datasluice-0.2.0/src/datasluice/data/_byte_source.py +108 -0
- datasluice-0.2.0/src/datasluice/data/access.py +404 -0
- datasluice-0.2.0/src/datasluice/data/batch_stream.py +208 -0
- datasluice-0.2.0/src/datasluice/data/compression.py +336 -0
- datasluice-0.2.0/src/datasluice/data/readers/__init__.py +61 -0
- datasluice-0.2.0/src/datasluice/data/readers/base.py +51 -0
- datasluice-0.2.0/src/datasluice/data/readers/csv.py +92 -0
- datasluice-0.2.0/src/datasluice/data/readers/geojson.py +127 -0
- datasluice-0.2.0/src/datasluice/data/readers/json.py +106 -0
- datasluice-0.2.0/src/datasluice/data/readers/parquet.py +138 -0
- datasluice-0.2.0/src/datasluice/data/readers/xlsx.py +97 -0
- datasluice-0.2.0/src/datasluice/data/schema.py +139 -0
- datasluice-0.2.0/src/datasluice/discovery/__init__.py +15 -0
- datasluice-0.2.0/src/datasluice/discovery/detector.py +92 -0
- datasluice-0.2.0/src/datasluice/discovery/fingerprints.py +29 -0
- datasluice-0.2.0/src/datasluice/discovery/portal_metadata.py +24 -0
- datasluice-0.2.0/src/datasluice/domain/__init__.py +38 -0
- datasluice-0.2.0/src/datasluice/domain/access.py +97 -0
- datasluice-0.2.0/src/datasluice/domain/artifact.py +278 -0
- datasluice-0.2.0/src/datasluice/domain/capabilities.py +35 -0
- datasluice-0.2.0/src/datasluice/domain/credentials.py +20 -0
- datasluice-0.2.0/src/datasluice/domain/dataset.py +50 -0
- datasluice-0.2.0/src/datasluice/domain/detection.py +48 -0
- datasluice-0.2.0/src/datasluice/domain/license.py +20 -0
- datasluice-0.2.0/src/datasluice/domain/organization.py +31 -0
- datasluice-0.2.0/src/datasluice/domain/query.py +32 -0
- datasluice-0.2.0/src/datasluice/domain/resource.py +67 -0
- datasluice-0.2.0/src/datasluice/domain/result.py +35 -0
- datasluice-0.2.0/src/datasluice/domain/schema.py +31 -0
- datasluice-0.2.0/src/datasluice/domain/sync_state.py +23 -0
- datasluice-0.2.0/src/datasluice/exceptions.py +186 -0
- datasluice-0.2.0/src/datasluice/integrations/__init__.py +21 -0
- datasluice-0.2.0/src/datasluice/integrations/arrow.py +35 -0
- datasluice-0.2.0/src/datasluice/integrations/dlt.py +194 -0
- datasluice-0.2.0/src/datasluice/integrations/duckdb.py +86 -0
- datasluice-0.2.0/src/datasluice/integrations/pandas.py +42 -0
- datasluice-0.2.0/src/datasluice/integrations/polars.py +41 -0
- datasluice-0.2.0/src/datasluice/io/__init__.py +56 -0
- datasluice-0.2.0/src/datasluice/io/cache.py +58 -0
- datasluice-0.2.0/src/datasluice/io/checksums.py +53 -0
- datasluice-0.2.0/src/datasluice/io/content_cache.py +291 -0
- datasluice-0.2.0/src/datasluice/io/downloader.py +113 -0
- datasluice-0.2.0/src/datasluice/io/filesystem.py +68 -0
- datasluice-0.2.0/src/datasluice/io/fsspec_storage.py +94 -0
- datasluice-0.2.0/src/datasluice/io/local.py +45 -0
- datasluice-0.2.0/src/datasluice/io/storage.py +64 -0
- datasluice-0.2.0/src/datasluice/logging.py +94 -0
- datasluice-0.2.0/src/datasluice/ports/__init__.py +29 -0
- datasluice-0.2.0/src/datasluice/ports/cache.py +16 -0
- datasluice-0.2.0/src/datasluice/ports/catalog.py +33 -0
- datasluice-0.2.0/src/datasluice/ports/credentials.py +15 -0
- datasluice-0.2.0/src/datasluice/ports/detector.py +14 -0
- datasluice-0.2.0/src/datasluice/ports/resource_reader.py +49 -0
- datasluice-0.2.0/src/datasluice/ports/state_store.py +91 -0
- datasluice-0.2.0/src/datasluice/ports/storage.py +16 -0
- datasluice-0.2.0/src/datasluice/ports/transport.py +89 -0
- datasluice-0.2.0/src/datasluice/py.typed +1 -0
- datasluice-0.2.0/src/datasluice/runtime/__init__.py +10 -0
- datasluice-0.2.0/src/datasluice/runtime/context.py +31 -0
- datasluice-0.2.0/src/datasluice/runtime/defaults.py +82 -0
- datasluice-0.2.0/src/datasluice/runtime/plugin_manager.py +92 -0
- datasluice-0.2.0/src/datasluice/runtime/session.py +275 -0
- datasluice-0.2.0/src/datasluice/sync/__init__.py +32 -0
- datasluice-0.2.0/src/datasluice/sync/_hashing.py +38 -0
- datasluice-0.2.0/src/datasluice/sync/_identity.py +135 -0
- datasluice-0.2.0/src/datasluice/sync/materialize.py +521 -0
- datasluice-0.2.0/src/datasluice/sync/state_store.py +711 -0
- datasluice-0.2.0/src/datasluice/sync/sync.py +579 -0
- datasluice-0.2.0/src/datasluice/transforms/__init__.py +63 -0
- datasluice-0.2.0/src/datasluice/transforms/pipeline.py +108 -0
- datasluice-0.2.0/src/datasluice/transforms/protocol.py +60 -0
- datasluice-0.2.0/src/datasluice/transforms/steps.py +244 -0
- datasluice-0.2.0/src/datasluice/transport/__init__.py +42 -0
- datasluice-0.2.0/src/datasluice/transport/http_client.py +164 -0
- datasluice-0.2.0/src/datasluice/transport/httpx_transport.py +537 -0
- datasluice-0.2.0/src/datasluice/transport/pagination.py +49 -0
- datasluice-0.2.0/src/datasluice/transport/rate_limit.py +34 -0
- datasluice-0.2.0/src/datasluice/transport/redirect.py +82 -0
- datasluice-0.2.0/src/datasluice/transport/retry.py +75 -0
- datasluice-0.2.0/src/datasluice/transport/user_agent.py +25 -0
- datasluice-0.2.0/tests/__init__.py +0 -0
- datasluice-0.2.0/tests/conftest.py +13 -0
- datasluice-0.2.0/tests/e2e/test_cli_bare.py +104 -0
- datasluice-0.2.0/tests/e2e/test_cli_existing.py +417 -0
- datasluice-0.2.0/tests/e2e/test_cli_materialize.py +226 -0
- datasluice-0.2.0/tests/e2e/test_cli_open.py +201 -0
- datasluice-0.2.0/tests/e2e/test_cli_scan.py +241 -0
- datasluice-0.2.0/tests/e2e/test_docs_examples.py +125 -0
- datasluice-0.2.0/tests/fixtures/ckan/.gitkeep +0 -0
- datasluice-0.2.0/tests/fixtures/ckan/organization_show.json +16 -0
- datasluice-0.2.0/tests/fixtures/ckan/package_search.json +190 -0
- datasluice-0.2.0/tests/fixtures/ckan/package_show.json +53 -0
- datasluice-0.2.0/tests/fixtures/contracts/artifact-v1.json +43 -0
- datasluice-0.2.0/tests/fixtures/contracts/locator-v1.json +26 -0
- datasluice-0.2.0/tests/fixtures/datagouv/.gitkeep +0 -0
- datasluice-0.2.0/tests/fixtures/datagouv/dataset.json +44 -0
- datasluice-0.2.0/tests/fixtures/datagouv/datasets.json +156 -0
- datasluice-0.2.0/tests/fixtures/datagouv/organization.json +11 -0
- datasluice-0.2.0/tests/fixtures/socrata/.gitkeep +0 -0
- datasluice-0.2.0/tests/fixtures/socrata/catalog_v1.json +137 -0
- datasluice-0.2.0/tests/fixtures/socrata/catalog_v1_single.json +41 -0
- datasluice-0.2.0/tests/helpers/__init__.py +1 -0
- datasluice-0.2.0/tests/helpers/http_server.py +138 -0
- datasluice-0.2.0/tests/integration/ckan/.gitkeep +0 -0
- datasluice-0.2.0/tests/integration/datagouv/.gitkeep +0 -0
- datasluice-0.2.0/tests/integration/socrata/.gitkeep +0 -0
- datasluice-0.2.0/tests/quality/test_compatibility_matrix.py +92 -0
- datasluice-0.2.0/tests/quality/test_coverage_config.py +221 -0
- datasluice-0.2.0/tests/quality/test_docs_guard.py +106 -0
- datasluice-0.2.0/tests/quality/test_release_routing.py +661 -0
- datasluice-0.2.0/tests/unit/application/test_artifact.py +150 -0
- datasluice-0.2.0/tests/unit/application/test_facade.py +246 -0
- datasluice-0.2.0/tests/unit/application/test_opened_resource.py +193 -0
- datasluice-0.2.0/tests/unit/application/test_scheme_routing.py +42 -0
- datasluice-0.2.0/tests/unit/application/test_tracer.py +82 -0
- datasluice-0.2.0/tests/unit/auth/test_auth.py +70 -0
- datasluice-0.2.0/tests/unit/cli/test_detect_cli.py +134 -0
- datasluice-0.2.0/tests/unit/cli/test_download.py +165 -0
- datasluice-0.2.0/tests/unit/cli/test_inspect.py +134 -0
- datasluice-0.2.0/tests/unit/cli/test_search.py +115 -0
- datasluice-0.2.0/tests/unit/connectors/__init__.py +0 -0
- datasluice-0.2.0/tests/unit/connectors/test_access_schema_population.py +152 -0
- datasluice-0.2.0/tests/unit/connectors/test_capabilities.py +97 -0
- datasluice-0.2.0/tests/unit/connectors/test_ckan_mapper.py +67 -0
- datasluice-0.2.0/tests/unit/connectors/test_ckan_reject_policy.py +211 -0
- datasluice-0.2.0/tests/unit/connectors/test_connector_pagination.py +49 -0
- datasluice-0.2.0/tests/unit/connectors/test_datagouv_reject_policy.py +141 -0
- datasluice-0.2.0/tests/unit/connectors/test_socrata_mapper.py +17 -0
- datasluice-0.2.0/tests/unit/connectors/test_socrata_no_org_capability.py +33 -0
- datasluice-0.2.0/tests/unit/connectors/test_socrata_reject_policy.py +160 -0
- datasluice-0.2.0/tests/unit/contracts/conftest.py +148 -0
- datasluice-0.2.0/tests/unit/contracts/test_builtin_conformance.py +37 -0
- datasluice-0.2.0/tests/unit/contracts/test_contract_api.py +35 -0
- datasluice-0.2.0/tests/unit/credentials/__init__.py +0 -0
- datasluice-0.2.0/tests/unit/credentials/test_host_provider.py +282 -0
- datasluice-0.2.0/tests/unit/data/__init__.py +0 -0
- datasluice-0.2.0/tests/unit/data/conftest.py +62 -0
- datasluice-0.2.0/tests/unit/data/readers/__init__.py +0 -0
- datasluice-0.2.0/tests/unit/data/readers/test_csv.py +101 -0
- datasluice-0.2.0/tests/unit/data/readers/test_geojson.py +126 -0
- datasluice-0.2.0/tests/unit/data/readers/test_json.py +103 -0
- datasluice-0.2.0/tests/unit/data/readers/test_parquet.py +75 -0
- datasluice-0.2.0/tests/unit/data/readers/test_xlsx.py +97 -0
- datasluice-0.2.0/tests/unit/data/test_access.py +196 -0
- datasluice-0.2.0/tests/unit/data/test_batch_stream.py +199 -0
- datasluice-0.2.0/tests/unit/data/test_batch_stream_lifecycle.py +131 -0
- datasluice-0.2.0/tests/unit/data/test_compression.py +162 -0
- datasluice-0.2.0/tests/unit/data/test_peak_rss.py +165 -0
- datasluice-0.2.0/tests/unit/data/test_schema_mapper.py +111 -0
- datasluice-0.2.0/tests/unit/data/test_schema_unification.py +130 -0
- datasluice-0.2.0/tests/unit/data/test_streaming_memory.py +132 -0
- datasluice-0.2.0/tests/unit/discovery/test_detection_api.py +47 -0
- datasluice-0.2.0/tests/unit/discovery/test_detection_di.py +118 -0
- datasluice-0.2.0/tests/unit/discovery/test_detection_evidence.py +163 -0
- datasluice-0.2.0/tests/unit/discovery/test_detection_exceptions.py +102 -0
- datasluice-0.2.0/tests/unit/discovery/test_discovery.py +23 -0
- datasluice-0.2.0/tests/unit/domain/test_credentials.py +97 -0
- datasluice-0.2.0/tests/unit/domain/test_models.py +53 -0
- datasluice-0.2.0/tests/unit/domain/test_new_models.py +210 -0
- datasluice-0.2.0/tests/unit/domain/test_purity.py +30 -0
- datasluice-0.2.0/tests/unit/integrations/test_dlt.py +450 -0
- datasluice-0.2.0/tests/unit/integrations/test_duckdb_injection.py +35 -0
- datasluice-0.2.0/tests/unit/integrations/test_equivalence.py +199 -0
- datasluice-0.2.0/tests/unit/integrations/test_integrations.py +14 -0
- datasluice-0.2.0/tests/unit/integrations/test_to_arrow.py +72 -0
- datasluice-0.2.0/tests/unit/integrations/test_to_duckdb.py +105 -0
- datasluice-0.2.0/tests/unit/integrations/test_to_pandas.py +84 -0
- datasluice-0.2.0/tests/unit/integrations/test_to_polars.py +60 -0
- datasluice-0.2.0/tests/unit/io/test_cache.py +63 -0
- datasluice-0.2.0/tests/unit/io/test_content_cache.py +329 -0
- datasluice-0.2.0/tests/unit/io/test_filesystem.py +82 -0
- datasluice-0.2.0/tests/unit/io/test_fsspec_storage.py +131 -0
- datasluice-0.2.0/tests/unit/io/test_io.py +63 -0
- datasluice-0.2.0/tests/unit/io/test_storage.py +80 -0
- datasluice-0.2.0/tests/unit/ports/test_capability_probing.py +82 -0
- datasluice-0.2.0/tests/unit/ports/test_protocols.py +133 -0
- datasluice-0.2.0/tests/unit/ports/test_transport_conformance.py +21 -0
- datasluice-0.2.0/tests/unit/ports/test_transport_protocol.py +56 -0
- datasluice-0.2.0/tests/unit/runtime/__init__.py +0 -0
- datasluice-0.2.0/tests/unit/runtime/test_no_global_state.py +30 -0
- datasluice-0.2.0/tests/unit/runtime/test_plugin_manager.py +112 -0
- datasluice-0.2.0/tests/unit/runtime/test_session.py +53 -0
- datasluice-0.2.0/tests/unit/runtime/test_session_injection.py +210 -0
- datasluice-0.2.0/tests/unit/runtime/test_session_portal.py +150 -0
- datasluice-0.2.0/tests/unit/runtime/test_session_sync.py +147 -0
- datasluice-0.2.0/tests/unit/sync/__init__.py +1 -0
- datasluice-0.2.0/tests/unit/sync/conftest.py +133 -0
- datasluice-0.2.0/tests/unit/sync/test_artifact_health.py +155 -0
- datasluice-0.2.0/tests/unit/sync/test_conditional_get.py +117 -0
- datasluice-0.2.0/tests/unit/sync/test_conditional_handoff.py +120 -0
- datasluice-0.2.0/tests/unit/sync/test_idempotent_materialize.py +222 -0
- datasluice-0.2.0/tests/unit/sync/test_identity.py +193 -0
- datasluice-0.2.0/tests/unit/sync/test_logical_sha.py +99 -0
- datasluice-0.2.0/tests/unit/sync/test_resume_two_pass.py +86 -0
- datasluice-0.2.0/tests/unit/sync/test_resume_within_resource.py +779 -0
- datasluice-0.2.0/tests/unit/sync/test_state_store_cas.py +468 -0
- datasluice-0.2.0/tests/unit/sync/test_state_store_errors.py +88 -0
- datasluice-0.2.0/tests/unit/sync/test_state_store_hardening.py +572 -0
- datasluice-0.2.0/tests/unit/sync/test_state_store_tracer.py +47 -0
- datasluice-0.2.0/tests/unit/sync/test_sync_tracer.py +77 -0
- datasluice-0.2.0/tests/unit/test_custom_adapter_removed.py +55 -0
- datasluice-0.2.0/tests/unit/test_no_dead_settings.py +44 -0
- datasluice-0.2.0/tests/unit/test_package.py +42 -0
- datasluice-0.2.0/tests/unit/test_redacting_filter.py +161 -0
- datasluice-0.2.0/tests/unit/test_sync_purity.py +60 -0
- datasluice-0.2.0/tests/unit/test_uri_sanitizer.py +54 -0
- datasluice-0.2.0/tests/unit/transforms/__init__.py +0 -0
- datasluice-0.2.0/tests/unit/transforms/conftest.py +30 -0
- datasluice-0.2.0/tests/unit/transforms/test_cast_schema.py +55 -0
- datasluice-0.2.0/tests/unit/transforms/test_context.py +58 -0
- datasluice-0.2.0/tests/unit/transforms/test_filter.py +61 -0
- datasluice-0.2.0/tests/unit/transforms/test_flatten.py +79 -0
- datasluice-0.2.0/tests/unit/transforms/test_normalize_timestamps.py +90 -0
- datasluice-0.2.0/tests/unit/transforms/test_pipeline.py +118 -0
- datasluice-0.2.0/tests/unit/transforms/test_protocol.py +44 -0
- datasluice-0.2.0/tests/unit/transforms/test_rename_columns.py +90 -0
- datasluice-0.2.0/tests/unit/transforms/test_select_columns.py +85 -0
- datasluice-0.2.0/tests/unit/transport/test_conditional_transport.py +86 -0
- datasluice-0.2.0/tests/unit/transport/test_http_client.py +107 -0
- datasluice-0.2.0/tests/unit/transport/test_httpx_transport.py +545 -0
- datasluice-0.2.0/tests/unit/transport/test_redirect.py +90 -0
- datasluice-0.2.0/tests/unit/transport/test_retry.py +125 -0
- datasluice-0.2.0/tests/unit/transport/test_transport.py +61 -0
- datasluice-0.2.0/uv.lock +1755 -0
- datasluice-0.2.0/zensical.toml +42 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# https://editorconfig.org
|
|
2
|
+
root = true
|
|
3
|
+
|
|
4
|
+
[*]
|
|
5
|
+
charset = utf-8
|
|
6
|
+
end_of_line = lf
|
|
7
|
+
indent_style = space
|
|
8
|
+
indent_size = 4
|
|
9
|
+
trim_trailing_whitespace = true
|
|
10
|
+
insert_final_newline = true
|
|
11
|
+
|
|
12
|
+
[*.{html,css,js,json,sh,yml,yaml}]
|
|
13
|
+
indent_size = 2
|
|
14
|
+
|
|
15
|
+
[*.bat]
|
|
16
|
+
indent_style = tab
|
|
17
|
+
end_of_line = crlf
|
|
18
|
+
|
|
19
|
+
[LICENSE]
|
|
20
|
+
insert_final_newline = false
|
|
21
|
+
|
|
22
|
+
[justfile]
|
|
23
|
+
indent_style = space
|
|
24
|
+
indent_size = 4
|
|
25
|
+
|
|
26
|
+
# Ignore binary or generated files
|
|
27
|
+
[*.{png,jpg,gif,ico,woff,woff2,ttf,eot,svg,pdf}]
|
|
28
|
+
charset = unset
|
|
29
|
+
end_of_line = unset
|
|
30
|
+
indent_style = unset
|
|
31
|
+
indent_size = unset
|
|
32
|
+
trim_trailing_whitespace = unset
|
|
33
|
+
insert_final_newline = unset
|
|
34
|
+
max_line_length = unset
|
|
35
|
+
|
|
36
|
+
[*.{diff,patch}]
|
|
37
|
+
trim_trailing_whitespace = false
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# DataSluice environment variables
|
|
2
|
+
# Copy this file to .env and adjust as needed.
|
|
3
|
+
|
|
4
|
+
# HTTP client
|
|
5
|
+
DATASLUICE_HTTP_TIMEOUT=30
|
|
6
|
+
DATASLUICE_HTTP_RETRIES=3
|
|
7
|
+
DATASLUICE_HTTP_RATE_LIMIT=10
|
|
8
|
+
|
|
9
|
+
# Authentication (optional, for portals requiring API keys)
|
|
10
|
+
DATASLUICE_API_KEY=
|
|
11
|
+
DATASLUICE_BEARER_TOKEN=
|
|
12
|
+
|
|
13
|
+
# Cache
|
|
14
|
+
DATASLUICE_CACHE_DIR=.datasluice/cache
|
|
15
|
+
DATASLUICE_CACHE_TTL=3600
|
|
16
|
+
|
|
17
|
+
# Logging
|
|
18
|
+
DATASLUICE_LOG_LEVEL=INFO
|
|
19
|
+
|
|
20
|
+
# User agent
|
|
21
|
+
DATASLUICE_USER_AGENT=datasluice/0.1.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
graphify-out/graph.json merge=graphify
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# These are supported funding model platforms
|
|
2
|
+
|
|
3
|
+
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
|
4
|
+
patreon: # Replace with a single Patreon username
|
|
5
|
+
open_collective: # Replace with a single Open Collective username
|
|
6
|
+
ko_fi: # Replace with a single Ko-fi username
|
|
7
|
+
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
|
8
|
+
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
|
9
|
+
liberapay: # Replace with a single Liberapay username
|
|
10
|
+
issuehunt: # Replace with a single IssueHunt username
|
|
11
|
+
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
|
12
|
+
polar: # Replace with a single Polar username
|
|
13
|
+
buy_me_a_coffee: nitishraj
|
|
14
|
+
thanks_dev: # Replace with a single thanks.dev username
|
|
15
|
+
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
name: Bug Report
|
|
2
|
+
description: Something isn't working as expected.
|
|
3
|
+
title: "BUG: "
|
|
4
|
+
labels: [bug]
|
|
5
|
+
body:
|
|
6
|
+
- type: textarea
|
|
7
|
+
id: description
|
|
8
|
+
attributes:
|
|
9
|
+
label: Describe the bug
|
|
10
|
+
description: What happened? What did you expect to happen?
|
|
11
|
+
validations:
|
|
12
|
+
required: true
|
|
13
|
+
- type: textarea
|
|
14
|
+
id: steps
|
|
15
|
+
attributes:
|
|
16
|
+
label: Steps to reproduce
|
|
17
|
+
description: Minimal steps to trigger the bug.
|
|
18
|
+
placeholder: |
|
|
19
|
+
1. Install with `uv pip install datasluice`
|
|
20
|
+
2. Run `...`
|
|
21
|
+
3. See error
|
|
22
|
+
validations:
|
|
23
|
+
required: true
|
|
24
|
+
- type: textarea
|
|
25
|
+
id: expected
|
|
26
|
+
attributes:
|
|
27
|
+
label: Expected behavior
|
|
28
|
+
validations:
|
|
29
|
+
required: true
|
|
30
|
+
- type: input
|
|
31
|
+
id: version
|
|
32
|
+
attributes:
|
|
33
|
+
label: "DataSluice version"
|
|
34
|
+
placeholder: "0.1.0"
|
|
35
|
+
validations:
|
|
36
|
+
required: true
|
|
37
|
+
- type: input
|
|
38
|
+
id: python-version
|
|
39
|
+
attributes:
|
|
40
|
+
label: Python version
|
|
41
|
+
placeholder: "3.13"
|
|
42
|
+
validations:
|
|
43
|
+
required: true
|
|
44
|
+
- type: dropdown
|
|
45
|
+
id: os
|
|
46
|
+
attributes:
|
|
47
|
+
label: Operating system
|
|
48
|
+
options:
|
|
49
|
+
- macOS
|
|
50
|
+
- Linux
|
|
51
|
+
- Windows
|
|
52
|
+
- Other
|
|
53
|
+
validations:
|
|
54
|
+
required: true
|
|
55
|
+
- type: textarea
|
|
56
|
+
id: context
|
|
57
|
+
attributes:
|
|
58
|
+
label: Additional context
|
|
59
|
+
description: Logs, tracebacks, screenshots, or anything else that helps.
|
|
60
|
+
validations:
|
|
61
|
+
required: false
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
blank_issues_enabled: true
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: Feature Request
|
|
2
|
+
description: Suggest something new.
|
|
3
|
+
title: "FEAT: "
|
|
4
|
+
labels: [enhancement]
|
|
5
|
+
body:
|
|
6
|
+
- type: textarea
|
|
7
|
+
id: description
|
|
8
|
+
attributes:
|
|
9
|
+
label: Describe the feature
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: motivation
|
|
14
|
+
attributes:
|
|
15
|
+
label: Motivation
|
|
16
|
+
description: What problem does this solve? What's the use case?
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: alternatives
|
|
21
|
+
attributes:
|
|
22
|
+
label: Alternatives considered
|
|
23
|
+
validations:
|
|
24
|
+
required: false
|
|
25
|
+
- type: textarea
|
|
26
|
+
id: context
|
|
27
|
+
attributes:
|
|
28
|
+
label: Additional context
|
|
29
|
+
validations:
|
|
30
|
+
required: false
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- main
|
|
8
|
+
pull_request:
|
|
9
|
+
types:
|
|
10
|
+
- opened
|
|
11
|
+
- synchronize
|
|
12
|
+
- reopened
|
|
13
|
+
- ready_for_review
|
|
14
|
+
|
|
15
|
+
permissions: {}
|
|
16
|
+
|
|
17
|
+
concurrency:
|
|
18
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
19
|
+
cancel-in-progress: true
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
lint:
|
|
23
|
+
name: Lint & format
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
steps:
|
|
26
|
+
- name: Checkout code
|
|
27
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
28
|
+
with:
|
|
29
|
+
persist-credentials: false
|
|
30
|
+
|
|
31
|
+
- name: Set up UV
|
|
32
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
33
|
+
|
|
34
|
+
- name: Ruff format check
|
|
35
|
+
run: uv run ruff format --check .
|
|
36
|
+
|
|
37
|
+
- name: Ruff lint
|
|
38
|
+
run: uv run ruff check .
|
|
39
|
+
|
|
40
|
+
type-check:
|
|
41
|
+
name: Type check
|
|
42
|
+
runs-on: ubuntu-latest
|
|
43
|
+
steps:
|
|
44
|
+
- name: Checkout code
|
|
45
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
46
|
+
with:
|
|
47
|
+
persist-credentials: false
|
|
48
|
+
|
|
49
|
+
- name: Set up UV
|
|
50
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
51
|
+
|
|
52
|
+
- name: Type check with ty
|
|
53
|
+
run: uv run --all-extras ty check .
|
|
54
|
+
|
|
55
|
+
provider-matrix:
|
|
56
|
+
name: Resolve provider compatibility matrix
|
|
57
|
+
runs-on: ubuntu-latest
|
|
58
|
+
outputs:
|
|
59
|
+
matrix: ${{ steps.emit.outputs.matrix }}
|
|
60
|
+
steps:
|
|
61
|
+
- name: Checkout code
|
|
62
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
63
|
+
with:
|
|
64
|
+
persist-credentials: false
|
|
65
|
+
|
|
66
|
+
- name: Emit matrix from compatibility manifest
|
|
67
|
+
id: emit
|
|
68
|
+
run: |
|
|
69
|
+
python - <<'PY'
|
|
70
|
+
import json
|
|
71
|
+
import itertools
|
|
72
|
+
with open("providers/apache-airflow/compatibility.json", encoding="utf-8") as fh:
|
|
73
|
+
manifest = json.load(fh)
|
|
74
|
+
include = [
|
|
75
|
+
{"core_version": core, "airflow": airflow, "python": minor}
|
|
76
|
+
for core, airflow, minor in itertools.product(
|
|
77
|
+
manifest["core"], manifest["airflow"], manifest["python"]
|
|
78
|
+
)
|
|
79
|
+
]
|
|
80
|
+
with open("/tmp/provider-matrix.json", "w", encoding="utf-8") as fh:
|
|
81
|
+
json.dump({"include": include}, fh)
|
|
82
|
+
print(json.dumps({"include": include}))
|
|
83
|
+
PY
|
|
84
|
+
echo "matrix=$(cat /tmp/provider-matrix.json)" >> "$GITHUB_OUTPUT"
|
|
85
|
+
|
|
86
|
+
test:
|
|
87
|
+
name: Test (Python ${{ matrix.python-version }})
|
|
88
|
+
runs-on: ubuntu-latest
|
|
89
|
+
strategy:
|
|
90
|
+
fail-fast: false
|
|
91
|
+
matrix:
|
|
92
|
+
python-version: ["3.12", "3.13", "3.14"]
|
|
93
|
+
steps:
|
|
94
|
+
- name: Checkout code
|
|
95
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
96
|
+
with:
|
|
97
|
+
persist-credentials: false
|
|
98
|
+
|
|
99
|
+
- name: Set up UV
|
|
100
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
101
|
+
|
|
102
|
+
- name: Run core tests
|
|
103
|
+
run: uv run --all-extras --python=${{ matrix.python-version }} coverage run --source=src/datasluice --branch -m pytest tests
|
|
104
|
+
|
|
105
|
+
- name: Upload core coverage data
|
|
106
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
107
|
+
with:
|
|
108
|
+
name: core-coverage-${{ matrix.python-version }}
|
|
109
|
+
path: .coverage.core.*
|
|
110
|
+
include-hidden-files: true
|
|
111
|
+
if-no-files-found: error
|
|
112
|
+
|
|
113
|
+
coverage-core:
|
|
114
|
+
name: Core branch coverage (>= 80%)
|
|
115
|
+
needs: test
|
|
116
|
+
runs-on: ubuntu-latest
|
|
117
|
+
steps:
|
|
118
|
+
- name: Checkout code
|
|
119
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
120
|
+
with:
|
|
121
|
+
persist-credentials: false
|
|
122
|
+
|
|
123
|
+
- name: Set up UV
|
|
124
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
125
|
+
|
|
126
|
+
- name: Download core coverage data
|
|
127
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
128
|
+
with:
|
|
129
|
+
pattern: core-coverage-*
|
|
130
|
+
merge-multiple: true
|
|
131
|
+
path: .coverage/
|
|
132
|
+
include-hidden-files: true
|
|
133
|
+
|
|
134
|
+
- name: Combine core coverage
|
|
135
|
+
run: uv run coverage combine --data-file=.coverage.core .coverage/
|
|
136
|
+
env:
|
|
137
|
+
COVERAGE_FILE: .coverage.core
|
|
138
|
+
|
|
139
|
+
- name: Core coverage report
|
|
140
|
+
run: |
|
|
141
|
+
echo '## Core Branch Coverage Report' >> $GITHUB_STEP_SUMMARY
|
|
142
|
+
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
143
|
+
uv run coverage report --data-file=.coverage.core | tee -a $GITHUB_STEP_SUMMARY
|
|
144
|
+
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
145
|
+
|
|
146
|
+
provider-test:
|
|
147
|
+
name: Provider ${{ matrix.airflow }} / py${{ matrix.python }}
|
|
148
|
+
needs: provider-matrix
|
|
149
|
+
runs-on: ubuntu-latest
|
|
150
|
+
strategy:
|
|
151
|
+
fail-fast: false
|
|
152
|
+
matrix: ${{ fromJson(needs.provider-matrix.outputs.matrix) }}
|
|
153
|
+
steps:
|
|
154
|
+
- name: Checkout code
|
|
155
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
156
|
+
with:
|
|
157
|
+
persist-credentials: false
|
|
158
|
+
|
|
159
|
+
- name: Set up UV
|
|
160
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
161
|
+
|
|
162
|
+
- name: Run provider tests (local candidate wheels)
|
|
163
|
+
run: |
|
|
164
|
+
uv run --python=${{ matrix.python }} python providers/apache-airflow/tests/run_candidate.py \
|
|
165
|
+
--core-version ${{ matrix.core_version }} \
|
|
166
|
+
--airflow-version ${{ matrix.airflow }} \
|
|
167
|
+
-- pytest providers/apache-airflow/tests -x
|
|
168
|
+
|
|
169
|
+
coverage-provider:
|
|
170
|
+
name: Provider branch coverage (>= 80%)
|
|
171
|
+
runs-on: ubuntu-latest
|
|
172
|
+
steps:
|
|
173
|
+
- name: Checkout code
|
|
174
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
175
|
+
with:
|
|
176
|
+
persist-credentials: false
|
|
177
|
+
|
|
178
|
+
- name: Set up UV
|
|
179
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
180
|
+
|
|
181
|
+
- name: Run provider suite under coverage
|
|
182
|
+
run: |
|
|
183
|
+
uv run python providers/apache-airflow/tests/run_candidate.py \
|
|
184
|
+
--core-version 1.0.0 \
|
|
185
|
+
--airflow-version 3.2.2 \
|
|
186
|
+
-- --cover-provider providers/apache-airflow/tests -q
|
|
187
|
+
|
|
188
|
+
build:
|
|
189
|
+
name: Build & validate package
|
|
190
|
+
runs-on: ubuntu-latest
|
|
191
|
+
steps:
|
|
192
|
+
- name: Checkout code
|
|
193
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
194
|
+
with:
|
|
195
|
+
persist-credentials: false
|
|
196
|
+
|
|
197
|
+
- name: Set up UV
|
|
198
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
199
|
+
with:
|
|
200
|
+
enable-cache: false
|
|
201
|
+
|
|
202
|
+
- name: Build distribution
|
|
203
|
+
run: uv build
|
|
204
|
+
|
|
205
|
+
- name: Validate distribution
|
|
206
|
+
run: uvx twine check dist/*
|
|
207
|
+
|
|
208
|
+
- name: Upload distribution
|
|
209
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
210
|
+
with:
|
|
211
|
+
name: dist
|
|
212
|
+
path: dist/
|
|
213
|
+
|
|
214
|
+
installed-wheel-e2e:
|
|
215
|
+
name: Installed-wheel CLI E2E (py${{ matrix.python-version }})
|
|
216
|
+
needs: build
|
|
217
|
+
runs-on: ubuntu-latest
|
|
218
|
+
strategy:
|
|
219
|
+
fail-fast: false
|
|
220
|
+
matrix:
|
|
221
|
+
python-version: ["3.12", "3.14"]
|
|
222
|
+
steps:
|
|
223
|
+
- name: Checkout code
|
|
224
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
225
|
+
with:
|
|
226
|
+
persist-credentials: false
|
|
227
|
+
|
|
228
|
+
- name: Set up UV
|
|
229
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
230
|
+
|
|
231
|
+
- name: Installed-wheel bare CLI E2E
|
|
232
|
+
run: uv run --python=${{ matrix.python-version }} pytest tests/e2e/test_cli_bare.py -x
|
|
233
|
+
|
|
234
|
+
- name: Installed-wheel all-extras CLI E2E
|
|
235
|
+
run: uv run --python=${{ matrix.python-version }} pytest tests/e2e/test_cli_existing.py -x
|
|
236
|
+
env:
|
|
237
|
+
DATASLUICE_E2E_EXTRAS: all
|
|
238
|
+
|
|
239
|
+
provider-e2e:
|
|
240
|
+
name: Provider DAG import E2E (py${{ matrix.python-version }})
|
|
241
|
+
needs: build
|
|
242
|
+
runs-on: ubuntu-latest
|
|
243
|
+
strategy:
|
|
244
|
+
fail-fast: false
|
|
245
|
+
matrix:
|
|
246
|
+
python-version: ["3.12", "3.14"]
|
|
247
|
+
steps:
|
|
248
|
+
- name: Checkout code
|
|
249
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
250
|
+
with:
|
|
251
|
+
persist-credentials: false
|
|
252
|
+
|
|
253
|
+
- name: Set up UV
|
|
254
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
255
|
+
|
|
256
|
+
- name: Import sample DAG from installed wheels
|
|
257
|
+
run: |
|
|
258
|
+
uv run --python=${{ matrix.python-version }} python providers/apache-airflow/tests/run_candidate.py \
|
|
259
|
+
--core-version 1.0.0 \
|
|
260
|
+
--airflow-version 3.2.2 \
|
|
261
|
+
-- python providers/apache-airflow/tests/dags/example_datasluice.py
|
|
262
|
+
|
|
263
|
+
smoke-test:
|
|
264
|
+
name: Smoke test (install wheel)
|
|
265
|
+
needs: build
|
|
266
|
+
runs-on: ubuntu-latest
|
|
267
|
+
steps:
|
|
268
|
+
- name: Download distribution
|
|
269
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
270
|
+
with:
|
|
271
|
+
name: dist
|
|
272
|
+
path: dist/
|
|
273
|
+
|
|
274
|
+
- name: Set up UV
|
|
275
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
276
|
+
with:
|
|
277
|
+
enable-cache: false
|
|
278
|
+
|
|
279
|
+
- name: Install built wheel & smoke import
|
|
280
|
+
run: |
|
|
281
|
+
uv venv --python 3.12 /tmp/smoke
|
|
282
|
+
uv pip install --python /tmp/smoke dist/*.whl
|
|
283
|
+
/tmp/smoke/bin/python -c "import datasluice; print(datasluice.__version__)"
|
|
284
|
+
|
|
285
|
+
all-checks-pass:
|
|
286
|
+
name: All checks pass
|
|
287
|
+
if: always()
|
|
288
|
+
needs:
|
|
289
|
+
- lint
|
|
290
|
+
- type-check
|
|
291
|
+
- test
|
|
292
|
+
- coverage-core
|
|
293
|
+
- provider-test
|
|
294
|
+
- coverage-provider
|
|
295
|
+
- build
|
|
296
|
+
- installed-wheel-e2e
|
|
297
|
+
- provider-e2e
|
|
298
|
+
- smoke-test
|
|
299
|
+
runs-on: ubuntu-latest
|
|
300
|
+
steps:
|
|
301
|
+
- name: Check job results
|
|
302
|
+
uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2
|
|
303
|
+
with:
|
|
304
|
+
jobs: ${{ toJSON(needs) }}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: CodeQL
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main ]
|
|
6
|
+
pull_request:
|
|
7
|
+
schedule:
|
|
8
|
+
- cron: '0 6 * * 1'
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
analyze:
|
|
12
|
+
name: Analyze (${{ matrix.language }})
|
|
13
|
+
runs-on: ${{ 'ubuntu-latest' }}
|
|
14
|
+
permissions:
|
|
15
|
+
security-events: write
|
|
16
|
+
packages: read
|
|
17
|
+
actions: read
|
|
18
|
+
contents: read
|
|
19
|
+
|
|
20
|
+
strategy:
|
|
21
|
+
fail-fast: false
|
|
22
|
+
matrix:
|
|
23
|
+
include:
|
|
24
|
+
- language: actions
|
|
25
|
+
build-mode: none
|
|
26
|
+
- language: python
|
|
27
|
+
build-mode: none
|
|
28
|
+
queries: security-extended
|
|
29
|
+
|
|
30
|
+
steps:
|
|
31
|
+
- name: Checkout repository
|
|
32
|
+
uses: actions/checkout@v7.0.0
|
|
33
|
+
|
|
34
|
+
- name: Initialize CodeQL
|
|
35
|
+
uses: github/codeql-action/init@v4
|
|
36
|
+
with:
|
|
37
|
+
languages: ${{ matrix.language }}
|
|
38
|
+
build-mode: ${{ matrix.build-mode }}
|
|
39
|
+
config-file: ./.github/codeql/codeql-config.yml
|
|
40
|
+
|
|
41
|
+
- name: Perform CodeQL Analysis
|
|
42
|
+
uses: github/codeql-action/analyze@v4
|
|
43
|
+
with:
|
|
44
|
+
category: "/language:${{matrix.language}}"
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
name: Documentation
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- main
|
|
8
|
+
|
|
9
|
+
permissions: {}
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: docs-deploy
|
|
13
|
+
# Let in-flight deployments finish to avoid a half-deployed site.
|
|
14
|
+
cancel-in-progress: false
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
build:
|
|
18
|
+
name: Build
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
permissions:
|
|
21
|
+
contents: read
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
24
|
+
with:
|
|
25
|
+
persist-credentials: false
|
|
26
|
+
|
|
27
|
+
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
28
|
+
|
|
29
|
+
- name: Guard current docs against obsolete Airflow references
|
|
30
|
+
run: |
|
|
31
|
+
set -e
|
|
32
|
+
if grep -rEn -e 'datasluice\[airflow\]' -e 'datasluice\.integrations\.airflow' -e 'DataSluiceOperator' -e 'DataSluiceSession' \
|
|
33
|
+
README.md docs --include '*.md' --exclude-dir='.planning' --exclude='CHANGELOG.md'; then
|
|
34
|
+
echo "Obsolete Airflow/core reference found in current docs" >&2
|
|
35
|
+
exit 1
|
|
36
|
+
fi
|
|
37
|
+
grep -q 'apache-airflow-providers-datasluice' docs/install.md
|
|
38
|
+
|
|
39
|
+
- name: Run executable public documentation examples
|
|
40
|
+
run: uv run --group docs --extra pandas --extra streaming --extra storage --extra http pytest tests/e2e/test_docs_examples.py tests/e2e/test_cli_bare.py -x
|
|
41
|
+
|
|
42
|
+
- name: Import provider sample DAG from installed wheels
|
|
43
|
+
run: |
|
|
44
|
+
uv run python providers/apache-airflow/tests/run_candidate.py \
|
|
45
|
+
--core-version 1.0.0 \
|
|
46
|
+
--airflow-version 3.2.2 \
|
|
47
|
+
-- python providers/apache-airflow/tests/dags/example_datasluice.py
|
|
48
|
+
|
|
49
|
+
- name: Build docs (warnings fatal)
|
|
50
|
+
env:
|
|
51
|
+
ZENSICAL_WARNINGS_AS_ERRORS: "1"
|
|
52
|
+
run: uv run --group docs zensical build --clean
|
|
53
|
+
|
|
54
|
+
- uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
|
|
55
|
+
|
|
56
|
+
- uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
|
|
57
|
+
with:
|
|
58
|
+
path: site
|
|
59
|
+
|
|
60
|
+
deploy:
|
|
61
|
+
name: Deploy
|
|
62
|
+
needs: build
|
|
63
|
+
runs-on: ubuntu-latest
|
|
64
|
+
permissions:
|
|
65
|
+
pages: write
|
|
66
|
+
id-token: write
|
|
67
|
+
environment:
|
|
68
|
+
name: github-pages
|
|
69
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
70
|
+
steps:
|
|
71
|
+
- uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
|
|
72
|
+
id: deployment
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
name: OpenCodeReview PR Review
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request_target:
|
|
5
|
+
types:
|
|
6
|
+
- opened
|
|
7
|
+
- synchronize
|
|
8
|
+
- reopened
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
pull-requests: write
|
|
13
|
+
|
|
14
|
+
concurrency:
|
|
15
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
16
|
+
cancel-in-progress: true
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
code-review:
|
|
20
|
+
name: AI code review
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
timeout-minutes: 180
|
|
23
|
+
if: github.event_name == 'pull_request_target' && github.actor != 'renovate[bot]' && github.actor != 'dependabot[bot]'
|
|
24
|
+
steps:
|
|
25
|
+
- name: Run OpenCodeReview
|
|
26
|
+
uses: alibaba/open-code-review@4bcc95acecd629e64ea984c962cfd08dd892a38e # v1.8.10
|
|
27
|
+
with:
|
|
28
|
+
llm_url: ${{ secrets.OCR_LLM_URL }}
|
|
29
|
+
llm_auth_token: ${{ secrets.OCR_LLM_AUTH_TOKEN }}
|
|
30
|
+
llm_model: ${{ secrets.OCR_LLM_MODEL }}
|
|
31
|
+
llm_use_anthropic: ${{ secrets.OCR_LLM_USE_ANTHROPIC }}
|
|
32
|
+
|
|
33
|
+
llm_extra_body: '{"reasoning_effort": "max"}'
|
|
34
|
+
|
|
35
|
+
review_concurrency: '4'
|
|
36
|
+
language: 'English'
|
|
37
|
+
|
|
38
|
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
39
|
+
sticky_summary: 'true'
|
|
40
|
+
incremental: 'true'
|
|
41
|
+
incremental_overlap_threshold: '0.8'
|
|
42
|
+
upload_artifacts: 'true'
|
|
43
|
+
|
|
44
|
+
background: >-
|
|
45
|
+
DataSluice is a Python 3.12+ open-data SDK and CLI for discovery, extraction,
|
|
46
|
+
format normalization, and pipeline integration against CKAN, data.gouv.fr,
|
|
47
|
+
Socrata, and custom portals. Preserve public API compatibility and consistent
|
|
48
|
+
behavior across all portal connectors. Connectors are discovered via the
|
|
49
|
+
datasluice.connectors entry-points group by the injected runtime
|
|
50
|
+
PluginManager (no module-level registry, no import side effects; broken
|
|
51
|
+
third-party plugins are recorded as failures, never fatal). Optional format,
|
|
52
|
+
storage, and integration dependencies (httpx, fsspec, pyarrow, pandas,
|
|
53
|
+
polars, openpyxl, zstandard, dlt, duckdb, airflow) must remain lazily
|
|
54
|
+
imported so the base package works without extras. Prioritize HTTP
|
|
55
|
+
correctness, pagination, retries, rate limiting, redirect handling, resource
|
|
56
|
+
and file-descriptor cleanup (streams, readers, clients), credential and
|
|
57
|
+
secret safety, portal mapping correctness, cache/checksum integrity, sync
|
|
58
|
+
state correctness, typing, and tests for changed behavior. Avoid style-only
|
|
59
|
+
findings already covered by Ruff and ty.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: PR Agent
|
|
2
|
+
|
|
3
|
+
concurrency:
|
|
4
|
+
group: pr-agent-${{ github.event.pull_request.number || github.ref }}
|
|
5
|
+
cancel-in-progress: true
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
pull_request_target:
|
|
9
|
+
types: [opened, reopened, synchronize, ready_for_review]
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: write
|
|
13
|
+
pull-requests: write
|
|
14
|
+
issues: write
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
pr_description:
|
|
18
|
+
name: Auto-generate PR title & description (PR-Agent /describe)
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
timeout-minutes: 15
|
|
21
|
+
if: ${{ github.actor != 'renovate[bot]' && github.actor != 'dependabot[bot]' }}
|
|
22
|
+
steps:
|
|
23
|
+
- name: PR Agent /describe
|
|
24
|
+
uses: the-pr-agent/pr-agent@743f52d80f3513193dfc7626f778c73478df6d0a # v0.41.1
|
|
25
|
+
env:
|
|
26
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
27
|
+
config.model: ${{ secrets.OCR_LLM_MODEL }}
|
|
28
|
+
OPENAI_KEY: ${{ secrets.OCR_LLM_AUTH_TOKEN }}
|
|
29
|
+
OPENAI.API_BASE: ${{ secrets.OCR_LLM_URL }}
|
|
30
|
+
config.fallback_models: '${{ vars.PR_AGENT_FALLBACK_MODEL }}'
|