etlplus 0.16.3__py3-none-any.whl → 0.16.4__py3-none-any.whl

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.
etlplus/README.md CHANGED
@@ -31,6 +31,28 @@ assert validate(filtered, {"age": {"type": "number", "min": 0}})["valid"]
31
31
  load(filtered, "file", "output.json", file_format="json")
32
32
  ```
33
33
 
34
+ ## Loading and Validating Configs
35
+
36
+ Use the provided classes to load and validate configuration files:
37
+
38
+ ```python
39
+ from etlplus.workflow import Config
40
+
41
+ cfg = Config.from_yaml("pipeline.yml")
42
+ ```
43
+
44
+ - Supports YAML and JSON formats
45
+ - Validates against expected schema
46
+
47
+ ## Example: Loading a Pipeline Config
48
+
49
+ ```python
50
+ from etlplus.workflow import Config
51
+
52
+ config = Config.from_yaml("configs/pipeline.yml")
53
+ print(config)
54
+ ```
55
+
34
56
  ## See Also
35
57
 
36
58
  - [Top-level project README](../README.md)
etlplus/__init__.py CHANGED
@@ -5,6 +5,7 @@ Top-level facade for the ETLPlus toolkit.
5
5
  """
6
6
 
7
7
  from .__version__ import __version__
8
+ from .config import Config
8
9
 
9
10
  __author__ = 'ETLPlus Team'
10
11
 
@@ -15,4 +16,5 @@ __author__ = 'ETLPlus Team'
15
16
  __all__ = [
16
17
  '__author__',
17
18
  '__version__',
19
+ 'Config',
18
20
  ]
etlplus/cli/commands.py CHANGED
@@ -62,6 +62,16 @@ __all__ = ['app']
62
62
  # SECTION: TYPE ALIASES ==================================================== #
63
63
 
64
64
 
65
+ ConfigOption = Annotated[
66
+ str,
67
+ typer.Option(
68
+ ...,
69
+ '--config',
70
+ metavar='PATH',
71
+ help='Path to YAML-formatted configuration file.',
72
+ ),
73
+ ]
74
+
65
75
  JobOption = Annotated[
66
76
  str | None,
67
77
  typer.Option(
@@ -97,16 +107,6 @@ OutputOption = Annotated[
97
107
  ),
98
108
  ]
99
109
 
100
- PipelineConfigOption = Annotated[
101
- str,
102
- typer.Option(
103
- ...,
104
- '--config',
105
- metavar='PATH',
106
- help='Path to pipeline YAML configuration file.',
107
- ),
108
- ]
109
-
110
110
  PipelineOption = Annotated[
111
111
  str | None,
112
112
  typer.Option(
@@ -407,7 +407,7 @@ def _root(
407
407
  @app.command('check')
408
408
  def check_cmd(
409
409
  ctx: typer.Context,
410
- config: PipelineConfigOption,
410
+ config: ConfigOption,
411
411
  jobs: JobsOption = False,
412
412
  pipelines: PipelinesOption = False,
413
413
  sources: SourcesOption = False,
@@ -422,20 +422,20 @@ def check_cmd(
422
422
  ----------
423
423
  ctx : typer.Context
424
424
  The Typer context.
425
- config : PipelineConfigOption
425
+ config : ConfigOption
426
426
  Path to pipeline YAML configuration file.
427
- jobs : bool, optional
427
+ jobs : JobsOption, optional
428
428
  List available job names and exit. Default is ``False``.
429
- pipelines : bool, optional
429
+ pipelines : PipelinesOption, optional
430
430
  List ETL pipelines. Default is ``False``.
431
- sources : bool, optional
431
+ sources : SourcesOption, optional
432
432
  List data sources. Default is ``False``.
433
- summary : bool, optional
433
+ summary : SummaryOption, optional
434
434
  Show pipeline summary (name, version, sources, targets, jobs). Default
435
435
  is ``False``.
436
- targets : bool, optional
436
+ targets : TargetsOption, optional
437
437
  List data targets. Default is ``False``.
438
- transforms : bool, optional
438
+ transforms : TransformsOption, optional
439
439
  List data transforms. Default is ``False``.
440
440
 
441
441
  Returns
@@ -725,7 +725,7 @@ def render_cmd(
725
725
  @app.command('run')
726
726
  def run_cmd(
727
727
  ctx: typer.Context,
728
- config: PipelineConfigOption,
728
+ config: ConfigOption,
729
729
  job: JobOption = None,
730
730
  pipeline: PipelineOption = None,
731
731
  ) -> int:
@@ -736,11 +736,11 @@ def run_cmd(
736
736
  ----------
737
737
  ctx : typer.Context
738
738
  The Typer context.
739
- config : PipelineConfigOption
739
+ config : ConfigOption
740
740
  Path to pipeline YAML configuration file.
741
- job : str | None, optional
741
+ job : JobOption, optional
742
742
  Name of the job to run. Default is ``None``.
743
- pipeline : str | None, optional
743
+ pipeline : PipelineOption, optional
744
744
  Name of the pipeline to run. Default is ``None``.
745
745
 
746
746
  Returns
etlplus/cli/handlers.py CHANGED
@@ -14,6 +14,7 @@ from typing import Any
14
14
  from typing import Literal
15
15
  from typing import cast
16
16
 
17
+ from .. import Config
17
18
  from ..database import load_table_spec
18
19
  from ..database import render_tables
19
20
  from ..file import File
@@ -26,8 +27,6 @@ from ..ops import validate
26
27
  from ..ops.validate import FieldRules
27
28
  from ..types import JSONData
28
29
  from ..types import TemplateKey
29
- from ..workflow import PipelineConfig
30
- from ..workflow import load_pipeline_config
31
30
  from . import io as cli_io
32
31
 
33
32
  # SECTION: EXPORTS ========================================================== #
@@ -73,14 +72,14 @@ def _collect_table_specs(
73
72
  specs.append(dict(load_table_spec(Path(spec_path))))
74
73
 
75
74
  if config_path:
76
- cfg = load_pipeline_config(config_path, substitute=True)
75
+ cfg = Config.from_yaml(config_path, substitute=True)
77
76
  specs.extend(getattr(cfg, 'table_schemas', []))
78
77
 
79
78
  return specs
80
79
 
81
80
 
82
81
  def _check_sections(
83
- cfg: PipelineConfig,
82
+ cfg: Config,
84
83
  *,
85
84
  jobs: bool,
86
85
  pipelines: bool,
@@ -93,7 +92,7 @@ def _check_sections(
93
92
 
94
93
  Parameters
95
94
  ----------
96
- cfg : PipelineConfig
95
+ cfg : Config
97
96
  The loaded pipeline configuration.
98
97
  jobs : bool
99
98
  Whether to include job metadata.
@@ -133,14 +132,14 @@ def _check_sections(
133
132
 
134
133
 
135
134
  def _pipeline_summary(
136
- cfg: PipelineConfig,
135
+ cfg: Config,
137
136
  ) -> dict[str, Any]:
138
137
  """
139
138
  Return a human-friendly snapshot of a pipeline config.
140
139
 
141
140
  Parameters
142
141
  ----------
143
- cfg : PipelineConfig
142
+ cfg : Config
144
143
  The loaded pipeline configuration.
145
144
 
146
145
  Returns
@@ -229,7 +228,7 @@ def check_handler(
229
228
  Zero on success.
230
229
 
231
230
  """
232
- cfg = load_pipeline_config(config, substitute=substitute)
231
+ cfg = Config.from_yaml(config, substitute=substitute)
233
232
  if summary:
234
233
  cli_io.emit_json(_pipeline_summary(cfg), pretty=True)
235
234
  return 0
@@ -514,7 +513,7 @@ def run_handler(
514
513
  int
515
514
  Zero on success.
516
515
  """
517
- cfg = load_pipeline_config(config, substitute=True)
516
+ cfg = Config.from_yaml(config, substitute=True)
518
517
 
519
518
  job_name = job or pipeline
520
519
  if job_name:
@@ -1,7 +1,7 @@
1
1
  """
2
- :mod:`etlplus.workflow.pipeline` module.
2
+ :mod:`etlplus.config` module.
3
3
 
4
- Pipeline configuration model and helpers for job orchestration.
4
+ Configuration model and helpers for job pipeline orchestration.
5
5
 
6
6
  Notes
7
7
  -----
@@ -24,26 +24,24 @@ from pathlib import Path
24
24
  from typing import Any
25
25
  from typing import Self
26
26
 
27
- from ..api import ApiConfig
28
- from ..connector import Connector
29
- from ..connector import parse_connector
30
- from ..file import File
31
- from ..file import FileFormat
32
- from ..types import StrAnyMap
33
- from ..utils import coerce_dict
34
- from ..utils import deep_substitute
35
- from ..utils import maybe_mapping
36
- from .jobs import JobConfig
37
- from .profile import ProfileConfig
27
+ from .api import ApiConfig
28
+ from .connector import Connector
29
+ from .connector import parse_connector
30
+ from .file import File
31
+ from .file import FileFormat
32
+ from .types import StrAnyMap
33
+ from .utils import coerce_dict
34
+ from .utils import deep_substitute
35
+ from .utils import maybe_mapping
36
+ from .workflow.jobs import JobConfig
37
+ from .workflow.profile import ProfileConfig
38
38
 
39
39
  # SECTION: EXPORTS ========================================================== #
40
40
 
41
41
 
42
42
  __all__ = [
43
43
  # Data Classes
44
- 'PipelineConfig',
45
- # Functions
46
- 'load_pipeline_config',
44
+ 'Config',
47
45
  ]
48
46
 
49
47
 
@@ -126,29 +124,11 @@ def _parse_connector_entry(
126
124
  return None
127
125
 
128
126
 
129
- # SECTION: FUNCTIONS ======================================================== #
130
-
131
-
132
- def load_pipeline_config(
133
- path: Path | str,
134
- *,
135
- substitute: bool = False,
136
- env: Mapping[str, str] | None = None,
137
- ) -> PipelineConfig:
138
- """
139
- Load a pipeline YAML file into a ``PipelineConfig`` instance.
140
-
141
- Delegates to ``PipelineConfig.from_yaml`` for construction and optional
142
- variable substitution.
143
- """
144
- return PipelineConfig.from_yaml(path, substitute=substitute, env=env)
145
-
146
-
147
127
  # SECTION: DATA CLASSES ===================================================== #
148
128
 
149
129
 
150
130
  @dataclass(kw_only=True, slots=True)
151
- class PipelineConfig:
131
+ class Config:
152
132
  """
153
133
  Configuration for the data processing pipeline.
154
134
 
@@ -211,7 +191,7 @@ class PipelineConfig:
211
191
  env: Mapping[str, str] | None = None,
212
192
  ) -> Self:
213
193
  """
214
- Parse a YAML file into a ``PipelineConfig`` instance.
194
+ Parse a YAML file into a ``Config`` instance.
215
195
 
216
196
  Parameters
217
197
  ----------
@@ -259,7 +239,7 @@ class PipelineConfig:
259
239
  raw: StrAnyMap,
260
240
  ) -> Self:
261
241
  """
262
- Parse a mapping into a ``PipelineConfig`` instance.
242
+ Parse a mapping into a ``Config`` instance.
263
243
 
264
244
  Parameters
265
245
  ----------
etlplus/ops/run.py CHANGED
@@ -11,6 +11,7 @@ from typing import Final
11
11
  from typing import cast
12
12
 
13
13
  from ..api import HttpMethod
14
+ from ..config import Config
14
15
  from ..connector import DataConnectorType
15
16
  from ..file import FileFormat
16
17
  from ..ops.types import PipelineConfig
@@ -18,7 +19,6 @@ from ..types import JSONData
18
19
  from ..types import JSONDict
19
20
  from ..types import StrPath
20
21
  from ..utils import print_json
21
- from ..workflow import load_pipeline_config
22
22
  from .extract import extract
23
23
  from .extract import extract_from_api_source
24
24
  from .load import load
@@ -176,7 +176,7 @@ def run(
176
176
  If the job is not found or if there are configuration issues.
177
177
  """
178
178
  cfg_path = config_path or DEFAULT_CONFIG_PATH
179
- cfg = load_pipeline_config(cfg_path, substitute=True)
179
+ cfg = Config.from_yaml(cfg_path, substitute=True)
180
180
 
181
181
  # Lookup job by name
182
182
  if not (job_obj := next((j for j in cfg.jobs if j.name == job), None)):
etlplus/types.py CHANGED
@@ -16,7 +16,8 @@ See Also
16
16
 
17
17
  Examples
18
18
  --------
19
- >>> from etlplus.types import JSONDict, PipelineConfig
19
+ >>> from etlplus.types import JSONDict
20
+ >>> from etlplus.ops.types import PipelineConfig
20
21
  >>> payload: JSONDict = {'id': 1, 'name': 'Ada'}
21
22
  >>> isinstance(payload, dict)
22
23
  True
@@ -12,8 +12,6 @@ Back to project overview: see the top-level [README](../../README.md).
12
12
 
13
13
  - [`etlplus.workflow` Subpackage](#etlplusworkflow-subpackage)
14
14
  - [Supported Configuration Types](#supported-configuration-types)
15
- - [Loading and Validating Configs](#loading-and-validating-configs)
16
- - [Example: Loading a Pipeline Config](#example-loading-a-pipeline-config)
17
15
  - [See Also](#see-also)
18
16
 
19
17
  ## Supported Configuration Types
@@ -23,28 +21,6 @@ Back to project overview: see the top-level [README](../../README.md).
23
21
  - **Pipeline**: End-to-end pipeline configuration
24
22
  - **Profile**: User or environment-specific settings
25
23
 
26
- ## Loading and Validating Configs
27
-
28
- Use the provided classes to load and validate configuration files:
29
-
30
- ```python
31
- from etlplus.workflow import PipelineConfig
32
-
33
- cfg = PipelineConfig.from_yaml("pipeline.yml")
34
- ```
35
-
36
- - Supports YAML and JSON formats
37
- - Validates against expected schema
38
-
39
- ## Example: Loading a Pipeline Config
40
-
41
- ```python
42
- from etlplus.workflow import PipelineConfig
43
-
44
- pipeline = PipelineConfig.from_yaml("configs/pipeline.yml")
45
- print(pipeline)
46
- ```
47
-
48
24
  ## See Also
49
25
 
50
26
  - Top-level CLI and library usage in the main [README](../../README.md)
@@ -12,8 +12,6 @@ from .jobs import JobConfig
12
12
  from .jobs import LoadRef
13
13
  from .jobs import TransformRef
14
14
  from .jobs import ValidationRef
15
- from .pipeline import PipelineConfig
16
- from .pipeline import load_pipeline_config
17
15
  from .profile import ProfileConfig
18
16
 
19
17
  # SECTION: EXPORTS ========================================================== #
@@ -24,11 +22,9 @@ __all__ = [
24
22
  'ExtractRef',
25
23
  'JobConfig',
26
24
  'LoadRef',
27
- 'PipelineConfig',
28
25
  'ProfileConfig',
29
26
  'TransformRef',
30
27
  'ValidationRef',
31
28
  # Functions
32
- 'load_pipeline_config',
33
29
  'topological_sort_jobs',
34
30
  ]
etlplus/workflow/jobs.py CHANGED
@@ -6,8 +6,6 @@ transform, load).
6
6
 
7
7
  Notes
8
8
  -----
9
- - Lightweight references used inside :class:`PipelineConfig` to avoid storing
10
- large nested structures.
11
9
  - All attributes are simple and optional where appropriate, keeping parsing
12
10
  tolerant.
13
11
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: etlplus
3
- Version: 0.16.3
3
+ Version: 0.16.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
@@ -1,11 +1,12 @@
1
- etlplus/README.md,sha256=JaMSomnMsHrTruDnonHqe83Rv4K0-e7Wy46tMeVoleU,1468
2
- etlplus/__init__.py,sha256=mgTP4PJmRmsEjTCAizzzdtzAmhuHtarmPzphzdjvLgM,277
1
+ etlplus/README.md,sha256=L3un9q7Q7Mstfh0dmSjpsZMZzsOz2tvlWw4_-Y_LZEs,1887
2
+ etlplus/__init__.py,sha256=yHZt-sjjfPjB_CrNhcT9bcMlZCfwiul39ZhQ2VfxpRs,318
3
3
  etlplus/__main__.py,sha256=btoROneNiigyfBU7BSzPKZ1R9gzBMpxcpsbPwmuHwTM,479
4
4
  etlplus/__version__.py,sha256=1E0GMK_yUWCMQFKxXjTvyMwofi0qT2k4CDNiHWiymWE,327
5
+ etlplus/config.py,sha256=6BCI9hC1yWYAy5WclIHJlg90FYeWn5vAVrT1NWUTwpE,8817
5
6
  etlplus/enums.py,sha256=MfQhy3XDpN7oqLrF7_WwZojl7n8cW3RAzsZGRnAbWgc,4073
6
7
  etlplus/mixins.py,sha256=ifGpHwWv7U00yqGf-kN93vJax2IiK4jaGtTsPsO3Oak,1350
7
8
  etlplus/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- etlplus/types.py,sha256=DC9424i5qNBuCVGrfNLY3Ha2sz1mU84I0btSRAH7vrc,3428
9
+ etlplus/types.py,sha256=Op2H1dcmv0Srm9prFnBZjt7f1S4Mqrus7XrdsjoZkIM,3461
9
10
  etlplus/utils.py,sha256=X-k_Y8i6oDjlE5aQu9sw3gPw7O2ikiSn4uoheVv_ERc,17091
10
11
  etlplus/api/README.md,sha256=amxS_eIcsnNuVvD0x_w8nkyfedOTYbhlY0gGhaFg0DE,8705
11
12
  etlplus/api/__init__.py,sha256=PK2lQv1FbsE7ZZS_ejevFZQSuOUHGApBc22YfHAzMqA,4615
@@ -28,9 +29,9 @@ etlplus/api/rate_limiting/config.py,sha256=Byc_kmnwFmjjfDEFIdc_sHc7Wnjde1NGgsjPH
28
29
  etlplus/api/rate_limiting/rate_limiter.py,sha256=uYxn-l2qwLUKVclDQ3vJIIP3fozJx2JlHhz7_zyXVbA,7033
29
30
  etlplus/cli/README.md,sha256=8H_G2d3HteYIU6ReX9K9DM485QjWDT5vHMQbGD_vv20,1237
30
31
  etlplus/cli/__init__.py,sha256=J97-Rv931IL1_b4AXnB7Fbbd7HKnHBpx18NQfC_kE6c,299
31
- etlplus/cli/commands.py,sha256=HFlg29tO6Jwv1NXWAHmvniLCyRSlboL55Arn9B8nZAM,25028
32
+ etlplus/cli/commands.py,sha256=Mbnu_YYUrOumbDjkul9x5VjP8VXW5u08xNi4nLF9Yyo,25048
32
33
  etlplus/cli/constants.py,sha256=0F7dXIQKWUhhVu2Us527GJeknJIWpBqz7CK2e5OQgcE,1947
33
- etlplus/cli/handlers.py,sha256=uvbAyF6Ux8_5C-obCWZOrOP0QP0oiT-Km1hPhE8tDx0,18558
34
+ etlplus/cli/handlers.py,sha256=r06JatAUewxtZYGuu7lLWlcy4hKGQ8U-Oo_YtAuIhzI,18454
34
35
  etlplus/cli/io.py,sha256=tGGNQ4ecezqj-mD285fgBVrYdphdeqApsyV9VojOj1I,7836
35
36
  etlplus/cli/main.py,sha256=68_uJwmWajhOC9o4R_ns8IQloC9BFmAKC_9GlQOxKWg,5239
36
37
  etlplus/cli/options.py,sha256=vfXT3YLh7wG1iC-aTdSg6ItMC8l6n0Lozmy53XjqLbA,1199
@@ -120,7 +121,7 @@ etlplus/ops/__init__.py,sha256=r5_-pPhSLCD1nq1EbN0rQrLOGpudueeIxCH_JvT2bt0,1718
120
121
  etlplus/ops/enums.py,sha256=dC_8CfaTiB2i83Az-oG-2hkjMuAfDADNbcMF2f94UeU,4014
121
122
  etlplus/ops/extract.py,sha256=LOYiPrALRMF7JDBabnRF24_HKnnIcfTdfXesWdS3QZM,11020
122
123
  etlplus/ops/load.py,sha256=yicciVwomUKkdbhuRqbavKBNpT2Hg813BnQzG6IgF4o,10811
123
- etlplus/ops/run.py,sha256=2Z27ahRZGVULxDelHldHzUJ_vdbBCwlkwpm5KyKFP7U,11298
124
+ etlplus/ops/run.py,sha256=4HWelMevW0pW_76lJkoMcbzeQMiThMbxzO09wx6yoHg,11278
124
125
  etlplus/ops/transform.py,sha256=-41uw_pwOGsMTUYxtXaeYOmTF_fTkN-L4Q9KT1OFe78,25671
125
126
  etlplus/ops/types.py,sha256=Cvp8AJzJhJ1iYjyHd7j9ZLioxE2NdK__3g6fOI0qq6Q,4198
126
127
  etlplus/ops/utils.py,sha256=lJmrO1KDob-xZU8Gc2SvZvMgdYLsVoaz-fTV42KkLVo,10835
@@ -129,15 +130,14 @@ etlplus/templates/README.md,sha256=IfPXlj1TGVA-uFWosHJhE2rabFW-znxOlOMazO9Z5cE,1
129
130
  etlplus/templates/__init__.py,sha256=tsniN7XJYs3NwYxJ6c2HD5upHP3CDkLx-bQCMt97UOM,106
130
131
  etlplus/templates/ddl.sql.j2,sha256=s8fMWvcb4eaJVXkifuib1aQPljtZ8buuyB_uA-ZdU3Q,4734
131
132
  etlplus/templates/view.sql.j2,sha256=Iy8DHfhq5yyvrUKDxqp_aHIEXY4Tm6j4wT7YDEFWAhk,2180
132
- etlplus/workflow/README.md,sha256=D1oloiJCOHiqpqgv3m3qpRSIUOMIQcWtIsOPv7KkNI0,1652
133
- etlplus/workflow/__init__.py,sha256=ueothwpLruyLgr3-2hW8VT1unNyFJxdmT-l_3eB2ejc,724
133
+ etlplus/workflow/README.md,sha256=QelyVFGX-sZM9mx3v6BXkzX36hv6MI1yK4eCPSOKNwI,1050
134
+ etlplus/workflow/__init__.py,sha256=XgCQr684om0rONrQZ61yQ0r4qqFQL0iLAAB2Mn2BRSE,594
134
135
  etlplus/workflow/dag.py,sha256=-f1x8N1eb-PUuiOwEvFLmJwfR7JaMDJihlCHlhrFhgE,2937
135
- etlplus/workflow/jobs.py,sha256=5DmAzmEZV6XXQ-xzowkLxFzplIh8Eno3wuCmjy79xHw,8818
136
- etlplus/workflow/pipeline.py,sha256=PA5zhcfrk--pAg3b3x4oBf29WMj5HqR8zOozz4oEmg8,9387
136
+ etlplus/workflow/jobs.py,sha256=hLE9QJUzQaI0aOEon0P-xxxa6xHp997ANei4F310WRY,8711
137
137
  etlplus/workflow/profile.py,sha256=FQU3bzBZ9_yjKC9kCXKN1FQDS9zjNUjtWB1r3UL95_Q,1993
138
- etlplus-0.16.3.dist-info/licenses/LICENSE,sha256=MuNO63i6kWmgnV2pbP2SLqP54mk1BGmu7CmbtxMmT-U,1069
139
- etlplus-0.16.3.dist-info/METADATA,sha256=uV-JEWCscNgGsoF34kK-1TZWzWjYZKamLylPHGwhlwU,28114
140
- etlplus-0.16.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
141
- etlplus-0.16.3.dist-info/entry_points.txt,sha256=6w-2-jzuPa55spzK34h-UKh2JTEShh38adFRONNP9QE,45
142
- etlplus-0.16.3.dist-info/top_level.txt,sha256=aWWF-udn_sLGuHTM6W6MLh99ArS9ROkUWO8Mi8y1_2U,8
143
- etlplus-0.16.3.dist-info/RECORD,,
138
+ etlplus-0.16.4.dist-info/licenses/LICENSE,sha256=MuNO63i6kWmgnV2pbP2SLqP54mk1BGmu7CmbtxMmT-U,1069
139
+ etlplus-0.16.4.dist-info/METADATA,sha256=Pe-3vIQcAfTasRzy2HPq0A4cin2I5PJChAmA23S9dgo,28114
140
+ etlplus-0.16.4.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
141
+ etlplus-0.16.4.dist-info/entry_points.txt,sha256=6w-2-jzuPa55spzK34h-UKh2JTEShh38adFRONNP9QE,45
142
+ etlplus-0.16.4.dist-info/top_level.txt,sha256=aWWF-udn_sLGuHTM6W6MLh99ArS9ROkUWO8Mi8y1_2U,8
143
+ etlplus-0.16.4.dist-info/RECORD,,