etlplus 0.10.1__tar.gz → 0.10.4__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 (150) hide show
  1. {etlplus-0.10.1/etlplus.egg-info → etlplus-0.10.4}/PKG-INFO +1 -1
  2. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/enums.py +37 -3
  3. {etlplus-0.10.1 → etlplus-0.10.4/etlplus.egg-info}/PKG-INFO +1 -1
  4. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/test_u_enums.py +17 -9
  5. {etlplus-0.10.1 → etlplus-0.10.4}/.coveragerc +0 -0
  6. {etlplus-0.10.1 → etlplus-0.10.4}/.editorconfig +0 -0
  7. {etlplus-0.10.1 → etlplus-0.10.4}/.gitattributes +0 -0
  8. {etlplus-0.10.1 → etlplus-0.10.4}/.github/actions/python-bootstrap/action.yml +0 -0
  9. {etlplus-0.10.1 → etlplus-0.10.4}/.github/workflows/ci.yml +0 -0
  10. {etlplus-0.10.1 → etlplus-0.10.4}/.gitignore +0 -0
  11. {etlplus-0.10.1 → etlplus-0.10.4}/.pre-commit-config.yaml +0 -0
  12. {etlplus-0.10.1 → etlplus-0.10.4}/.ruff.toml +0 -0
  13. {etlplus-0.10.1 → etlplus-0.10.4}/CODE_OF_CONDUCT.md +0 -0
  14. {etlplus-0.10.1 → etlplus-0.10.4}/CONTRIBUTING.md +0 -0
  15. {etlplus-0.10.1 → etlplus-0.10.4}/DEMO.md +0 -0
  16. {etlplus-0.10.1 → etlplus-0.10.4}/LICENSE +0 -0
  17. {etlplus-0.10.1 → etlplus-0.10.4}/MANIFEST.in +0 -0
  18. {etlplus-0.10.1 → etlplus-0.10.4}/Makefile +0 -0
  19. {etlplus-0.10.1 → etlplus-0.10.4}/README.md +0 -0
  20. {etlplus-0.10.1 → etlplus-0.10.4}/REFERENCES.md +0 -0
  21. {etlplus-0.10.1 → etlplus-0.10.4}/docs/README.md +0 -0
  22. {etlplus-0.10.1 → etlplus-0.10.4}/docs/pipeline-guide.md +0 -0
  23. {etlplus-0.10.1 → etlplus-0.10.4}/docs/snippets/installation_version.md +0 -0
  24. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/__init__.py +0 -0
  25. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/__main__.py +0 -0
  26. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/__version__.py +0 -0
  27. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/api/README.md +0 -0
  28. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/api/__init__.py +0 -0
  29. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/api/auth.py +0 -0
  30. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/api/config.py +0 -0
  31. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/api/endpoint_client.py +0 -0
  32. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/api/errors.py +0 -0
  33. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/api/pagination/__init__.py +0 -0
  34. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/api/pagination/client.py +0 -0
  35. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/api/pagination/config.py +0 -0
  36. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/api/pagination/paginator.py +0 -0
  37. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/api/rate_limiting/__init__.py +0 -0
  38. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/api/rate_limiting/config.py +0 -0
  39. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/api/rate_limiting/rate_limiter.py +0 -0
  40. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/api/request_manager.py +0 -0
  41. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/api/retry_manager.py +0 -0
  42. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/api/transport.py +0 -0
  43. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/api/types.py +0 -0
  44. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/cli/__init__.py +0 -0
  45. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/cli/commands.py +0 -0
  46. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/cli/constants.py +0 -0
  47. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/cli/handlers.py +0 -0
  48. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/cli/io.py +0 -0
  49. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/cli/main.py +0 -0
  50. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/cli/options.py +0 -0
  51. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/cli/state.py +0 -0
  52. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/cli/types.py +0 -0
  53. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/config/__init__.py +0 -0
  54. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/config/connector.py +0 -0
  55. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/config/jobs.py +0 -0
  56. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/config/pipeline.py +0 -0
  57. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/config/profile.py +0 -0
  58. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/config/types.py +0 -0
  59. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/config/utils.py +0 -0
  60. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/database/__init__.py +0 -0
  61. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/database/ddl.py +0 -0
  62. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/database/engine.py +0 -0
  63. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/database/orm.py +0 -0
  64. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/database/schema.py +0 -0
  65. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/database/types.py +0 -0
  66. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/extract.py +0 -0
  67. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/file.py +0 -0
  68. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/load.py +0 -0
  69. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/mixins.py +0 -0
  70. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/py.typed +0 -0
  71. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/run.py +0 -0
  72. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/run_helpers.py +0 -0
  73. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/templates/__init__.py +0 -0
  74. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/templates/ddl.sql.j2 +0 -0
  75. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/templates/view.sql.j2 +0 -0
  76. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/transform.py +0 -0
  77. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/types.py +0 -0
  78. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/utils.py +0 -0
  79. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/validate.py +0 -0
  80. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/validation/__init__.py +0 -0
  81. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus/validation/utils.py +0 -0
  82. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus.egg-info/SOURCES.txt +0 -0
  83. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus.egg-info/dependency_links.txt +0 -0
  84. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus.egg-info/entry_points.txt +0 -0
  85. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus.egg-info/requires.txt +0 -0
  86. {etlplus-0.10.1 → etlplus-0.10.4}/etlplus.egg-info/top_level.txt +0 -0
  87. {etlplus-0.10.1 → etlplus-0.10.4}/examples/README.md +0 -0
  88. {etlplus-0.10.1 → etlplus-0.10.4}/examples/configs/ddl_spec.yml +0 -0
  89. {etlplus-0.10.1 → etlplus-0.10.4}/examples/configs/pipeline.yml +0 -0
  90. {etlplus-0.10.1 → etlplus-0.10.4}/examples/data/sample.csv +0 -0
  91. {etlplus-0.10.1 → etlplus-0.10.4}/examples/data/sample.json +0 -0
  92. {etlplus-0.10.1 → etlplus-0.10.4}/examples/data/sample.xml +0 -0
  93. {etlplus-0.10.1 → etlplus-0.10.4}/examples/data/sample.xsd +0 -0
  94. {etlplus-0.10.1 → etlplus-0.10.4}/examples/data/sample.yaml +0 -0
  95. {etlplus-0.10.1 → etlplus-0.10.4}/examples/quickstart_python.py +0 -0
  96. {etlplus-0.10.1 → etlplus-0.10.4}/pyproject.toml +0 -0
  97. {etlplus-0.10.1 → etlplus-0.10.4}/pytest.ini +0 -0
  98. {etlplus-0.10.1 → etlplus-0.10.4}/setup.cfg +0 -0
  99. {etlplus-0.10.1 → etlplus-0.10.4}/setup.py +0 -0
  100. {etlplus-0.10.1 → etlplus-0.10.4}/tests/__init__.py +0 -0
  101. {etlplus-0.10.1 → etlplus-0.10.4}/tests/conftest.py +0 -0
  102. {etlplus-0.10.1 → etlplus-0.10.4}/tests/integration/conftest.py +0 -0
  103. {etlplus-0.10.1 → etlplus-0.10.4}/tests/integration/test_i_cli.py +0 -0
  104. {etlplus-0.10.1 → etlplus-0.10.4}/tests/integration/test_i_examples_data_parity.py +0 -0
  105. {etlplus-0.10.1 → etlplus-0.10.4}/tests/integration/test_i_pagination_strategy.py +0 -0
  106. {etlplus-0.10.1 → etlplus-0.10.4}/tests/integration/test_i_pipeline_smoke.py +0 -0
  107. {etlplus-0.10.1 → etlplus-0.10.4}/tests/integration/test_i_pipeline_yaml_load.py +0 -0
  108. {etlplus-0.10.1 → etlplus-0.10.4}/tests/integration/test_i_run.py +0 -0
  109. {etlplus-0.10.1 → etlplus-0.10.4}/tests/integration/test_i_run_profile_pagination_defaults.py +0 -0
  110. {etlplus-0.10.1 → etlplus-0.10.4}/tests/integration/test_i_run_profile_rate_limit_defaults.py +0 -0
  111. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/api/conftest.py +0 -0
  112. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/api/test_u_auth.py +0 -0
  113. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/api/test_u_config.py +0 -0
  114. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/api/test_u_endpoint_client.py +0 -0
  115. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/api/test_u_mocks.py +0 -0
  116. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/api/test_u_pagination_client.py +0 -0
  117. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/api/test_u_pagination_config.py +0 -0
  118. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/api/test_u_paginator.py +0 -0
  119. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/api/test_u_rate_limit_config.py +0 -0
  120. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/api/test_u_rate_limiter.py +0 -0
  121. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/api/test_u_request_manager.py +0 -0
  122. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/api/test_u_retry_manager.py +0 -0
  123. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/api/test_u_transport.py +0 -0
  124. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/api/test_u_types.py +0 -0
  125. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/cli/conftest.py +0 -0
  126. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/cli/test_u_cli_handlers.py +0 -0
  127. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/cli/test_u_cli_main.py +0 -0
  128. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/cli/test_u_cli_state.py +0 -0
  129. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/config/test_u_config_utils.py +0 -0
  130. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/config/test_u_connector.py +0 -0
  131. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/config/test_u_jobs.py +0 -0
  132. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/config/test_u_pipeline.py +0 -0
  133. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/conftest.py +0 -0
  134. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/database/test_u_database_ddl.py +0 -0
  135. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/database/test_u_database_engine.py +0 -0
  136. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/database/test_u_database_orm.py +0 -0
  137. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/database/test_u_database_schema.py +0 -0
  138. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/test_u_extract.py +0 -0
  139. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/test_u_file.py +0 -0
  140. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/test_u_load.py +0 -0
  141. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/test_u_main.py +0 -0
  142. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/test_u_mixins.py +0 -0
  143. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/test_u_run.py +0 -0
  144. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/test_u_run_helpers.py +0 -0
  145. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/test_u_transform.py +0 -0
  146. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/test_u_utils.py +0 -0
  147. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/test_u_validate.py +0 -0
  148. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/test_u_version.py +0 -0
  149. {etlplus-0.10.1 → etlplus-0.10.4}/tests/unit/validation/test_u_validation_utils.py +0 -0
  150. {etlplus-0.10.1 → etlplus-0.10.4}/tools/update_demo_snippets.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: etlplus
3
- Version: 0.10.1
3
+ Version: 0.10.4
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
@@ -300,12 +300,16 @@ class FileFormat(CoercibleStrEnum):
300
300
  '.yml': 'yaml',
301
301
  # MIME types
302
302
  'application/avro': 'avro',
303
+ 'application/csv': 'csv',
303
304
  'application/feather': 'feather',
304
305
  'application/gzip': 'gz',
305
306
  'application/json': 'json',
306
307
  'application/jsonlines': 'ndjson',
307
308
  'application/ndjson': 'ndjson',
308
309
  'application/orc': 'orc',
310
+ 'application/parquet': 'parquet',
311
+ 'application/vnd.apache.avro': 'avro',
312
+ 'application/vnd.apache.parquet': 'parquet',
309
313
  'application/vnd.apache.arrow.file': 'feather',
310
314
  'application/vnd.apache.orc': 'orc',
311
315
  'application/vnd.ms-excel': 'xls',
@@ -314,13 +318,20 @@ class FileFormat(CoercibleStrEnum):
314
318
  'officedocument.spreadsheetml.sheet'
315
319
  ): 'xlsx',
316
320
  'application/x-avro': 'avro',
321
+ 'application/x-csv': 'csv',
322
+ 'application/x-feather': 'feather',
323
+ 'application/x-orc': 'orc',
317
324
  'application/x-ndjson': 'ndjson',
318
325
  'application/x-parquet': 'parquet',
326
+ 'application/x-yaml': 'yaml',
319
327
  'application/xml': 'xml',
320
328
  'application/zip': 'zip',
321
329
  'text/csv': 'csv',
322
330
  'text/plain': 'txt',
323
331
  'text/tab-separated-values': 'tsv',
332
+ 'text/tsv': 'tsv',
333
+ 'text/xml': 'xml',
334
+ 'text/yaml': 'yaml',
324
335
  }
325
336
 
326
337
 
@@ -524,6 +535,7 @@ def coerce_http_method(
524
535
 
525
536
  def infer_file_format_and_compression(
526
537
  value: object,
538
+ filename: object | None = None,
527
539
  ) -> tuple[FileFormat | None, CompressionFormat | None]:
528
540
  """
529
541
  Infer data format and compression from a filename, extension, or MIME type.
@@ -532,6 +544,9 @@ def infer_file_format_and_compression(
532
544
  ----------
533
545
  value : object
534
546
  A filename, extension, MIME type, or existing enum member.
547
+ filename : object | None, optional
548
+ A filename to consult for extension-based inference (e.g. when
549
+ ``value`` is ``application/octet-stream``).
535
550
 
536
551
  Returns
537
552
  -------
@@ -552,10 +567,29 @@ def infer_file_format_and_compression(
552
567
  normalized = text.casefold()
553
568
  mime = normalized.split(';', 1)[0].strip()
554
569
 
570
+ is_octet_stream = mime == 'application/octet-stream'
555
571
  compression = CompressionFormat.try_coerce(mime)
556
- fmt = FileFormat.try_coerce(mime)
557
-
558
- suffixes = PurePath(text).suffixes
572
+ fmt = None if is_octet_stream else FileFormat.try_coerce(mime)
573
+
574
+ is_mime = mime.startswith(
575
+ (
576
+ 'application/',
577
+ 'text/',
578
+ 'audio/',
579
+ 'image/',
580
+ 'video/',
581
+ 'multipart/',
582
+ ),
583
+ )
584
+ suffix_source: object | None = filename if filename is not None else text
585
+ if is_mime and filename is None:
586
+ suffix_source = None
587
+
588
+ suffixes = (
589
+ PurePath(str(suffix_source)).suffixes
590
+ if suffix_source is not None
591
+ else []
592
+ )
559
593
  if suffixes:
560
594
  normalized_suffixes = [suffix.casefold() for suffix in suffixes]
561
595
  compression = (
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: etlplus
3
- Version: 0.10.1
3
+ Version: 0.10.4
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
@@ -119,25 +119,33 @@ class TestInferFileFormatAndCompression:
119
119
  """Unit test suite for :func:`infer_file_format_and_compression`."""
120
120
 
121
121
  @pytest.mark.parametrize(
122
- 'value,expected_format,expected_compression',
122
+ 'value,filename,expected_format,expected_compression',
123
123
  [
124
- ('data.csv.gz', FileFormat.CSV, CompressionFormat.GZ),
125
- ('data.jsonl.gz', FileFormat.NDJSON, CompressionFormat.GZ),
126
- ('data.zip', None, CompressionFormat.ZIP),
127
- ('application/json; charset=utf-8', FileFormat.JSON, None),
128
- ('application/gzip', None, CompressionFormat.GZ),
129
- (FileFormat.GZ, None, CompressionFormat.GZ),
130
- (CompressionFormat.ZIP, None, CompressionFormat.ZIP),
124
+ ('data.csv.gz', None, FileFormat.CSV, CompressionFormat.GZ),
125
+ ('data.jsonl.gz', None, FileFormat.NDJSON, CompressionFormat.GZ),
126
+ ('data.zip', None, None, CompressionFormat.ZIP),
127
+ ('application/json; charset=utf-8', None, FileFormat.JSON, None),
128
+ ('application/gzip', None, None, CompressionFormat.GZ),
129
+ (
130
+ 'application/octet-stream',
131
+ 'payload.csv.gz',
132
+ FileFormat.CSV,
133
+ CompressionFormat.GZ,
134
+ ),
135
+ ('application/octet-stream', None, None, None),
136
+ (FileFormat.GZ, None, None, CompressionFormat.GZ),
137
+ (CompressionFormat.ZIP, None, None, CompressionFormat.ZIP),
131
138
  ],
132
139
  )
133
140
  def test_infers_format_and_compression(
134
141
  self,
135
142
  value: object,
143
+ filename: object | None,
136
144
  expected_format: FileFormat | None,
137
145
  expected_compression: CompressionFormat | None,
138
146
  ) -> None:
139
147
  """Test mixed inputs for format and compression inference."""
140
- fmt, compression = infer_file_format_and_compression(value)
148
+ fmt, compression = infer_file_format_and_compression(value, filename)
141
149
  assert fmt is expected_format
142
150
  assert compression is expected_compression
143
151
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes