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.
Files changed (355) hide show
  1. datasluice-0.2.0/.editorconfig +37 -0
  2. datasluice-0.2.0/.env.example +21 -0
  3. datasluice-0.2.0/.gitattributes +1 -0
  4. datasluice-0.2.0/.github/FUNDING.yml +15 -0
  5. datasluice-0.2.0/.github/ISSUE_TEMPLATE/bug_report.yml +61 -0
  6. datasluice-0.2.0/.github/ISSUE_TEMPLATE/config.yml +1 -0
  7. datasluice-0.2.0/.github/ISSUE_TEMPLATE/feature_request.yml +30 -0
  8. datasluice-0.2.0/.github/codeql/codeql-config.yml +5 -0
  9. datasluice-0.2.0/.github/workflows/ci.yml +304 -0
  10. datasluice-0.2.0/.github/workflows/codeql.yml +44 -0
  11. datasluice-0.2.0/.github/workflows/docs.yml +72 -0
  12. datasluice-0.2.0/.github/workflows/ocr-review.yml +59 -0
  13. datasluice-0.2.0/.github/workflows/pr-agent.yml +30 -0
  14. datasluice-0.2.0/.github/workflows/publish.yml +147 -0
  15. datasluice-0.2.0/.github/workflows/release-please.yml +115 -0
  16. datasluice-0.2.0/.github/workflows/zizmor.yml +38 -0
  17. datasluice-0.2.0/.gitignore +72 -0
  18. datasluice-0.2.0/.graphifyignore +8 -0
  19. datasluice-0.2.0/.opencodereview/rule.json +100 -0
  20. datasluice-0.2.0/.pr_agent.toml +12 -0
  21. datasluice-0.2.0/.pre-commit-config.yaml +52 -0
  22. datasluice-0.2.0/.release-please-manifest.json +4 -0
  23. datasluice-0.2.0/AGENTS.md +83 -0
  24. datasluice-0.2.0/CHANGELOG.md +43 -0
  25. datasluice-0.2.0/CNAME +1 -0
  26. datasluice-0.2.0/CODE_OF_CONDUCT.md +89 -0
  27. datasluice-0.2.0/CONTRIBUTING.md +141 -0
  28. datasluice-0.2.0/LICENSE +21 -0
  29. datasluice-0.2.0/Makefile +69 -0
  30. datasluice-0.2.0/PKG-INFO +197 -0
  31. datasluice-0.2.0/README.md +147 -0
  32. datasluice-0.2.0/SECURITY.md +32 -0
  33. datasluice-0.2.0/docs/adapters.md +45 -0
  34. datasluice-0.2.0/docs/api.md +3 -0
  35. datasluice-0.2.0/docs/architecture.md +93 -0
  36. datasluice-0.2.0/docs/assets/datasluice-logo-nbg.png +0 -0
  37. datasluice-0.2.0/docs/assets/datasluice-logo.png +0 -0
  38. datasluice-0.2.0/docs/assets/datasluice.png +0 -0
  39. datasluice-0.2.0/docs/examples/airflow.md +73 -0
  40. datasluice-0.2.0/docs/examples/application.md +86 -0
  41. datasluice-0.2.0/docs/examples/ckan.md +19 -0
  42. datasluice-0.2.0/docs/examples/datagouv.md +15 -0
  43. datasluice-0.2.0/docs/examples/dlt.md +23 -0
  44. datasluice-0.2.0/docs/examples/pandas.md +18 -0
  45. datasluice-0.2.0/docs/examples/socrata.md +15 -0
  46. datasluice-0.2.0/docs/index.md +23 -0
  47. datasluice-0.2.0/docs/install.md +49 -0
  48. datasluice-0.2.0/docs/supported-portals.md +61 -0
  49. datasluice-0.2.0/graphify-out/.graphify_labels.json +97 -0
  50. datasluice-0.2.0/graphify-out/GRAPH_REPORT.md +514 -0
  51. datasluice-0.2.0/graphify-out/graph.html +320 -0
  52. datasluice-0.2.0/graphify-out/graph.json +59557 -0
  53. datasluice-0.2.0/graphify-out/manifest.json +652 -0
  54. datasluice-0.2.0/justfile +103 -0
  55. datasluice-0.2.0/providers/apache-airflow/CHANGELOG.md +8 -0
  56. datasluice-0.2.0/providers/apache-airflow/compatibility.json +5 -0
  57. datasluice-0.2.0/providers/apache-airflow/pyproject.toml +59 -0
  58. datasluice-0.2.0/providers/apache-airflow/src/airflow/providers/datasluice/__init__.py +1 -0
  59. datasluice-0.2.0/providers/apache-airflow/src/airflow/providers/datasluice/get_provider_info.py +46 -0
  60. datasluice-0.2.0/providers/apache-airflow/src/airflow/providers/datasluice/hooks/__init__.py +5 -0
  61. datasluice-0.2.0/providers/apache-airflow/src/airflow/providers/datasluice/hooks/datasluice.py +377 -0
  62. datasluice-0.2.0/providers/apache-airflow/src/airflow/providers/datasluice/operators/__init__.py +6 -0
  63. datasluice-0.2.0/providers/apache-airflow/src/airflow/providers/datasluice/operators/_xcom.py +26 -0
  64. datasluice-0.2.0/providers/apache-airflow/src/airflow/providers/datasluice/operators/materialize.py +62 -0
  65. datasluice-0.2.0/providers/apache-airflow/src/airflow/providers/datasluice/operators/search.py +59 -0
  66. datasluice-0.2.0/providers/apache-airflow/src/airflow/providers/datasluice/provider.yaml +23 -0
  67. datasluice-0.2.0/providers/apache-airflow/tests/dags/example_datasluice.py +26 -0
  68. datasluice-0.2.0/providers/apache-airflow/tests/measure_coverage.py +96 -0
  69. datasluice-0.2.0/providers/apache-airflow/tests/run_candidate.py +282 -0
  70. datasluice-0.2.0/providers/apache-airflow/tests/smoke.py +34 -0
  71. datasluice-0.2.0/providers/apache-airflow/tests/test_hook.py +366 -0
  72. datasluice-0.2.0/providers/apache-airflow/tests/test_materialize_operator.py +205 -0
  73. datasluice-0.2.0/providers/apache-airflow/tests/test_provider_metadata.py +150 -0
  74. datasluice-0.2.0/providers/apache-airflow/tests/test_public_boundary.py +44 -0
  75. datasluice-0.2.0/providers/apache-airflow/tests/test_search_operator.py +160 -0
  76. datasluice-0.2.0/providers/registry.json +12 -0
  77. datasluice-0.2.0/pyproject.toml +140 -0
  78. datasluice-0.2.0/release-please-config.json +31 -0
  79. datasluice-0.2.0/renovate.json +44 -0
  80. datasluice-0.2.0/src/datasluice/__init__.py +103 -0
  81. datasluice-0.2.0/src/datasluice/_uri.py +77 -0
  82. datasluice-0.2.0/src/datasluice/_version.py +15 -0
  83. datasluice-0.2.0/src/datasluice/application.py +658 -0
  84. datasluice-0.2.0/src/datasluice/auth/__init__.py +17 -0
  85. datasluice-0.2.0/src/datasluice/auth/api_key.py +57 -0
  86. datasluice-0.2.0/src/datasluice/auth/base.py +28 -0
  87. datasluice-0.2.0/src/datasluice/auth/basic.py +32 -0
  88. datasluice-0.2.0/src/datasluice/auth/bearer.py +30 -0
  89. datasluice-0.2.0/src/datasluice/auth/headers.py +31 -0
  90. datasluice-0.2.0/src/datasluice/auth/none.py +19 -0
  91. datasluice-0.2.0/src/datasluice/cli/__init__.py +5 -0
  92. datasluice-0.2.0/src/datasluice/cli/_output.py +26 -0
  93. datasluice-0.2.0/src/datasluice/cli/_resolver.py +76 -0
  94. datasluice-0.2.0/src/datasluice/cli/app.py +56 -0
  95. datasluice-0.2.0/src/datasluice/cli/detect.py +82 -0
  96. datasluice-0.2.0/src/datasluice/cli/download.py +52 -0
  97. datasluice-0.2.0/src/datasluice/cli/inspect.py +81 -0
  98. datasluice-0.2.0/src/datasluice/cli/materialize.py +53 -0
  99. datasluice-0.2.0/src/datasluice/cli/open.py +69 -0
  100. datasluice-0.2.0/src/datasluice/cli/scan.py +80 -0
  101. datasluice-0.2.0/src/datasluice/cli/search.py +74 -0
  102. datasluice-0.2.0/src/datasluice/config/__init__.py +21 -0
  103. datasluice-0.2.0/src/datasluice/config/defaults.py +11 -0
  104. datasluice-0.2.0/src/datasluice/connectors/__init__.py +6 -0
  105. datasluice-0.2.0/src/datasluice/connectors/_reject.py +71 -0
  106. datasluice-0.2.0/src/datasluice/connectors/base.py +69 -0
  107. datasluice-0.2.0/src/datasluice/connectors/ckan/__init__.py +9 -0
  108. datasluice-0.2.0/src/datasluice/connectors/ckan/adapter.py +116 -0
  109. datasluice-0.2.0/src/datasluice/connectors/ckan/errors.py +30 -0
  110. datasluice-0.2.0/src/datasluice/connectors/ckan/factory.py +21 -0
  111. datasluice-0.2.0/src/datasluice/connectors/ckan/mapper.py +139 -0
  112. datasluice-0.2.0/src/datasluice/connectors/ckan/pagination.py +24 -0
  113. datasluice-0.2.0/src/datasluice/connectors/datagouv/__init__.py +9 -0
  114. datasluice-0.2.0/src/datasluice/connectors/datagouv/adapter.py +107 -0
  115. datasluice-0.2.0/src/datasluice/connectors/datagouv/errors.py +20 -0
  116. datasluice-0.2.0/src/datasluice/connectors/datagouv/factory.py +21 -0
  117. datasluice-0.2.0/src/datasluice/connectors/datagouv/mapper.py +127 -0
  118. datasluice-0.2.0/src/datasluice/connectors/datagouv/pagination.py +24 -0
  119. datasluice-0.2.0/src/datasluice/connectors/socrata/__init__.py +9 -0
  120. datasluice-0.2.0/src/datasluice/connectors/socrata/adapter.py +134 -0
  121. datasluice-0.2.0/src/datasluice/connectors/socrata/errors.py +20 -0
  122. datasluice-0.2.0/src/datasluice/connectors/socrata/factory.py +21 -0
  123. datasluice-0.2.0/src/datasluice/connectors/socrata/mapper.py +125 -0
  124. datasluice-0.2.0/src/datasluice/connectors/socrata/pagination.py +24 -0
  125. datasluice-0.2.0/src/datasluice/contracts/__init__.py +22 -0
  126. datasluice-0.2.0/src/datasluice/contracts/checks.py +242 -0
  127. datasluice-0.2.0/src/datasluice/contracts/fixtures.py +38 -0
  128. datasluice-0.2.0/src/datasluice/credentials/__init__.py +5 -0
  129. datasluice-0.2.0/src/datasluice/credentials/host_provider.py +139 -0
  130. datasluice-0.2.0/src/datasluice/data/__init__.py +45 -0
  131. datasluice-0.2.0/src/datasluice/data/_byte_source.py +108 -0
  132. datasluice-0.2.0/src/datasluice/data/access.py +404 -0
  133. datasluice-0.2.0/src/datasluice/data/batch_stream.py +208 -0
  134. datasluice-0.2.0/src/datasluice/data/compression.py +336 -0
  135. datasluice-0.2.0/src/datasluice/data/readers/__init__.py +61 -0
  136. datasluice-0.2.0/src/datasluice/data/readers/base.py +51 -0
  137. datasluice-0.2.0/src/datasluice/data/readers/csv.py +92 -0
  138. datasluice-0.2.0/src/datasluice/data/readers/geojson.py +127 -0
  139. datasluice-0.2.0/src/datasluice/data/readers/json.py +106 -0
  140. datasluice-0.2.0/src/datasluice/data/readers/parquet.py +138 -0
  141. datasluice-0.2.0/src/datasluice/data/readers/xlsx.py +97 -0
  142. datasluice-0.2.0/src/datasluice/data/schema.py +139 -0
  143. datasluice-0.2.0/src/datasluice/discovery/__init__.py +15 -0
  144. datasluice-0.2.0/src/datasluice/discovery/detector.py +92 -0
  145. datasluice-0.2.0/src/datasluice/discovery/fingerprints.py +29 -0
  146. datasluice-0.2.0/src/datasluice/discovery/portal_metadata.py +24 -0
  147. datasluice-0.2.0/src/datasluice/domain/__init__.py +38 -0
  148. datasluice-0.2.0/src/datasluice/domain/access.py +97 -0
  149. datasluice-0.2.0/src/datasluice/domain/artifact.py +278 -0
  150. datasluice-0.2.0/src/datasluice/domain/capabilities.py +35 -0
  151. datasluice-0.2.0/src/datasluice/domain/credentials.py +20 -0
  152. datasluice-0.2.0/src/datasluice/domain/dataset.py +50 -0
  153. datasluice-0.2.0/src/datasluice/domain/detection.py +48 -0
  154. datasluice-0.2.0/src/datasluice/domain/license.py +20 -0
  155. datasluice-0.2.0/src/datasluice/domain/organization.py +31 -0
  156. datasluice-0.2.0/src/datasluice/domain/query.py +32 -0
  157. datasluice-0.2.0/src/datasluice/domain/resource.py +67 -0
  158. datasluice-0.2.0/src/datasluice/domain/result.py +35 -0
  159. datasluice-0.2.0/src/datasluice/domain/schema.py +31 -0
  160. datasluice-0.2.0/src/datasluice/domain/sync_state.py +23 -0
  161. datasluice-0.2.0/src/datasluice/exceptions.py +186 -0
  162. datasluice-0.2.0/src/datasluice/integrations/__init__.py +21 -0
  163. datasluice-0.2.0/src/datasluice/integrations/arrow.py +35 -0
  164. datasluice-0.2.0/src/datasluice/integrations/dlt.py +194 -0
  165. datasluice-0.2.0/src/datasluice/integrations/duckdb.py +86 -0
  166. datasluice-0.2.0/src/datasluice/integrations/pandas.py +42 -0
  167. datasluice-0.2.0/src/datasluice/integrations/polars.py +41 -0
  168. datasluice-0.2.0/src/datasluice/io/__init__.py +56 -0
  169. datasluice-0.2.0/src/datasluice/io/cache.py +58 -0
  170. datasluice-0.2.0/src/datasluice/io/checksums.py +53 -0
  171. datasluice-0.2.0/src/datasluice/io/content_cache.py +291 -0
  172. datasluice-0.2.0/src/datasluice/io/downloader.py +113 -0
  173. datasluice-0.2.0/src/datasluice/io/filesystem.py +68 -0
  174. datasluice-0.2.0/src/datasluice/io/fsspec_storage.py +94 -0
  175. datasluice-0.2.0/src/datasluice/io/local.py +45 -0
  176. datasluice-0.2.0/src/datasluice/io/storage.py +64 -0
  177. datasluice-0.2.0/src/datasluice/logging.py +94 -0
  178. datasluice-0.2.0/src/datasluice/ports/__init__.py +29 -0
  179. datasluice-0.2.0/src/datasluice/ports/cache.py +16 -0
  180. datasluice-0.2.0/src/datasluice/ports/catalog.py +33 -0
  181. datasluice-0.2.0/src/datasluice/ports/credentials.py +15 -0
  182. datasluice-0.2.0/src/datasluice/ports/detector.py +14 -0
  183. datasluice-0.2.0/src/datasluice/ports/resource_reader.py +49 -0
  184. datasluice-0.2.0/src/datasluice/ports/state_store.py +91 -0
  185. datasluice-0.2.0/src/datasluice/ports/storage.py +16 -0
  186. datasluice-0.2.0/src/datasluice/ports/transport.py +89 -0
  187. datasluice-0.2.0/src/datasluice/py.typed +1 -0
  188. datasluice-0.2.0/src/datasluice/runtime/__init__.py +10 -0
  189. datasluice-0.2.0/src/datasluice/runtime/context.py +31 -0
  190. datasluice-0.2.0/src/datasluice/runtime/defaults.py +82 -0
  191. datasluice-0.2.0/src/datasluice/runtime/plugin_manager.py +92 -0
  192. datasluice-0.2.0/src/datasluice/runtime/session.py +275 -0
  193. datasluice-0.2.0/src/datasluice/sync/__init__.py +32 -0
  194. datasluice-0.2.0/src/datasluice/sync/_hashing.py +38 -0
  195. datasluice-0.2.0/src/datasluice/sync/_identity.py +135 -0
  196. datasluice-0.2.0/src/datasluice/sync/materialize.py +521 -0
  197. datasluice-0.2.0/src/datasluice/sync/state_store.py +711 -0
  198. datasluice-0.2.0/src/datasluice/sync/sync.py +579 -0
  199. datasluice-0.2.0/src/datasluice/transforms/__init__.py +63 -0
  200. datasluice-0.2.0/src/datasluice/transforms/pipeline.py +108 -0
  201. datasluice-0.2.0/src/datasluice/transforms/protocol.py +60 -0
  202. datasluice-0.2.0/src/datasluice/transforms/steps.py +244 -0
  203. datasluice-0.2.0/src/datasluice/transport/__init__.py +42 -0
  204. datasluice-0.2.0/src/datasluice/transport/http_client.py +164 -0
  205. datasluice-0.2.0/src/datasluice/transport/httpx_transport.py +537 -0
  206. datasluice-0.2.0/src/datasluice/transport/pagination.py +49 -0
  207. datasluice-0.2.0/src/datasluice/transport/rate_limit.py +34 -0
  208. datasluice-0.2.0/src/datasluice/transport/redirect.py +82 -0
  209. datasluice-0.2.0/src/datasluice/transport/retry.py +75 -0
  210. datasluice-0.2.0/src/datasluice/transport/user_agent.py +25 -0
  211. datasluice-0.2.0/tests/__init__.py +0 -0
  212. datasluice-0.2.0/tests/conftest.py +13 -0
  213. datasluice-0.2.0/tests/e2e/test_cli_bare.py +104 -0
  214. datasluice-0.2.0/tests/e2e/test_cli_existing.py +417 -0
  215. datasluice-0.2.0/tests/e2e/test_cli_materialize.py +226 -0
  216. datasluice-0.2.0/tests/e2e/test_cli_open.py +201 -0
  217. datasluice-0.2.0/tests/e2e/test_cli_scan.py +241 -0
  218. datasluice-0.2.0/tests/e2e/test_docs_examples.py +125 -0
  219. datasluice-0.2.0/tests/fixtures/ckan/.gitkeep +0 -0
  220. datasluice-0.2.0/tests/fixtures/ckan/organization_show.json +16 -0
  221. datasluice-0.2.0/tests/fixtures/ckan/package_search.json +190 -0
  222. datasluice-0.2.0/tests/fixtures/ckan/package_show.json +53 -0
  223. datasluice-0.2.0/tests/fixtures/contracts/artifact-v1.json +43 -0
  224. datasluice-0.2.0/tests/fixtures/contracts/locator-v1.json +26 -0
  225. datasluice-0.2.0/tests/fixtures/datagouv/.gitkeep +0 -0
  226. datasluice-0.2.0/tests/fixtures/datagouv/dataset.json +44 -0
  227. datasluice-0.2.0/tests/fixtures/datagouv/datasets.json +156 -0
  228. datasluice-0.2.0/tests/fixtures/datagouv/organization.json +11 -0
  229. datasluice-0.2.0/tests/fixtures/socrata/.gitkeep +0 -0
  230. datasluice-0.2.0/tests/fixtures/socrata/catalog_v1.json +137 -0
  231. datasluice-0.2.0/tests/fixtures/socrata/catalog_v1_single.json +41 -0
  232. datasluice-0.2.0/tests/helpers/__init__.py +1 -0
  233. datasluice-0.2.0/tests/helpers/http_server.py +138 -0
  234. datasluice-0.2.0/tests/integration/ckan/.gitkeep +0 -0
  235. datasluice-0.2.0/tests/integration/datagouv/.gitkeep +0 -0
  236. datasluice-0.2.0/tests/integration/socrata/.gitkeep +0 -0
  237. datasluice-0.2.0/tests/quality/test_compatibility_matrix.py +92 -0
  238. datasluice-0.2.0/tests/quality/test_coverage_config.py +221 -0
  239. datasluice-0.2.0/tests/quality/test_docs_guard.py +106 -0
  240. datasluice-0.2.0/tests/quality/test_release_routing.py +661 -0
  241. datasluice-0.2.0/tests/unit/application/test_artifact.py +150 -0
  242. datasluice-0.2.0/tests/unit/application/test_facade.py +246 -0
  243. datasluice-0.2.0/tests/unit/application/test_opened_resource.py +193 -0
  244. datasluice-0.2.0/tests/unit/application/test_scheme_routing.py +42 -0
  245. datasluice-0.2.0/tests/unit/application/test_tracer.py +82 -0
  246. datasluice-0.2.0/tests/unit/auth/test_auth.py +70 -0
  247. datasluice-0.2.0/tests/unit/cli/test_detect_cli.py +134 -0
  248. datasluice-0.2.0/tests/unit/cli/test_download.py +165 -0
  249. datasluice-0.2.0/tests/unit/cli/test_inspect.py +134 -0
  250. datasluice-0.2.0/tests/unit/cli/test_search.py +115 -0
  251. datasluice-0.2.0/tests/unit/connectors/__init__.py +0 -0
  252. datasluice-0.2.0/tests/unit/connectors/test_access_schema_population.py +152 -0
  253. datasluice-0.2.0/tests/unit/connectors/test_capabilities.py +97 -0
  254. datasluice-0.2.0/tests/unit/connectors/test_ckan_mapper.py +67 -0
  255. datasluice-0.2.0/tests/unit/connectors/test_ckan_reject_policy.py +211 -0
  256. datasluice-0.2.0/tests/unit/connectors/test_connector_pagination.py +49 -0
  257. datasluice-0.2.0/tests/unit/connectors/test_datagouv_reject_policy.py +141 -0
  258. datasluice-0.2.0/tests/unit/connectors/test_socrata_mapper.py +17 -0
  259. datasluice-0.2.0/tests/unit/connectors/test_socrata_no_org_capability.py +33 -0
  260. datasluice-0.2.0/tests/unit/connectors/test_socrata_reject_policy.py +160 -0
  261. datasluice-0.2.0/tests/unit/contracts/conftest.py +148 -0
  262. datasluice-0.2.0/tests/unit/contracts/test_builtin_conformance.py +37 -0
  263. datasluice-0.2.0/tests/unit/contracts/test_contract_api.py +35 -0
  264. datasluice-0.2.0/tests/unit/credentials/__init__.py +0 -0
  265. datasluice-0.2.0/tests/unit/credentials/test_host_provider.py +282 -0
  266. datasluice-0.2.0/tests/unit/data/__init__.py +0 -0
  267. datasluice-0.2.0/tests/unit/data/conftest.py +62 -0
  268. datasluice-0.2.0/tests/unit/data/readers/__init__.py +0 -0
  269. datasluice-0.2.0/tests/unit/data/readers/test_csv.py +101 -0
  270. datasluice-0.2.0/tests/unit/data/readers/test_geojson.py +126 -0
  271. datasluice-0.2.0/tests/unit/data/readers/test_json.py +103 -0
  272. datasluice-0.2.0/tests/unit/data/readers/test_parquet.py +75 -0
  273. datasluice-0.2.0/tests/unit/data/readers/test_xlsx.py +97 -0
  274. datasluice-0.2.0/tests/unit/data/test_access.py +196 -0
  275. datasluice-0.2.0/tests/unit/data/test_batch_stream.py +199 -0
  276. datasluice-0.2.0/tests/unit/data/test_batch_stream_lifecycle.py +131 -0
  277. datasluice-0.2.0/tests/unit/data/test_compression.py +162 -0
  278. datasluice-0.2.0/tests/unit/data/test_peak_rss.py +165 -0
  279. datasluice-0.2.0/tests/unit/data/test_schema_mapper.py +111 -0
  280. datasluice-0.2.0/tests/unit/data/test_schema_unification.py +130 -0
  281. datasluice-0.2.0/tests/unit/data/test_streaming_memory.py +132 -0
  282. datasluice-0.2.0/tests/unit/discovery/test_detection_api.py +47 -0
  283. datasluice-0.2.0/tests/unit/discovery/test_detection_di.py +118 -0
  284. datasluice-0.2.0/tests/unit/discovery/test_detection_evidence.py +163 -0
  285. datasluice-0.2.0/tests/unit/discovery/test_detection_exceptions.py +102 -0
  286. datasluice-0.2.0/tests/unit/discovery/test_discovery.py +23 -0
  287. datasluice-0.2.0/tests/unit/domain/test_credentials.py +97 -0
  288. datasluice-0.2.0/tests/unit/domain/test_models.py +53 -0
  289. datasluice-0.2.0/tests/unit/domain/test_new_models.py +210 -0
  290. datasluice-0.2.0/tests/unit/domain/test_purity.py +30 -0
  291. datasluice-0.2.0/tests/unit/integrations/test_dlt.py +450 -0
  292. datasluice-0.2.0/tests/unit/integrations/test_duckdb_injection.py +35 -0
  293. datasluice-0.2.0/tests/unit/integrations/test_equivalence.py +199 -0
  294. datasluice-0.2.0/tests/unit/integrations/test_integrations.py +14 -0
  295. datasluice-0.2.0/tests/unit/integrations/test_to_arrow.py +72 -0
  296. datasluice-0.2.0/tests/unit/integrations/test_to_duckdb.py +105 -0
  297. datasluice-0.2.0/tests/unit/integrations/test_to_pandas.py +84 -0
  298. datasluice-0.2.0/tests/unit/integrations/test_to_polars.py +60 -0
  299. datasluice-0.2.0/tests/unit/io/test_cache.py +63 -0
  300. datasluice-0.2.0/tests/unit/io/test_content_cache.py +329 -0
  301. datasluice-0.2.0/tests/unit/io/test_filesystem.py +82 -0
  302. datasluice-0.2.0/tests/unit/io/test_fsspec_storage.py +131 -0
  303. datasluice-0.2.0/tests/unit/io/test_io.py +63 -0
  304. datasluice-0.2.0/tests/unit/io/test_storage.py +80 -0
  305. datasluice-0.2.0/tests/unit/ports/test_capability_probing.py +82 -0
  306. datasluice-0.2.0/tests/unit/ports/test_protocols.py +133 -0
  307. datasluice-0.2.0/tests/unit/ports/test_transport_conformance.py +21 -0
  308. datasluice-0.2.0/tests/unit/ports/test_transport_protocol.py +56 -0
  309. datasluice-0.2.0/tests/unit/runtime/__init__.py +0 -0
  310. datasluice-0.2.0/tests/unit/runtime/test_no_global_state.py +30 -0
  311. datasluice-0.2.0/tests/unit/runtime/test_plugin_manager.py +112 -0
  312. datasluice-0.2.0/tests/unit/runtime/test_session.py +53 -0
  313. datasluice-0.2.0/tests/unit/runtime/test_session_injection.py +210 -0
  314. datasluice-0.2.0/tests/unit/runtime/test_session_portal.py +150 -0
  315. datasluice-0.2.0/tests/unit/runtime/test_session_sync.py +147 -0
  316. datasluice-0.2.0/tests/unit/sync/__init__.py +1 -0
  317. datasluice-0.2.0/tests/unit/sync/conftest.py +133 -0
  318. datasluice-0.2.0/tests/unit/sync/test_artifact_health.py +155 -0
  319. datasluice-0.2.0/tests/unit/sync/test_conditional_get.py +117 -0
  320. datasluice-0.2.0/tests/unit/sync/test_conditional_handoff.py +120 -0
  321. datasluice-0.2.0/tests/unit/sync/test_idempotent_materialize.py +222 -0
  322. datasluice-0.2.0/tests/unit/sync/test_identity.py +193 -0
  323. datasluice-0.2.0/tests/unit/sync/test_logical_sha.py +99 -0
  324. datasluice-0.2.0/tests/unit/sync/test_resume_two_pass.py +86 -0
  325. datasluice-0.2.0/tests/unit/sync/test_resume_within_resource.py +779 -0
  326. datasluice-0.2.0/tests/unit/sync/test_state_store_cas.py +468 -0
  327. datasluice-0.2.0/tests/unit/sync/test_state_store_errors.py +88 -0
  328. datasluice-0.2.0/tests/unit/sync/test_state_store_hardening.py +572 -0
  329. datasluice-0.2.0/tests/unit/sync/test_state_store_tracer.py +47 -0
  330. datasluice-0.2.0/tests/unit/sync/test_sync_tracer.py +77 -0
  331. datasluice-0.2.0/tests/unit/test_custom_adapter_removed.py +55 -0
  332. datasluice-0.2.0/tests/unit/test_no_dead_settings.py +44 -0
  333. datasluice-0.2.0/tests/unit/test_package.py +42 -0
  334. datasluice-0.2.0/tests/unit/test_redacting_filter.py +161 -0
  335. datasluice-0.2.0/tests/unit/test_sync_purity.py +60 -0
  336. datasluice-0.2.0/tests/unit/test_uri_sanitizer.py +54 -0
  337. datasluice-0.2.0/tests/unit/transforms/__init__.py +0 -0
  338. datasluice-0.2.0/tests/unit/transforms/conftest.py +30 -0
  339. datasluice-0.2.0/tests/unit/transforms/test_cast_schema.py +55 -0
  340. datasluice-0.2.0/tests/unit/transforms/test_context.py +58 -0
  341. datasluice-0.2.0/tests/unit/transforms/test_filter.py +61 -0
  342. datasluice-0.2.0/tests/unit/transforms/test_flatten.py +79 -0
  343. datasluice-0.2.0/tests/unit/transforms/test_normalize_timestamps.py +90 -0
  344. datasluice-0.2.0/tests/unit/transforms/test_pipeline.py +118 -0
  345. datasluice-0.2.0/tests/unit/transforms/test_protocol.py +44 -0
  346. datasluice-0.2.0/tests/unit/transforms/test_rename_columns.py +90 -0
  347. datasluice-0.2.0/tests/unit/transforms/test_select_columns.py +85 -0
  348. datasluice-0.2.0/tests/unit/transport/test_conditional_transport.py +86 -0
  349. datasluice-0.2.0/tests/unit/transport/test_http_client.py +107 -0
  350. datasluice-0.2.0/tests/unit/transport/test_httpx_transport.py +545 -0
  351. datasluice-0.2.0/tests/unit/transport/test_redirect.py +90 -0
  352. datasluice-0.2.0/tests/unit/transport/test_retry.py +125 -0
  353. datasluice-0.2.0/tests/unit/transport/test_transport.py +61 -0
  354. datasluice-0.2.0/uv.lock +1755 -0
  355. 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,5 @@
1
+ name: "CodeQL config"
2
+
3
+ paths-ignore:
4
+ - tests
5
+ - providers/apache-airflow/tests
@@ -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 }}'