etlplus 0.15.5__tar.gz → 0.16.2__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 (234) hide show
  1. {etlplus-0.15.5/etlplus.egg-info → etlplus-0.16.2}/PKG-INFO +1 -1
  2. {etlplus-0.15.5 → etlplus-0.16.2}/docs/pipeline-guide.md +2 -2
  3. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/api/types.py +32 -11
  4. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/cli/constants.py +1 -1
  5. etlplus-0.16.2/etlplus/connector/__init__.py +43 -0
  6. etlplus-0.16.2/etlplus/connector/api.py +161 -0
  7. etlplus-0.16.2/etlplus/connector/connector.py +26 -0
  8. etlplus-0.16.2/etlplus/connector/core.py +132 -0
  9. etlplus-0.16.2/etlplus/connector/database.py +122 -0
  10. etlplus-0.16.2/etlplus/connector/enums.py +52 -0
  11. etlplus-0.16.2/etlplus/connector/file.py +120 -0
  12. etlplus-0.16.2/etlplus/connector/types.py +40 -0
  13. etlplus-0.16.2/etlplus/connector/utils.py +122 -0
  14. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/enums.py +0 -32
  15. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/ops/extract.py +210 -23
  16. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/ops/load.py +141 -35
  17. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/ops/run.py +86 -101
  18. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/ops/transform.py +30 -11
  19. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/types.py +3 -2
  20. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/workflow/__init__.py +2 -11
  21. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/workflow/dag.py +23 -1
  22. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/workflow/jobs.py +15 -26
  23. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/workflow/pipeline.py +39 -56
  24. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/workflow/profile.py +4 -2
  25. {etlplus-0.15.5 → etlplus-0.16.2/etlplus.egg-info}/PKG-INFO +1 -1
  26. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus.egg-info/SOURCES.txt +11 -3
  27. {etlplus-0.15.5 → etlplus-0.16.2}/tests/integration/conftest.py +22 -25
  28. etlplus-0.16.2/tests/unit/connector/test_u_connector_enums.py +47 -0
  29. etlplus-0.15.5/tests/unit/workflow/test_u_workflow_connector.py → etlplus-0.16.2/tests/unit/connector/test_u_connector_utils.py +6 -6
  30. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/ops/test_u_ops_load.py +1 -6
  31. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/ops/test_u_ops_run.py +16 -13
  32. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/test_u_enums.py +0 -27
  33. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/workflow/test_u_workflow_pipeline.py +4 -5
  34. etlplus-0.15.5/etlplus/workflow/connector.py +0 -386
  35. etlplus-0.15.5/etlplus/workflow/types.py +0 -115
  36. {etlplus-0.15.5 → etlplus-0.16.2}/.coveragerc +0 -0
  37. {etlplus-0.15.5 → etlplus-0.16.2}/.editorconfig +0 -0
  38. {etlplus-0.15.5 → etlplus-0.16.2}/.gitattributes +0 -0
  39. {etlplus-0.15.5 → etlplus-0.16.2}/.github/actions/python-bootstrap/action.yml +0 -0
  40. {etlplus-0.15.5 → etlplus-0.16.2}/.github/workflows/ci.yml +0 -0
  41. {etlplus-0.15.5 → etlplus-0.16.2}/.gitignore +0 -0
  42. {etlplus-0.15.5 → etlplus-0.16.2}/.pre-commit-config.yaml +0 -0
  43. {etlplus-0.15.5 → etlplus-0.16.2}/.ruff.toml +0 -0
  44. {etlplus-0.15.5 → etlplus-0.16.2}/CODE_OF_CONDUCT.md +0 -0
  45. {etlplus-0.15.5 → etlplus-0.16.2}/CONTRIBUTING.md +0 -0
  46. {etlplus-0.15.5 → etlplus-0.16.2}/DEMO.md +0 -0
  47. {etlplus-0.15.5 → etlplus-0.16.2}/LICENSE +0 -0
  48. {etlplus-0.15.5 → etlplus-0.16.2}/MANIFEST.in +0 -0
  49. {etlplus-0.15.5 → etlplus-0.16.2}/Makefile +0 -0
  50. {etlplus-0.15.5 → etlplus-0.16.2}/README.md +0 -0
  51. {etlplus-0.15.5 → etlplus-0.16.2}/REFERENCES.md +0 -0
  52. {etlplus-0.15.5 → etlplus-0.16.2}/SECURITY.md +0 -0
  53. {etlplus-0.15.5 → etlplus-0.16.2}/SUPPORT.md +0 -0
  54. {etlplus-0.15.5 → etlplus-0.16.2}/docs/README.md +0 -0
  55. {etlplus-0.15.5 → etlplus-0.16.2}/docs/snippets/installation_version.md +0 -0
  56. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/README.md +0 -0
  57. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/__init__.py +0 -0
  58. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/__main__.py +0 -0
  59. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/__version__.py +0 -0
  60. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/api/README.md +0 -0
  61. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/api/__init__.py +0 -0
  62. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/api/auth.py +0 -0
  63. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/api/config.py +0 -0
  64. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/api/endpoint_client.py +0 -0
  65. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/api/enums.py +0 -0
  66. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/api/errors.py +0 -0
  67. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/api/pagination/__init__.py +0 -0
  68. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/api/pagination/client.py +0 -0
  69. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/api/pagination/config.py +0 -0
  70. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/api/pagination/paginator.py +0 -0
  71. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/api/rate_limiting/__init__.py +0 -0
  72. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/api/rate_limiting/config.py +0 -0
  73. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/api/rate_limiting/rate_limiter.py +0 -0
  74. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/api/request_manager.py +0 -0
  75. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/api/retry_manager.py +0 -0
  76. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/api/transport.py +0 -0
  77. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/api/utils.py +0 -0
  78. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/cli/README.md +0 -0
  79. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/cli/__init__.py +0 -0
  80. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/cli/commands.py +0 -0
  81. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/cli/handlers.py +0 -0
  82. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/cli/io.py +0 -0
  83. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/cli/main.py +0 -0
  84. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/cli/options.py +0 -0
  85. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/cli/state.py +0 -0
  86. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/cli/types.py +0 -0
  87. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/database/README.md +0 -0
  88. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/database/__init__.py +0 -0
  89. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/database/ddl.py +0 -0
  90. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/database/engine.py +0 -0
  91. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/database/orm.py +0 -0
  92. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/database/schema.py +0 -0
  93. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/database/types.py +0 -0
  94. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/README.md +0 -0
  95. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/__init__.py +0 -0
  96. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/_imports.py +0 -0
  97. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/_io.py +0 -0
  98. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/accdb.py +0 -0
  99. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/arrow.py +0 -0
  100. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/avro.py +0 -0
  101. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/bson.py +0 -0
  102. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/cbor.py +0 -0
  103. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/cfg.py +0 -0
  104. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/conf.py +0 -0
  105. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/core.py +0 -0
  106. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/csv.py +0 -0
  107. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/dat.py +0 -0
  108. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/dta.py +0 -0
  109. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/duckdb.py +0 -0
  110. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/enums.py +0 -0
  111. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/feather.py +0 -0
  112. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/fwf.py +0 -0
  113. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/gz.py +0 -0
  114. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/hbs.py +0 -0
  115. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/hdf5.py +0 -0
  116. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/ini.py +0 -0
  117. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/ion.py +0 -0
  118. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/jinja2.py +0 -0
  119. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/json.py +0 -0
  120. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/log.py +0 -0
  121. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/mat.py +0 -0
  122. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/mdb.py +0 -0
  123. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/msgpack.py +0 -0
  124. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/mustache.py +0 -0
  125. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/nc.py +0 -0
  126. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/ndjson.py +0 -0
  127. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/numbers.py +0 -0
  128. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/ods.py +0 -0
  129. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/orc.py +0 -0
  130. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/parquet.py +0 -0
  131. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/pb.py +0 -0
  132. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/pbf.py +0 -0
  133. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/properties.py +0 -0
  134. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/proto.py +0 -0
  135. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/psv.py +0 -0
  136. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/rda.py +0 -0
  137. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/rds.py +0 -0
  138. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/sas7bdat.py +0 -0
  139. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/sav.py +0 -0
  140. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/sqlite.py +0 -0
  141. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/stub.py +0 -0
  142. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/sylk.py +0 -0
  143. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/tab.py +0 -0
  144. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/toml.py +0 -0
  145. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/tsv.py +0 -0
  146. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/txt.py +0 -0
  147. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/vm.py +0 -0
  148. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/wks.py +0 -0
  149. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/xls.py +0 -0
  150. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/xlsm.py +0 -0
  151. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/xlsx.py +0 -0
  152. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/xml.py +0 -0
  153. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/xpt.py +0 -0
  154. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/yaml.py +0 -0
  155. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/zip.py +0 -0
  156. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/file/zsav.py +0 -0
  157. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/mixins.py +0 -0
  158. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/ops/README.md +0 -0
  159. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/ops/__init__.py +0 -0
  160. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/ops/utils.py +0 -0
  161. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/ops/validate.py +0 -0
  162. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/py.typed +0 -0
  163. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/templates/README.md +0 -0
  164. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/templates/__init__.py +0 -0
  165. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/templates/ddl.sql.j2 +0 -0
  166. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/templates/view.sql.j2 +0 -0
  167. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/utils.py +0 -0
  168. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus/workflow/README.md +0 -0
  169. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus.egg-info/dependency_links.txt +0 -0
  170. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus.egg-info/entry_points.txt +0 -0
  171. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus.egg-info/requires.txt +0 -0
  172. {etlplus-0.15.5 → etlplus-0.16.2}/etlplus.egg-info/top_level.txt +0 -0
  173. {etlplus-0.15.5 → etlplus-0.16.2}/examples/README.md +0 -0
  174. {etlplus-0.15.5 → etlplus-0.16.2}/examples/configs/ddl_spec.yml +0 -0
  175. {etlplus-0.15.5 → etlplus-0.16.2}/examples/configs/pipeline.yml +0 -0
  176. {etlplus-0.15.5 → etlplus-0.16.2}/examples/data/sample.csv +0 -0
  177. {etlplus-0.15.5 → etlplus-0.16.2}/examples/data/sample.json +0 -0
  178. {etlplus-0.15.5 → etlplus-0.16.2}/examples/data/sample.xml +0 -0
  179. {etlplus-0.15.5 → etlplus-0.16.2}/examples/data/sample.xsd +0 -0
  180. {etlplus-0.15.5 → etlplus-0.16.2}/examples/data/sample.yaml +0 -0
  181. {etlplus-0.15.5 → etlplus-0.16.2}/examples/quickstart_python.py +0 -0
  182. {etlplus-0.15.5 → etlplus-0.16.2}/pyproject.toml +0 -0
  183. {etlplus-0.15.5 → etlplus-0.16.2}/pytest.ini +0 -0
  184. {etlplus-0.15.5 → etlplus-0.16.2}/setup.cfg +0 -0
  185. {etlplus-0.15.5 → etlplus-0.16.2}/setup.py +0 -0
  186. {etlplus-0.15.5 → etlplus-0.16.2}/tests/__init__.py +0 -0
  187. {etlplus-0.15.5 → etlplus-0.16.2}/tests/conftest.py +0 -0
  188. {etlplus-0.15.5 → etlplus-0.16.2}/tests/integration/test_i_cli.py +0 -0
  189. {etlplus-0.15.5 → etlplus-0.16.2}/tests/integration/test_i_examples_data_parity.py +0 -0
  190. {etlplus-0.15.5 → etlplus-0.16.2}/tests/integration/test_i_pagination_strategy.py +0 -0
  191. {etlplus-0.15.5 → etlplus-0.16.2}/tests/integration/test_i_pipeline_smoke.py +0 -0
  192. {etlplus-0.15.5 → etlplus-0.16.2}/tests/integration/test_i_pipeline_yaml_load.py +0 -0
  193. {etlplus-0.15.5 → etlplus-0.16.2}/tests/integration/test_i_run.py +0 -0
  194. {etlplus-0.15.5 → etlplus-0.16.2}/tests/integration/test_i_run_profile_pagination_defaults.py +0 -0
  195. {etlplus-0.15.5 → etlplus-0.16.2}/tests/integration/test_i_run_profile_rate_limit_defaults.py +0 -0
  196. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/api/conftest.py +0 -0
  197. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/api/test_u_api_enums.py +0 -0
  198. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/api/test_u_api_utils.py +0 -0
  199. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/api/test_u_auth.py +0 -0
  200. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/api/test_u_config.py +0 -0
  201. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/api/test_u_endpoint_client.py +0 -0
  202. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/api/test_u_mocks.py +0 -0
  203. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/api/test_u_pagination_client.py +0 -0
  204. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/api/test_u_pagination_config.py +0 -0
  205. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/api/test_u_paginator.py +0 -0
  206. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/api/test_u_rate_limit_config.py +0 -0
  207. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/api/test_u_rate_limiter.py +0 -0
  208. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/api/test_u_request_manager.py +0 -0
  209. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/api/test_u_retry_manager.py +0 -0
  210. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/api/test_u_transport.py +0 -0
  211. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/api/test_u_types.py +0 -0
  212. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/cli/conftest.py +0 -0
  213. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/cli/test_u_cli_handlers.py +0 -0
  214. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/cli/test_u_cli_io.py +0 -0
  215. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/cli/test_u_cli_main.py +0 -0
  216. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/cli/test_u_cli_state.py +0 -0
  217. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/conftest.py +0 -0
  218. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/database/test_u_database_ddl.py +0 -0
  219. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/database/test_u_database_engine.py +0 -0
  220. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/database/test_u_database_orm.py +0 -0
  221. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/database/test_u_database_schema.py +0 -0
  222. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/file/test_u_file_core.py +0 -0
  223. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/file/test_u_file_enums.py +0 -0
  224. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/file/test_u_file_yaml.py +0 -0
  225. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/ops/test_u_ops_extract.py +0 -0
  226. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/ops/test_u_ops_transform.py +0 -0
  227. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/ops/test_u_ops_utils.py +0 -0
  228. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/ops/test_u_ops_validate.py +0 -0
  229. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/test_u_main.py +0 -0
  230. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/test_u_mixins.py +0 -0
  231. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/test_u_utils.py +0 -0
  232. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/test_u_version.py +0 -0
  233. {etlplus-0.15.5 → etlplus-0.16.2}/tests/unit/workflow/test_u_workflow_jobs.py +0 -0
  234. {etlplus-0.15.5 → etlplus-0.16.2}/tools/update_demo_snippets.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: etlplus
3
- Version: 0.15.5
3
+ Version: 0.16.2
4
4
  Summary: A Swiss Army knife for simple ETL operations
5
5
  Home-page: https://github.com/Dagitali/ETLPlus
6
6
  Author: ETLPlus Team
@@ -377,9 +377,9 @@ Details:
377
377
  - Unknown or malformed entries are skipped rather than failing the whole load (keeping pipeline
378
378
  authoring permissive).
379
379
  - The connector kind is also available as a type-safe literal in code as
380
- `etlplus.workflow.ConnectorType` (values: `"file" | "database" | "api"`).
380
+ `etlplus.connector.ConnectorType` (values: `"file" | "database" | "api"`).
381
381
 
382
- To add new connector kinds in the future, implement a new dataclass in `etlplus.workflow.connector`
382
+ To add new connector kinds in the future, implement a new dataclass in `etlplus.connector`
383
383
  and extend the internal parser to handle its `type` value.
384
384
 
385
385
  ## Jobs
@@ -53,7 +53,31 @@ __all__ = [
53
53
  # SECTION: CONSTANTS ======================================================== #
54
54
 
55
55
 
56
- _UNSET = object()
56
+ _UNSET: object = object()
57
+
58
+
59
+ # SECTION: INTERNAL FUNCTIONS =============================================== #
60
+
61
+
62
+ def _to_dict(
63
+ value: Mapping[str, Any] | object | None,
64
+ ) -> dict[str, Any] | None:
65
+ """
66
+ Return a defensive ``dict`` copy for mapping inputs.
67
+
68
+ Parameters
69
+ ----------
70
+ value : Mapping[str, Any] | object | None
71
+ Mapping to copy, or ``None``.
72
+
73
+ Returns
74
+ -------
75
+ dict[str, Any] | None
76
+ New ``dict`` instance or ``None`` when the input is ``None``.
77
+ """
78
+ if value is None:
79
+ return None
80
+ return cast(dict[str, Any], value)
57
81
 
58
82
 
59
83
  # SECTION: TYPED DICTS ====================================================== #
@@ -176,9 +200,9 @@ class RequestOptions:
176
200
 
177
201
  def __post_init__(self) -> None:
178
202
  if self.params is not None:
179
- object.__setattr__(self, 'params', dict(self.params))
203
+ object.__setattr__(self, 'params', _to_dict(self.params))
180
204
  if self.headers is not None:
181
- object.__setattr__(self, 'headers', dict(self.headers))
205
+ object.__setattr__(self, 'headers', _to_dict(self.headers))
182
206
 
183
207
  # -- Instance Methods -- #
184
208
 
@@ -224,23 +248,20 @@ class RequestOptions:
224
248
 
225
249
  Returns
226
250
  -------
227
- RequestOptions
251
+ Self
228
252
  New snapshot reflecting the provided overrides.
229
253
  """
230
254
  if params is _UNSET:
231
255
  next_params = self.params
232
- elif params is None:
233
- next_params = None
234
256
  else:
235
- next_params = cast(dict, params)
257
+ # next_params = _to_dict(params) if params is not None else None
258
+ next_params = _to_dict(params)
236
259
 
237
260
  if headers is _UNSET:
238
261
  next_headers = self.headers
239
- elif headers is None:
240
- next_headers = None
241
262
  else:
242
- next_headers = cast(dict, headers)
243
-
263
+ # next_headers = _to_dict(headers) if headers is not None else None
264
+ next_headers = _to_dict(headers)
244
265
  if timeout is _UNSET:
245
266
  next_timeout = self.timeout
246
267
  else:
@@ -8,7 +8,7 @@ from __future__ import annotations
8
8
 
9
9
  from typing import Final
10
10
 
11
- from ..enums import DataConnectorType
11
+ from ..connector import DataConnectorType
12
12
  from ..file import FileFormat
13
13
 
14
14
  # SECTION: EXPORTS ========================================================== #
@@ -0,0 +1,43 @@
1
+ """
2
+ :mod:`etlplus.connector` package.
3
+
4
+ Connector configuration types and enums.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from .api import ConnectorApi
10
+ from .api import ConnectorApiConfigMap
11
+ from .connector import Connector
12
+ from .core import ConnectorBase
13
+ from .core import ConnectorProtocol
14
+ from .database import ConnectorDb
15
+ from .database import ConnectorDbConfigMap
16
+ from .enums import DataConnectorType
17
+ from .file import ConnectorFile
18
+ from .file import ConnectorFileConfigMap
19
+ from .types import ConnectorType
20
+ from .utils import parse_connector
21
+
22
+ # SECTION: EXPORTS ========================================================== #
23
+
24
+
25
+ __all__ = [
26
+ # Data Classes
27
+ 'ConnectorApi',
28
+ 'ConnectorDb',
29
+ 'ConnectorFile',
30
+ # Enums
31
+ 'DataConnectorType',
32
+ # Functions
33
+ 'parse_connector',
34
+ # Type Aliases
35
+ 'Connector',
36
+ 'ConnectorBase',
37
+ 'ConnectorProtocol',
38
+ 'ConnectorType',
39
+ # Typed Dicts
40
+ 'ConnectorApiConfigMap',
41
+ 'ConnectorDbConfigMap',
42
+ 'ConnectorFileConfigMap',
43
+ ]
@@ -0,0 +1,161 @@
1
+ """
2
+ :mod:`etlplus.connector.api` module.
3
+
4
+ API connector configuration dataclass.
5
+
6
+ Notes
7
+ -----
8
+ - TypedDicts in this module are intentionally ``total=False`` and are not
9
+ enforced at runtime.
10
+ - :meth:`*.from_obj` constructors accept :class:`Mapping[str, Any]` and perform
11
+ tolerant parsing and light casting. This keeps the runtime permissive while
12
+ improving autocomplete and static analysis for contributors.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ from dataclasses import dataclass
18
+ from dataclasses import field
19
+ from typing import Any
20
+ from typing import Self
21
+ from typing import TypedDict
22
+ from typing import overload
23
+
24
+ from ..api import PaginationConfig
25
+ from ..api import PaginationConfigMap
26
+ from ..api import RateLimitConfig
27
+ from ..api import RateLimitConfigMap
28
+ from ..types import StrAnyMap
29
+ from ..types import StrStrMap
30
+ from ..utils import cast_str_dict
31
+ from ..utils import coerce_dict
32
+ from ..utils import maybe_mapping
33
+ from .core import ConnectorBase
34
+ from .enums import DataConnectorType
35
+ from .types import ConnectorType
36
+
37
+ # SECTION: EXPORTS ========================================================== #
38
+
39
+
40
+ __all__ = [
41
+ 'ConnectorApi',
42
+ 'ConnectorApiConfigMap',
43
+ ]
44
+
45
+
46
+ # SECTION: TYPED DICTS ====================================================== #
47
+
48
+
49
+ class ConnectorApiConfigMap(TypedDict, total=False):
50
+ """
51
+ Shape accepted by :meth:`ConnectorApi.from_obj` (all keys optional).
52
+
53
+ See Also
54
+ --------
55
+ - :meth:`etlplus.connector.api.ConnectorApi.from_obj`
56
+ """
57
+
58
+ name: str
59
+ type: ConnectorType
60
+ url: str
61
+ method: str
62
+ headers: StrStrMap
63
+ query_params: StrAnyMap
64
+ pagination: PaginationConfigMap
65
+ rate_limit: RateLimitConfigMap
66
+ api: str
67
+ endpoint: str
68
+
69
+
70
+ # SECTION: DATA CLASSES ===================================================== #
71
+
72
+
73
+ @dataclass(kw_only=True, slots=True)
74
+ class ConnectorApi(ConnectorBase):
75
+ """
76
+ Configuration for an API-based data connector.
77
+
78
+ Attributes
79
+ ----------
80
+ type : ConnectorType
81
+ Connector kind, always ``'api'``.
82
+ url : str | None
83
+ Direct absolute URL (when not using ``service``/``endpoint`` refs).
84
+ method : str | None
85
+ Optional HTTP method; typically omitted for sources (defaults to
86
+ GET) and used for targets (e.g., ``'post'``).
87
+ headers : dict[str, str]
88
+ Additional request headers.
89
+ query_params : dict[str, Any]
90
+ Default query parameters.
91
+ pagination : PaginationConfig | None
92
+ Pagination settings (optional).
93
+ rate_limit : RateLimitConfig | None
94
+ Rate limiting settings (optional).
95
+ api : str | None
96
+ Service reference into the pipeline ``apis`` block (a.k.a.
97
+ ``service``).
98
+ endpoint : str | None
99
+ Endpoint name within the referenced service.
100
+ """
101
+
102
+ # -- Attributes -- #
103
+
104
+ type: ConnectorType = DataConnectorType.API
105
+
106
+ # Direct form
107
+ url: str | None = None
108
+ # Optional HTTP method; typically omitted for sources (defaults to GET)
109
+ # at runtime) and used for targets (e.g., 'post', 'put').
110
+ method: str | None = None
111
+ headers: dict[str, str] = field(default_factory=dict)
112
+ query_params: dict[str, Any] = field(default_factory=dict)
113
+ pagination: PaginationConfig | None = None
114
+ rate_limit: RateLimitConfig | None = None
115
+
116
+ # Reference form (to top-level APIs/endpoints)
117
+ api: str | None = None
118
+ endpoint: str | None = None
119
+
120
+ # -- Class Methods -- #
121
+
122
+ @classmethod
123
+ @overload
124
+ def from_obj(cls, obj: ConnectorApiConfigMap) -> Self: ...
125
+
126
+ @classmethod
127
+ @overload
128
+ def from_obj(cls, obj: StrAnyMap) -> Self: ...
129
+
130
+ @classmethod
131
+ def from_obj(
132
+ cls,
133
+ obj: StrAnyMap,
134
+ ) -> Self:
135
+ """
136
+ Parse a mapping into a ``ConnectorApi`` instance.
137
+
138
+ Parameters
139
+ ----------
140
+ obj : StrAnyMap
141
+ Mapping with at least ``name``.
142
+
143
+ Returns
144
+ -------
145
+ Self
146
+ Parsed connector instance.
147
+ """
148
+ name = cls._require_name(obj, kind='Api')
149
+ headers = cast_str_dict(maybe_mapping(obj.get('headers')))
150
+
151
+ return cls(
152
+ name=name,
153
+ url=obj.get('url'),
154
+ method=obj.get('method'),
155
+ headers=headers,
156
+ query_params=coerce_dict(obj.get('query_params')),
157
+ pagination=PaginationConfig.from_obj(obj.get('pagination')),
158
+ rate_limit=RateLimitConfig.from_obj(obj.get('rate_limit')),
159
+ api=obj.get('api') or obj.get('service'),
160
+ endpoint=obj.get('endpoint'),
161
+ )
@@ -0,0 +1,26 @@
1
+ """
2
+ :mod:`etlplus.connector.connector` module.
3
+
4
+ Compatibility re-exports for connector configuration classes.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from .api import ConnectorApi
10
+ from .database import ConnectorDb
11
+ from .file import ConnectorFile
12
+
13
+ # SECTION: EXPORTS ========================================================== #
14
+
15
+
16
+ __all__ = [
17
+ # Type aliases
18
+ 'Connector',
19
+ ]
20
+
21
+
22
+ # SECTION: TYPED ALIASES ==================================================== #
23
+
24
+
25
+ # Type alias representing any supported connector
26
+ type Connector = ConnectorApi | ConnectorDb | ConnectorFile
@@ -0,0 +1,132 @@
1
+ """
2
+ :mod:`etlplus.connector.core` module.
3
+
4
+ Protocols and base classes for connector implementations.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from abc import ABC
10
+ from abc import abstractmethod
11
+ from dataclasses import dataclass
12
+ from typing import Protocol
13
+ from typing import Self
14
+ from typing import runtime_checkable
15
+
16
+ from ..types import StrAnyMap
17
+ from .types import ConnectorType
18
+
19
+ # SECTION: EXPORTS ========================================================== #
20
+
21
+
22
+ __all__ = [
23
+ 'ConnectorBase',
24
+ 'ConnectorProtocol',
25
+ ]
26
+
27
+
28
+ # SECTION: PROTOCOLS ======================================================== #
29
+
30
+
31
+ @runtime_checkable
32
+ class ConnectorProtocol(Protocol):
33
+ """
34
+ Structural contract for connector implementations.
35
+
36
+ Attributes
37
+ ----------
38
+ name : str
39
+ Unique connector name.
40
+ type : ConnectorType
41
+ Connector kind.
42
+ """
43
+
44
+ # -- Attributes -- #
45
+
46
+ name: str
47
+ type: ConnectorType
48
+
49
+ # -- Class Methods -- #
50
+
51
+ @classmethod
52
+ def from_obj(cls, obj: StrAnyMap) -> Self:
53
+ """
54
+ Parse a mapping into a connector instance.
55
+
56
+ Parameters
57
+ ----------
58
+ obj : StrAnyMap
59
+ Mapping with at least ``name``.
60
+
61
+ Returns
62
+ -------
63
+ Self
64
+ Parsed connector instance.
65
+ """
66
+ ...
67
+
68
+ # -- Internal Static Methods -- #
69
+
70
+ @staticmethod
71
+ def _require_name(obj: StrAnyMap, *, kind: str) -> str:
72
+ """
73
+ Extract and validate the ``name`` field from connector mappings.
74
+
75
+ Parameters
76
+ ----------
77
+ obj : StrAnyMap
78
+ Connector mapping with a ``name`` entry.
79
+ kind : str
80
+ Connector kind used in the error message.
81
+
82
+ Returns
83
+ -------
84
+ str
85
+ Valid connector name.
86
+
87
+ Raises
88
+ ------
89
+ TypeError
90
+ If ``name`` is missing or not a string.
91
+ """
92
+ name = obj.get('name')
93
+ if not isinstance(name, str):
94
+ raise TypeError(f'Connector{kind} requires a "name" (str)')
95
+ return name
96
+
97
+
98
+ # SECTION: ABSTRACT BASE DATA CLASSES ======================================= #
99
+
100
+
101
+ @dataclass(kw_only=True, slots=True)
102
+ class ConnectorBase(ABC, ConnectorProtocol):
103
+ """
104
+ Abstract base class for connector implementations.
105
+
106
+ Attributes
107
+ ----------
108
+ name : str
109
+ Unique connector name.
110
+ type : ConnectorType
111
+ Connector kind.
112
+ """
113
+
114
+ name: str
115
+ type: ConnectorType
116
+
117
+ @classmethod
118
+ @abstractmethod
119
+ def from_obj(cls, obj: StrAnyMap) -> Self:
120
+ """
121
+ Parse a mapping into a connector instance.
122
+
123
+ Parameters
124
+ ----------
125
+ obj : StrAnyMap
126
+ Mapping with at least ``name``.
127
+
128
+ Returns
129
+ -------
130
+ Self
131
+ Parsed connector instance.
132
+ """
@@ -0,0 +1,122 @@
1
+ """
2
+ :mod:`etlplus.connector.database` module.
3
+
4
+ Database connector configuration dataclass.
5
+
6
+ Notes
7
+ -----
8
+ - TypedDicts in this module are intentionally ``total=False`` and are not
9
+ enforced at runtime.
10
+ - :meth:`*.from_obj` constructors accept :class:`Mapping[str, Any]` and perform
11
+ tolerant parsing and light casting. This keeps the runtime permissive while
12
+ improving autocomplete and static analysis for contributors.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ from dataclasses import dataclass
18
+ from typing import Self
19
+ from typing import TypedDict
20
+ from typing import overload
21
+
22
+ from ..types import StrAnyMap
23
+ from .core import ConnectorBase
24
+ from .enums import DataConnectorType
25
+ from .types import ConnectorType
26
+
27
+ # SECTION: EXPORTS ========================================================== #
28
+
29
+
30
+ __all__ = [
31
+ 'ConnectorDb',
32
+ 'ConnectorDbConfigMap',
33
+ ]
34
+
35
+
36
+ # SECTION: TYPED DICTS ====================================================== #
37
+
38
+
39
+ class ConnectorDbConfigMap(TypedDict, total=False):
40
+ """
41
+ Shape accepted by :meth:`ConnectorDb.from_obj` (all keys optional).
42
+
43
+ See Also
44
+ --------
45
+ - :meth:`etlplus.connector.database.ConnectorDb.from_obj`
46
+ """
47
+
48
+ name: str
49
+ type: ConnectorType
50
+ connection_string: str
51
+ query: str
52
+ table: str
53
+ mode: str
54
+
55
+
56
+ # SECTION: DATA CLASSES ===================================================== #
57
+
58
+
59
+ @dataclass(kw_only=True, slots=True)
60
+ class ConnectorDb(ConnectorBase):
61
+ """
62
+ Configuration for a database-based data connector.
63
+
64
+ Attributes
65
+ ----------
66
+ type : ConnectorType
67
+ Connector kind, always ``'database'``.
68
+ connection_string : str | None
69
+ Connection string/DSN for the database.
70
+ query : str | None
71
+ Query to execute for extraction (optional).
72
+ table : str | None
73
+ Target/source table name (optional).
74
+ mode : str | None
75
+ Load mode hint (e.g., ``'append'``, ``'replace'``) - future use.
76
+ """
77
+
78
+ # -- Attributes -- #
79
+
80
+ type: ConnectorType = DataConnectorType.DATABASE
81
+ connection_string: str | None = None
82
+ query: str | None = None
83
+ table: str | None = None
84
+ mode: str | None = None # append|replace|upsert (future)
85
+
86
+ # -- Class Methods -- #
87
+
88
+ @classmethod
89
+ @overload
90
+ def from_obj(cls, obj: ConnectorDbConfigMap) -> Self: ...
91
+
92
+ @classmethod
93
+ @overload
94
+ def from_obj(cls, obj: StrAnyMap) -> Self: ...
95
+
96
+ @classmethod
97
+ def from_obj(
98
+ cls,
99
+ obj: StrAnyMap,
100
+ ) -> Self:
101
+ """
102
+ Parse a mapping into a ``ConnectorDb`` instance.
103
+
104
+ Parameters
105
+ ----------
106
+ obj : StrAnyMap
107
+ Mapping with at least ``name``.
108
+
109
+ Returns
110
+ -------
111
+ Self
112
+ Parsed connector instance.
113
+ """
114
+ name = cls._require_name(obj, kind='Db')
115
+
116
+ return cls(
117
+ name=name,
118
+ connection_string=obj.get('connection_string'),
119
+ query=obj.get('query'),
120
+ table=obj.get('table'),
121
+ mode=obj.get('mode'),
122
+ )
@@ -0,0 +1,52 @@
1
+ """
2
+ :mod:`etlplus.connector.enums` module.
3
+
4
+ Connector enums and helpers.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from ..enums import CoercibleStrEnum
10
+ from ..types import StrStrMap
11
+
12
+ # SECTION: EXPORTS ========================================================= #
13
+
14
+
15
+ __all__ = [
16
+ # Enums
17
+ 'DataConnectorType',
18
+ ]
19
+
20
+
21
+ # SECTION: ENUMS ============================================================ #
22
+
23
+
24
+ class DataConnectorType(CoercibleStrEnum):
25
+ """Supported data connector types."""
26
+
27
+ # -- Constants -- #
28
+
29
+ API = 'api'
30
+ DATABASE = 'database'
31
+ FILE = 'file'
32
+
33
+ # -- Class Methods -- #
34
+
35
+ @classmethod
36
+ def aliases(cls) -> StrStrMap:
37
+ """
38
+ Return a mapping of common aliases for each enum member.
39
+
40
+ Returns
41
+ -------
42
+ StrStrMap
43
+ A mapping of alias names to their corresponding enum member names.
44
+ """
45
+ return {
46
+ 'http': 'api',
47
+ 'https': 'api',
48
+ 'rest': 'api',
49
+ 'db': 'database',
50
+ 'filesystem': 'file',
51
+ 'fs': 'file',
52
+ }