dlt-utils 0.7.2__tar.gz → 0.7.3__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.
- {dlt_utils-0.7.2 → dlt_utils-0.7.3}/PKG-INFO +1 -1
- {dlt_utils-0.7.2 → dlt_utils-0.7.3}/dlt_utils/__init__.py +1 -1
- {dlt_utils-0.7.2 → dlt_utils-0.7.3}/dlt_utils/pipeline.py +46 -35
- {dlt_utils-0.7.2 → dlt_utils-0.7.3}/dlt_utils.egg-info/PKG-INFO +1 -1
- {dlt_utils-0.7.2 → dlt_utils-0.7.3}/pyproject.toml +1 -1
- {dlt_utils-0.7.2 → dlt_utils-0.7.3}/README.md +0 -0
- {dlt_utils-0.7.2 → dlt_utils-0.7.3}/dlt_utils/args.py +0 -0
- {dlt_utils-0.7.2 → dlt_utils-0.7.3}/dlt_utils/auth.py +0 -0
- {dlt_utils-0.7.2 → dlt_utils-0.7.3}/dlt_utils/azure_keyvault.py +0 -0
- {dlt_utils-0.7.2 → dlt_utils-0.7.3}/dlt_utils/dates.py +0 -0
- {dlt_utils-0.7.2 → dlt_utils-0.7.3}/dlt_utils/incremental.py +0 -0
- {dlt_utils-0.7.2 → dlt_utils-0.7.3}/dlt_utils/logging.py +0 -0
- {dlt_utils-0.7.2 → dlt_utils-0.7.3}/dlt_utils/schema.py +0 -0
- {dlt_utils-0.7.2 → dlt_utils-0.7.3}/dlt_utils.egg-info/SOURCES.txt +0 -0
- {dlt_utils-0.7.2 → dlt_utils-0.7.3}/dlt_utils.egg-info/dependency_links.txt +0 -0
- {dlt_utils-0.7.2 → dlt_utils-0.7.3}/dlt_utils.egg-info/requires.txt +0 -0
- {dlt_utils-0.7.2 → dlt_utils-0.7.3}/dlt_utils.egg-info/top_level.txt +0 -0
- {dlt_utils-0.7.2 → dlt_utils-0.7.3}/setup.cfg +0 -0
- {dlt_utils-0.7.2 → dlt_utils-0.7.3}/tests/test_azure_keyvault.py +0 -0
- {dlt_utils-0.7.2 → dlt_utils-0.7.3}/tests/test_dates.py +0 -0
- {dlt_utils-0.7.2 → dlt_utils-0.7.3}/tests/test_incremental.py +0 -0
|
@@ -23,14 +23,14 @@ def validate_refresh_args(
|
|
|
23
23
|
) -> None:
|
|
24
24
|
"""
|
|
25
25
|
Validate that refresh arguments are used correctly.
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
Raises ValueError if drop_sources is used with a resource filter,
|
|
28
28
|
as this would drop ALL tables but only reload selected resources.
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
Args:
|
|
31
31
|
refresh: The refresh mode ('drop_sources' or 'drop_resources').
|
|
32
32
|
resources_filter: List of resources being loaded (None = all).
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
Raises:
|
|
35
35
|
ValueError: If drop_sources is used with a resource filter.
|
|
36
36
|
"""
|
|
@@ -49,46 +49,47 @@ def filter_resources(
|
|
|
49
49
|
) -> list[str]:
|
|
50
50
|
"""
|
|
51
51
|
Filter available resources based on requested resources.
|
|
52
|
-
|
|
52
|
+
|
|
53
53
|
Args:
|
|
54
54
|
available_resources: List of all available resource names.
|
|
55
55
|
requested_resources: List of requested resources (None = all).
|
|
56
|
-
|
|
56
|
+
|
|
57
57
|
Returns:
|
|
58
58
|
List of valid resources to load.
|
|
59
|
-
|
|
59
|
+
|
|
60
60
|
Raises:
|
|
61
61
|
ValueError: If no valid resources are found.
|
|
62
62
|
"""
|
|
63
63
|
if requested_resources is None:
|
|
64
64
|
return available_resources
|
|
65
|
-
|
|
66
|
-
valid_resources = [
|
|
67
|
-
|
|
65
|
+
|
|
66
|
+
valid_resources = [
|
|
67
|
+
r for r in requested_resources if r in available_resources]
|
|
68
|
+
|
|
68
69
|
if not valid_resources:
|
|
69
70
|
raise ValueError(
|
|
70
71
|
f"No valid resources found. "
|
|
71
72
|
f"Requested: {requested_resources}. "
|
|
72
73
|
f"Available: {available_resources}"
|
|
73
74
|
)
|
|
74
|
-
|
|
75
|
+
|
|
75
76
|
# Log any requested resources that weren't found
|
|
76
77
|
invalid = set(requested_resources) - set(valid_resources)
|
|
77
78
|
if invalid:
|
|
78
79
|
logger.warning(f"Ignored invalid resources: {invalid}")
|
|
79
|
-
|
|
80
|
+
|
|
80
81
|
return valid_resources
|
|
81
82
|
|
|
82
83
|
|
|
83
84
|
def print_resources(source: Any) -> None:
|
|
84
85
|
"""
|
|
85
86
|
Print available resources from a dlt source and exit.
|
|
86
|
-
|
|
87
|
+
|
|
87
88
|
Args:
|
|
88
89
|
source: A dlt source object with a resources attribute.
|
|
89
90
|
"""
|
|
90
91
|
available_resources = sorted(get_resource_names(source))
|
|
91
|
-
|
|
92
|
+
|
|
92
93
|
print("\nAvailable resources:")
|
|
93
94
|
print("-" * 40)
|
|
94
95
|
for resource in available_resources:
|
|
@@ -100,10 +101,10 @@ def print_resources(source: Any) -> None:
|
|
|
100
101
|
def get_resource_names(source: Any) -> list[str]:
|
|
101
102
|
"""
|
|
102
103
|
Get list of resource names from a dlt source.
|
|
103
|
-
|
|
104
|
+
|
|
104
105
|
Args:
|
|
105
106
|
source: A dlt source object with a resources attribute.
|
|
106
|
-
|
|
107
|
+
|
|
107
108
|
Returns:
|
|
108
109
|
List of resource names.
|
|
109
110
|
"""
|
|
@@ -113,20 +114,20 @@ def get_resource_names(source: Any) -> list[str]:
|
|
|
113
114
|
def mask_sensitive_value(value: str | None, show_chars: int = 2) -> str:
|
|
114
115
|
"""
|
|
115
116
|
Mask a sensitive value (like API key) showing only first and middle characters.
|
|
116
|
-
|
|
117
|
+
|
|
117
118
|
Args:
|
|
118
119
|
value: The value to mask.
|
|
119
120
|
show_chars: Number of characters to show at start and middle.
|
|
120
|
-
|
|
121
|
+
|
|
121
122
|
Returns:
|
|
122
123
|
Masked value like "ab..cd..***" or "N/A" if not set.
|
|
123
124
|
"""
|
|
124
125
|
if not value:
|
|
125
126
|
return "N/A"
|
|
126
|
-
|
|
127
|
+
|
|
127
128
|
if len(value) < 6:
|
|
128
129
|
return value[:1] + "***"
|
|
129
|
-
|
|
130
|
+
|
|
130
131
|
mid = len(value) // 2
|
|
131
132
|
return f"{value[:show_chars]}..{value[mid:mid+show_chars]}..***"
|
|
132
133
|
|
|
@@ -138,34 +139,34 @@ def cleanup_tombstones(
|
|
|
138
139
|
) -> None:
|
|
139
140
|
"""
|
|
140
141
|
Clean up tombstone records from tables after a successful pipeline run.
|
|
141
|
-
|
|
142
|
+
|
|
142
143
|
Tombstones are placeholder records used to ensure delete-insert semantics
|
|
143
144
|
work correctly for partitions that have no real data. After the pipeline
|
|
144
145
|
completes, these tombstone records should be removed.
|
|
145
|
-
|
|
146
|
+
|
|
146
147
|
Args:
|
|
147
148
|
pipeline: A dlt pipeline object with sql_client() method.
|
|
148
149
|
resources: List of resource/table names to clean tombstones from.
|
|
149
150
|
column_name: The boolean column name that marks tombstone records.
|
|
150
151
|
Defaults to "_tt_is_tombstone".
|
|
151
|
-
|
|
152
|
+
|
|
152
153
|
Example:
|
|
153
154
|
# Clean up tombstones from all resources except 'customer'
|
|
154
155
|
tombstone_resources = [r for r in sync_resources if r != "customer"]
|
|
155
156
|
cleanup_tombstones(pipeline, tombstone_resources)
|
|
156
|
-
|
|
157
|
+
|
|
157
158
|
# Clean up with a custom column name
|
|
158
159
|
cleanup_tombstones(pipeline, ["my_table"], column_name="is_tombstone")
|
|
159
160
|
"""
|
|
160
161
|
if not resources:
|
|
161
162
|
logger.debug("No resources provided for tombstone cleanup")
|
|
162
163
|
return
|
|
163
|
-
|
|
164
|
+
|
|
164
165
|
with pipeline.sql_client() as sql_client:
|
|
165
166
|
for resource_name in resources:
|
|
166
167
|
table_name = sql_client.make_qualified_table_name(resource_name)
|
|
167
168
|
delete_query = f"DELETE FROM {table_name} WHERE {column_name} = 1"
|
|
168
|
-
|
|
169
|
+
|
|
169
170
|
try:
|
|
170
171
|
sql_client.execute_sql(delete_query)
|
|
171
172
|
logger.info(f"Cleaned up tombstone records from {table_name}")
|
|
@@ -267,11 +268,12 @@ def print_configs(
|
|
|
267
268
|
configs: Sequence of dataclass instances to print.
|
|
268
269
|
title: Title for the table header.
|
|
269
270
|
columns: List of (field_name, header_label, width) tuples defining which
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
sensitive_fields: List of field names that contain sensitive data to mask.
|
|
271
|
+
fields to display and how. If None, all fields are shown with
|
|
272
|
+
auto-generated headers.
|
|
273
|
+
sensitive_fields: List of field names that contain sensitive data to mask. Uses
|
|
274
|
+
auto-detection for dataclass fields with repr=False if not provided.
|
|
273
275
|
mask_func: Function to mask sensitive values. If None, uses mask_sensitive_value
|
|
274
|
-
|
|
276
|
+
which shows first and middle characters.
|
|
275
277
|
|
|
276
278
|
Example:
|
|
277
279
|
print_configs(
|
|
@@ -302,8 +304,17 @@ def print_configs(
|
|
|
302
304
|
"columns must be provided for non-dataclass configs"
|
|
303
305
|
)
|
|
304
306
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
+
auto_sensitive_fields: set[str] = set()
|
|
308
|
+
if is_dataclass(configs[0]):
|
|
309
|
+
auto_sensitive_fields = {
|
|
310
|
+
f.name for f in fields(configs[0]) if not f.repr
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if sensitive_fields is None:
|
|
314
|
+
sensitive_fields = list(auto_sensitive_fields)
|
|
315
|
+
else:
|
|
316
|
+
sensitive_fields = list(set(sensitive_fields) | auto_sensitive_fields)
|
|
317
|
+
|
|
307
318
|
# Use mask_sensitive_value as default mask function
|
|
308
319
|
if mask_func is None:
|
|
309
320
|
mask_func = mask_sensitive_value
|
|
@@ -315,11 +326,11 @@ def print_configs(
|
|
|
315
326
|
# Print header
|
|
316
327
|
print(f"\n{title}:")
|
|
317
328
|
print("-" * total_width)
|
|
318
|
-
|
|
329
|
+
|
|
319
330
|
header = f"{'Index':<{index_width}}"
|
|
320
331
|
header += "".join(f"{label:<{width}}" for _, label, width in columns)
|
|
321
332
|
print(header)
|
|
322
|
-
|
|
333
|
+
|
|
323
334
|
print("-" * total_width)
|
|
324
335
|
|
|
325
336
|
# Print rows
|
|
@@ -327,12 +338,12 @@ def print_configs(
|
|
|
327
338
|
row = f"{i:<{index_width}}"
|
|
328
339
|
for field_name, _, width in columns:
|
|
329
340
|
value = getattr(config, field_name, None)
|
|
330
|
-
|
|
341
|
+
|
|
331
342
|
if field_name in sensitive_fields:
|
|
332
343
|
display_value = mask_func(value)
|
|
333
344
|
else:
|
|
334
345
|
display_value = str(value) if value is not None else "N/A"
|
|
335
|
-
|
|
346
|
+
|
|
336
347
|
row += f"{display_value:<{width}}"
|
|
337
348
|
print(row)
|
|
338
349
|
|
|
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
|