etlplus 0.8.2__py3-none-any.whl → 0.8.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/api/README.md +24 -26
- etlplus/cli/commands.py +361 -136
- etlplus/cli/handlers.py +286 -82
- etlplus/cli/io.py +29 -52
- etlplus/cli/main.py +13 -331
- etlplus/cli/options.py +2 -68
- etlplus/cli/state.py +9 -85
- etlplus/utils.py +0 -31
- {etlplus-0.8.2.dist-info → etlplus-0.8.4.dist-info}/METADATA +5 -2
- {etlplus-0.8.2.dist-info → etlplus-0.8.4.dist-info}/RECORD +14 -14
- {etlplus-0.8.2.dist-info → etlplus-0.8.4.dist-info}/WHEEL +0 -0
- {etlplus-0.8.2.dist-info → etlplus-0.8.4.dist-info}/entry_points.txt +0 -0
- {etlplus-0.8.2.dist-info → etlplus-0.8.4.dist-info}/licenses/LICENSE +0 -0
- {etlplus-0.8.2.dist-info → etlplus-0.8.4.dist-info}/top_level.txt +0 -0
etlplus/cli/state.py
CHANGED
|
@@ -7,7 +7,6 @@ Shared state and helper utilities for the ``etlplus`` command-line interface
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
-
import argparse
|
|
11
10
|
import sys
|
|
12
11
|
from collections.abc import Collection
|
|
13
12
|
from dataclasses import dataclass
|
|
@@ -25,15 +24,12 @@ __all__ = [
|
|
|
25
24
|
'CliState',
|
|
26
25
|
# Functions
|
|
27
26
|
'ensure_state',
|
|
28
|
-
'format_namespace_kwargs',
|
|
29
27
|
'infer_resource_type',
|
|
30
28
|
'infer_resource_type_or_exit',
|
|
31
29
|
'infer_resource_type_soft',
|
|
32
30
|
'log_inferred_resource',
|
|
33
|
-
'ns',
|
|
34
31
|
'optional_choice',
|
|
35
32
|
'resolve_resource_type',
|
|
36
|
-
'stateful_namespace',
|
|
37
33
|
'validate_choice',
|
|
38
34
|
]
|
|
39
35
|
|
|
@@ -97,32 +93,6 @@ def ensure_state(
|
|
|
97
93
|
return ctx.obj
|
|
98
94
|
|
|
99
95
|
|
|
100
|
-
def format_namespace_kwargs(
|
|
101
|
-
*,
|
|
102
|
-
format_value: str | None,
|
|
103
|
-
default: str,
|
|
104
|
-
) -> dict[str, object]:
|
|
105
|
-
"""
|
|
106
|
-
Return common namespace kwargs for format handling.
|
|
107
|
-
|
|
108
|
-
Parameters
|
|
109
|
-
----------
|
|
110
|
-
format_value : str | None
|
|
111
|
-
The explicit format value from the CLI, or ``None`` if not provided.
|
|
112
|
-
default : str
|
|
113
|
-
The default format to use if none is provided.
|
|
114
|
-
|
|
115
|
-
Returns
|
|
116
|
-
-------
|
|
117
|
-
dict[str, object]
|
|
118
|
-
The namespace keyword arguments for format handling.
|
|
119
|
-
"""
|
|
120
|
-
return {
|
|
121
|
-
'format': (format_value or default),
|
|
122
|
-
'_format_explicit': (format_value is not None),
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
|
|
126
96
|
def infer_resource_type(
|
|
127
97
|
value: str,
|
|
128
98
|
) -> str:
|
|
@@ -236,7 +206,7 @@ def log_inferred_resource(
|
|
|
236
206
|
resource_type : str | None
|
|
237
207
|
The inferred resource type, or ``None`` if inference failed.
|
|
238
208
|
"""
|
|
239
|
-
if not state.verbose or resource_type is None:
|
|
209
|
+
if state.quiet or not state.verbose or resource_type is None:
|
|
240
210
|
return
|
|
241
211
|
print(
|
|
242
212
|
f'Inferred {role}_type={resource_type} for {role}={value}',
|
|
@@ -244,25 +214,6 @@ def log_inferred_resource(
|
|
|
244
214
|
)
|
|
245
215
|
|
|
246
216
|
|
|
247
|
-
def ns(
|
|
248
|
-
**kwargs: object,
|
|
249
|
-
) -> argparse.Namespace:
|
|
250
|
-
"""
|
|
251
|
-
Build an :class:`argparse.Namespace` for the legacy handlers.
|
|
252
|
-
|
|
253
|
-
Parameters
|
|
254
|
-
----------
|
|
255
|
-
**kwargs : object
|
|
256
|
-
Keyword arguments to include in the namespace.
|
|
257
|
-
|
|
258
|
-
Returns
|
|
259
|
-
-------
|
|
260
|
-
argparse.Namespace
|
|
261
|
-
The constructed namespace.
|
|
262
|
-
"""
|
|
263
|
-
return argparse.Namespace(**kwargs)
|
|
264
|
-
|
|
265
|
-
|
|
266
217
|
def optional_choice(
|
|
267
218
|
value: str | None,
|
|
268
219
|
choices: Collection[str],
|
|
@@ -342,40 +293,8 @@ def resolve_resource_type(
|
|
|
342
293
|
return validate_choice(candidate, DATA_CONNECTORS, label=label)
|
|
343
294
|
|
|
344
295
|
|
|
345
|
-
def stateful_namespace(
|
|
346
|
-
state: CliState,
|
|
347
|
-
*,
|
|
348
|
-
command: str,
|
|
349
|
-
**kwargs: object,
|
|
350
|
-
) -> argparse.Namespace:
|
|
351
|
-
"""
|
|
352
|
-
Attach CLI state toggles to a handler namespace.
|
|
353
|
-
|
|
354
|
-
Parameters
|
|
355
|
-
----------
|
|
356
|
-
state : CliState
|
|
357
|
-
The current CLI state.
|
|
358
|
-
command : str
|
|
359
|
-
The command name.
|
|
360
|
-
**kwargs : object
|
|
361
|
-
Additional keyword arguments for the namespace.
|
|
362
|
-
|
|
363
|
-
Returns
|
|
364
|
-
-------
|
|
365
|
-
argparse.Namespace
|
|
366
|
-
The constructed namespace with state toggles.
|
|
367
|
-
"""
|
|
368
|
-
return ns(
|
|
369
|
-
command=command,
|
|
370
|
-
pretty=state.pretty,
|
|
371
|
-
quiet=state.quiet,
|
|
372
|
-
verbose=state.verbose,
|
|
373
|
-
**kwargs,
|
|
374
|
-
)
|
|
375
|
-
|
|
376
|
-
|
|
377
296
|
def validate_choice(
|
|
378
|
-
value: str,
|
|
297
|
+
value: str | object,
|
|
379
298
|
choices: Collection[str],
|
|
380
299
|
*,
|
|
381
300
|
label: str,
|
|
@@ -402,8 +321,13 @@ def validate_choice(
|
|
|
402
321
|
typer.BadParameter
|
|
403
322
|
If the input value is not in the set of valid choices.
|
|
404
323
|
"""
|
|
405
|
-
v = (value or '').strip()
|
|
406
|
-
|
|
324
|
+
v = str(value or '').strip().lower()
|
|
325
|
+
normalized_choices = {c.lower() for c in choices}
|
|
326
|
+
if v in normalized_choices:
|
|
327
|
+
# Preserve original casing from choices when possible for messages
|
|
328
|
+
for choice in choices:
|
|
329
|
+
if choice.lower() == v:
|
|
330
|
+
return choice
|
|
407
331
|
return v
|
|
408
332
|
allowed = ', '.join(sorted(choices))
|
|
409
333
|
raise typer.BadParameter(
|
etlplus/utils.py
CHANGED
|
@@ -6,7 +6,6 @@ Small shared helpers used across modules.
|
|
|
6
6
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
|
-
import argparse
|
|
10
9
|
import json
|
|
11
10
|
from collections.abc import Callable
|
|
12
11
|
from collections.abc import Mapping
|
|
@@ -22,7 +21,6 @@ from .types import StrAnyMap
|
|
|
22
21
|
__all__ = [
|
|
23
22
|
# Data utilities
|
|
24
23
|
'count_records',
|
|
25
|
-
'json_type',
|
|
26
24
|
'print_json',
|
|
27
25
|
# Mapping utilities
|
|
28
26
|
'cast_str_dict',
|
|
@@ -119,35 +117,6 @@ def count_records(
|
|
|
119
117
|
return len(data) if isinstance(data, list) else 1
|
|
120
118
|
|
|
121
119
|
|
|
122
|
-
def json_type(
|
|
123
|
-
option: str,
|
|
124
|
-
) -> Any:
|
|
125
|
-
"""
|
|
126
|
-
Argparse ``type=`` hook that parses a JSON string.
|
|
127
|
-
|
|
128
|
-
Parameters
|
|
129
|
-
----------
|
|
130
|
-
option : str
|
|
131
|
-
Raw CLI string to parse as JSON.
|
|
132
|
-
|
|
133
|
-
Returns
|
|
134
|
-
-------
|
|
135
|
-
Any
|
|
136
|
-
Parsed JSON value.
|
|
137
|
-
|
|
138
|
-
Raises
|
|
139
|
-
------
|
|
140
|
-
argparse.ArgumentTypeError
|
|
141
|
-
If the input cannot be parsed as JSON.
|
|
142
|
-
"""
|
|
143
|
-
try:
|
|
144
|
-
return json.loads(option)
|
|
145
|
-
except json.JSONDecodeError as e: # pragma: no cover - argparse path
|
|
146
|
-
raise argparse.ArgumentTypeError(
|
|
147
|
-
f'Invalid JSON: {e.msg} (pos {e.pos})',
|
|
148
|
-
) from e
|
|
149
|
-
|
|
150
|
-
|
|
151
120
|
def maybe_mapping(
|
|
152
121
|
value: Any,
|
|
153
122
|
) -> StrAnyMap | None:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: etlplus
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.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
|
|
@@ -64,7 +64,7 @@ package and command-line interface for data extraction, validation, transformati
|
|
|
64
64
|
- [Quickstart](#quickstart)
|
|
65
65
|
- [Usage](#usage)
|
|
66
66
|
- [Command Line Interface](#command-line-interface)
|
|
67
|
-
- [
|
|
67
|
+
- [Check Pipelines](#check-pipelines)
|
|
68
68
|
- [Render SQL DDL](#render-sql-ddl)
|
|
69
69
|
- [Extract Data](#extract-data)
|
|
70
70
|
- [Validate Data](#validate-data)
|
|
@@ -182,6 +182,9 @@ etlplus --help
|
|
|
182
182
|
etlplus --version
|
|
183
183
|
```
|
|
184
184
|
|
|
185
|
+
The CLI is implemented with Typer (Click-based). There is no argparse compatibility layer, so rely
|
|
186
|
+
on the documented commands/flags and run `etlplus <command> --help` for current options.
|
|
187
|
+
|
|
185
188
|
#### Check Pipelines
|
|
186
189
|
|
|
187
190
|
Use `etlplus check` to explore pipeline YAML definitions without running them. The command can print
|
|
@@ -11,9 +11,9 @@ etlplus/run.py,sha256=X4kp5FQlIWVf1_d9oSrchKau7BFDCE1Zkscvu7WPaWw,12340
|
|
|
11
11
|
etlplus/run_helpers.py,sha256=bj6MkaeFxjl3CeKG1HoXKx5DwAlXNERVW-GX-z1P_qQ,24373
|
|
12
12
|
etlplus/transform.py,sha256=uAUVDDHYCgx7GpVez9IK3OAZM-CnCuMa9iox3vwGGJA,25296
|
|
13
13
|
etlplus/types.py,sha256=1hsDlnF6r76zAwaUYay-i6pCM-Y0IU5nP7Crj8PLCQ4,6157
|
|
14
|
-
etlplus/utils.py,sha256=
|
|
14
|
+
etlplus/utils.py,sha256=GrRH6N9u_U-4gs6PYpO0_Y2RwsyD3Ju9cup0b0byUbk,13367
|
|
15
15
|
etlplus/validate.py,sha256=7rJoEI_SIILdPpoBqqh2UJqg9oeReDz34mYSlc3t7Qg,12989
|
|
16
|
-
etlplus/api/README.md,sha256=
|
|
16
|
+
etlplus/api/README.md,sha256=ZiyjxLz0LfFCzeYKXwtH8yY1OJ4hXCju7t2ICroFoU8,7215
|
|
17
17
|
etlplus/api/__init__.py,sha256=P2JUYFy6Ep4t6xnsBiCBfQCkQLHYYhA-yXPXCobS8Y0,4295
|
|
18
18
|
etlplus/api/auth.py,sha256=GOO5on-LoMS1GXTAhtK9rFcfpjbBcNeA6NE5UZwIq0g,12158
|
|
19
19
|
etlplus/api/config.py,sha256=wRpOaZ31sPReVzEMme0jKl_37nqgraESwuYSNxP_xDo,17397
|
|
@@ -31,13 +31,13 @@ etlplus/api/rate_limiting/__init__.py,sha256=ZySB1dZettEDnWvI1EHf_TZ9L08M_kKsNR-
|
|
|
31
31
|
etlplus/api/rate_limiting/config.py,sha256=2b4wIynblN-1EyMqI4aXa71SljzSjXYh5N1Nngr3jOg,9406
|
|
32
32
|
etlplus/api/rate_limiting/rate_limiter.py,sha256=Uxozqd_Ej5Lsj-M-mLT2WexChgWh7x35_YP10yqYPQA,7159
|
|
33
33
|
etlplus/cli/__init__.py,sha256=J97-Rv931IL1_b4AXnB7Fbbd7HKnHBpx18NQfC_kE6c,299
|
|
34
|
-
etlplus/cli/commands.py,sha256
|
|
34
|
+
etlplus/cli/commands.py,sha256=-lO8XX2IeTvdfZLeI_UpT2kH4qZuNpfujArw3IKS2vY,22585
|
|
35
35
|
etlplus/cli/constants.py,sha256=NJ6IvNyYEI8IdB7eMcc-vteQiiIwqid5YvmUk-5DRHY,1839
|
|
36
|
-
etlplus/cli/handlers.py,sha256=
|
|
37
|
-
etlplus/cli/io.py,sha256=
|
|
38
|
-
etlplus/cli/main.py,sha256=
|
|
39
|
-
etlplus/cli/options.py,sha256=
|
|
40
|
-
etlplus/cli/state.py,sha256=
|
|
36
|
+
etlplus/cli/handlers.py,sha256=WBzJZz7ESU4Hljog_ON4g9PLIW6U6io_F9op7daksKY,17781
|
|
37
|
+
etlplus/cli/io.py,sha256=hkmbDh0HFrZhDjfZbma0Lp4tc0wrTwdD9Snqa-wNAd4,7308
|
|
38
|
+
etlplus/cli/main.py,sha256=_ipwLgIzkf8ks8cbu2KkVBbY3gcdaqDR98WUBdwviiw,5191
|
|
39
|
+
etlplus/cli/options.py,sha256=dswqAdnQ4fRJGI3xEFUyMifp0ry3rm2cCaPyEqI_99c,1199
|
|
40
|
+
etlplus/cli/state.py,sha256=20uKdYddYvAlR-HUQJAV-ThyXMZaPiSk9cN-tevRIpw,7991
|
|
41
41
|
etlplus/cli/types.py,sha256=tclhKVJXDqHzlTQBYKARfqMgDOcuBJ-Zej2pvFy96WM,652
|
|
42
42
|
etlplus/config/__init__.py,sha256=VZWzOg7d2YR9NT6UwKTv44yf2FRUMjTHynkm1Dl5Qzo,1486
|
|
43
43
|
etlplus/config/connector.py,sha256=0-TIwevHbKRHVmucvyGpPd-3tB1dKHB-dj0yJ6kq5eY,9809
|
|
@@ -57,9 +57,9 @@ etlplus/templates/ddl.sql.j2,sha256=s8fMWvcb4eaJVXkifuib1aQPljtZ8buuyB_uA-ZdU3Q,
|
|
|
57
57
|
etlplus/templates/view.sql.j2,sha256=Iy8DHfhq5yyvrUKDxqp_aHIEXY4Tm6j4wT7YDEFWAhk,2180
|
|
58
58
|
etlplus/validation/__init__.py,sha256=Pe5Xg1_EA4uiNZGYu5WTF3j7odjmyxnAJ8rcioaplSQ,1254
|
|
59
59
|
etlplus/validation/utils.py,sha256=Mtqg449VIke0ziy_wd2r6yrwJzQkA1iulZC87FzXMjo,10201
|
|
60
|
-
etlplus-0.8.
|
|
61
|
-
etlplus-0.8.
|
|
62
|
-
etlplus-0.8.
|
|
63
|
-
etlplus-0.8.
|
|
64
|
-
etlplus-0.8.
|
|
65
|
-
etlplus-0.8.
|
|
60
|
+
etlplus-0.8.4.dist-info/licenses/LICENSE,sha256=MuNO63i6kWmgnV2pbP2SLqP54mk1BGmu7CmbtxMmT-U,1069
|
|
61
|
+
etlplus-0.8.4.dist-info/METADATA,sha256=awIkLa9r6rXsxSPOBHRSFqfVgOjMmjvGr-D57zCkWz0,19513
|
|
62
|
+
etlplus-0.8.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
63
|
+
etlplus-0.8.4.dist-info/entry_points.txt,sha256=6w-2-jzuPa55spzK34h-UKh2JTEShh38adFRONNP9QE,45
|
|
64
|
+
etlplus-0.8.4.dist-info/top_level.txt,sha256=aWWF-udn_sLGuHTM6W6MLh99ArS9ROkUWO8Mi8y1_2U,8
|
|
65
|
+
etlplus-0.8.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|