keboola.component 1.6.7__tar.gz → 1.6.8__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.
- {keboola.component-1.6.7/src/keboola.component.egg-info → keboola.component-1.6.8}/PKG-INFO +1 -1
- {keboola.component-1.6.7 → keboola.component-1.6.8}/setup.py +1 -1
- {keboola.component-1.6.7 → keboola.component-1.6.8}/src/keboola/component/base.py +52 -18
- {keboola.component-1.6.7 → keboola.component-1.6.8}/src/keboola/component/dao.py +33 -16
- {keboola.component-1.6.7 → keboola.component-1.6.8}/src/keboola/component/interface.py +10 -8
- {keboola.component-1.6.7 → keboola.component-1.6.8/src/keboola.component.egg-info}/PKG-INFO +1 -1
- {keboola.component-1.6.7 → keboola.component-1.6.8}/LICENSE +0 -0
- {keboola.component-1.6.7 → keboola.component-1.6.8}/README.md +0 -0
- {keboola.component-1.6.7 → keboola.component-1.6.8}/setup.cfg +0 -0
- {keboola.component-1.6.7 → keboola.component-1.6.8}/src/keboola/component/__init__.py +0 -0
- {keboola.component-1.6.7 → keboola.component-1.6.8}/src/keboola/component/exceptions.py +0 -0
- {keboola.component-1.6.7 → keboola.component-1.6.8}/src/keboola/component/sync_actions.py +0 -0
- {keboola.component-1.6.7 → keboola.component-1.6.8}/src/keboola/component/table_schema.py +0 -0
- {keboola.component-1.6.7 → keboola.component-1.6.8}/src/keboola.component.egg-info/SOURCES.txt +0 -0
- {keboola.component-1.6.7 → keboola.component-1.6.8}/src/keboola.component.egg-info/dependency_links.txt +0 -0
- {keboola.component-1.6.7 → keboola.component-1.6.8}/src/keboola.component.egg-info/not-zip-safe +0 -0
- {keboola.component-1.6.7 → keboola.component-1.6.8}/src/keboola.component.egg-info/requires.txt +0 -0
- {keboola.component-1.6.7 → keboola.component-1.6.8}/src/keboola.component.egg-info/top_level.txt +0 -0
|
@@ -249,6 +249,18 @@ class ComponentBase(ABC, CommonInterface):
|
|
|
249
249
|
raise AttributeError(f"The defined action {action} is not implemented!") from e
|
|
250
250
|
return action_method()
|
|
251
251
|
|
|
252
|
+
def _generate_table_metadata_legacy(self, table_schema: ts.TableSchema) -> dao.TableMetadata:
|
|
253
|
+
"""
|
|
254
|
+
Generates a TableMetadata object for the table definition using a TableSchema object.
|
|
255
|
+
|
|
256
|
+
"""
|
|
257
|
+
table_metadata = dao.TableMetadata()
|
|
258
|
+
if table_schema.description:
|
|
259
|
+
table_metadata.add_table_description(table_schema.description)
|
|
260
|
+
table_metadata.add_column_descriptions({field.name: field.description for field in table_schema.fields})
|
|
261
|
+
table_metadata = self._add_field_data_types_to_table_metadata(table_schema, table_metadata)
|
|
262
|
+
return table_metadata
|
|
263
|
+
|
|
252
264
|
def create_out_table_definition_from_schema(self, table_schema: ts.TableSchema, is_sliced: bool = False,
|
|
253
265
|
destination: str = '', incremental: bool = None,
|
|
254
266
|
enclosure: str = '"', delimiter: str = ',',
|
|
@@ -271,17 +283,33 @@ class ComponentBase(ABC, CommonInterface):
|
|
|
271
283
|
TableDefinition object initialized with all table metadata defined in a schema
|
|
272
284
|
|
|
273
285
|
"""
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
286
|
+
if self._expects_legacy_manifest():
|
|
287
|
+
table_metadata = self._generate_table_metadata_legacy(table_schema)
|
|
288
|
+
table_def = self.create_out_table_definition(name=table_schema.csv_name,
|
|
289
|
+
columns=table_schema.field_names,
|
|
290
|
+
primary_key=table_schema.primary_keys,
|
|
291
|
+
table_metadata=table_metadata,
|
|
292
|
+
is_sliced=is_sliced,
|
|
293
|
+
destination=destination,
|
|
294
|
+
incremental=incremental,
|
|
295
|
+
enclosure=enclosure,
|
|
296
|
+
delimiter=delimiter,
|
|
297
|
+
delete_where=delete_where)
|
|
298
|
+
else:
|
|
299
|
+
schema = self._generate_schema_definition(table_schema)
|
|
300
|
+
|
|
301
|
+
table_def = self.create_out_table_definition(name=table_schema.csv_name,
|
|
302
|
+
primary_key=table_schema.primary_keys,
|
|
303
|
+
schema=schema,
|
|
304
|
+
is_sliced=is_sliced,
|
|
305
|
+
destination=destination,
|
|
306
|
+
incremental=incremental,
|
|
307
|
+
enclosure=enclosure,
|
|
308
|
+
delimiter=delimiter,
|
|
309
|
+
delete_where=delete_where,
|
|
310
|
+
description=table_schema.description)
|
|
311
|
+
|
|
312
|
+
return table_def
|
|
285
313
|
|
|
286
314
|
def get_table_schema_by_name(self, schema_name: str,
|
|
287
315
|
schema_folder_path: Optional[str] = None) -> ts.TableSchema:
|
|
@@ -324,18 +352,24 @@ class ComponentBase(ABC, CommonInterface):
|
|
|
324
352
|
"from a schema. If a schema folder path is not defined, the schemas folder must be"
|
|
325
353
|
" located in the 'src' directory of a component : src/schemas")
|
|
326
354
|
|
|
327
|
-
def
|
|
355
|
+
def _generate_schema_definition(self, table_schema: ts.TableSchema) -> Dict[str, dao.ColumnDefinition]:
|
|
328
356
|
"""
|
|
329
357
|
Generates a TableMetadata object for the table definition using a TableSchema object.
|
|
330
358
|
|
|
331
359
|
"""
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
360
|
+
column_definitions = {}
|
|
361
|
+
for field in table_schema.fields:
|
|
362
|
+
if field.base_type:
|
|
363
|
+
data_types = dao.BaseType(field.base_type,
|
|
364
|
+
length=field.length,
|
|
365
|
+
default=field.default)
|
|
366
|
+
else:
|
|
367
|
+
data_types = dao.BaseType()
|
|
368
|
+
column_definitions[field.name] = dao.ColumnDefinition(data_types=data_types,
|
|
369
|
+
nullable=field.nullable,
|
|
370
|
+
description=field.description)
|
|
337
371
|
|
|
338
|
-
return
|
|
372
|
+
return column_definitions
|
|
339
373
|
|
|
340
374
|
@staticmethod
|
|
341
375
|
def _add_field_data_types_to_table_metadata(table_schema: ts.TableSchema,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# Python 3.7 support
|
|
2
2
|
from __future__ import annotations
|
|
3
|
+
|
|
3
4
|
import dataclasses
|
|
4
5
|
import json
|
|
5
6
|
import logging
|
|
@@ -12,7 +13,6 @@ from enum import Enum
|
|
|
12
13
|
from pathlib import Path
|
|
13
14
|
from typing import List, Union, Dict, Optional, OrderedDict as TypeOrderedDict
|
|
14
15
|
|
|
15
|
-
|
|
16
16
|
from deprecated import deprecated
|
|
17
17
|
|
|
18
18
|
from .exceptions import UserException
|
|
@@ -204,15 +204,15 @@ class TableMetadata:
|
|
|
204
204
|
"""
|
|
205
205
|
if legacy_manifest:
|
|
206
206
|
final_metadata_list = [{'key': key,
|
|
207
|
-
'value':
|
|
208
|
-
for key in self.table_metadata]
|
|
207
|
+
'value': value}
|
|
208
|
+
for key, value in self.table_metadata.items() if value not in [None, '']]
|
|
209
209
|
else:
|
|
210
|
-
final_metadata_list =
|
|
211
|
-
for key in self.table_metadata]
|
|
210
|
+
final_metadata_list = {key: value
|
|
211
|
+
for key, value in self.table_metadata.items() if value not in [None, '']}
|
|
212
212
|
|
|
213
213
|
return final_metadata_list
|
|
214
214
|
|
|
215
|
-
@deprecated(version='1.5.1', reason="Please use schema instead of
|
|
215
|
+
@deprecated(version='1.5.1', reason="Please use schema instead of Column Metadata")
|
|
216
216
|
def get_column_metadata_for_manifest(self) -> dict:
|
|
217
217
|
"""
|
|
218
218
|
Returns column metadata dict as required by the
|
|
@@ -251,13 +251,14 @@ class TableMetadata:
|
|
|
251
251
|
final_column_metadata[column] = list()
|
|
252
252
|
|
|
253
253
|
column_metadata = [{'key': key,
|
|
254
|
-
'value':
|
|
255
|
-
column_metadata_dicts]
|
|
254
|
+
'value': value} for key, value in
|
|
255
|
+
column_metadata_dicts.items() if value not in [None, '']]
|
|
256
256
|
final_column_metadata[column].extend(column_metadata)
|
|
257
257
|
|
|
258
258
|
return final_column_metadata
|
|
259
259
|
|
|
260
260
|
@property
|
|
261
|
+
@deprecated(version='1.5.1', reason="Please use TableDefinition.description instead of TableMetadata")
|
|
261
262
|
def table_description(self) -> str:
|
|
262
263
|
"""
|
|
263
264
|
Returns table description (KBC.description)
|
|
@@ -402,14 +403,20 @@ class TableMetadata:
|
|
|
402
403
|
Args:
|
|
403
404
|
|
|
404
405
|
"""
|
|
406
|
+
if value is None:
|
|
407
|
+
return
|
|
405
408
|
self.table_metadata = {**self.table_metadata, **{key: value}}
|
|
406
409
|
|
|
410
|
+
@deprecated(version='1.5.1', reason="Column metadata ere moved to dao.TableDefinition.schema property."
|
|
411
|
+
"Please use the dao.ColumnDefinition.metadata")
|
|
407
412
|
def add_column_metadata(self, column: str, key: str, value: Union[str, bool, int], backend="base"):
|
|
408
413
|
"""
|
|
409
414
|
Add/Updates column metadata and ensures the Key is unique.
|
|
410
415
|
Args:
|
|
411
416
|
|
|
412
417
|
"""
|
|
418
|
+
if value is None:
|
|
419
|
+
return
|
|
413
420
|
if not self.column_metadata.get(column):
|
|
414
421
|
self.column_metadata[column] = dict()
|
|
415
422
|
|
|
@@ -417,6 +424,8 @@ class TableMetadata:
|
|
|
417
424
|
|
|
418
425
|
# self.schema = [ColumnDefinition(name=column, data_type={backend: DataType(type=value)})]
|
|
419
426
|
|
|
427
|
+
@deprecated(version='1.5.1', reason="Column metadata ere moved to dao.TableDefinition.schema property."
|
|
428
|
+
"Please use the dao.ColumnDefinition.metadata")
|
|
420
429
|
def add_multiple_column_metadata(self, column_metadata: Dict[str, List[dict]]):
|
|
421
430
|
"""
|
|
422
431
|
Add key-value pairs to column metadata.
|
|
@@ -577,7 +586,7 @@ class SupportedManifestAttributes(SubscriptableDataclass):
|
|
|
577
586
|
to_remove = ['primary_key', 'columns', 'distribution_key', 'column_metadata', 'metadata']
|
|
578
587
|
attributes = list(set(attributes).difference(to_remove))
|
|
579
588
|
|
|
580
|
-
to_add = ['manifest_type', 'has_header', '
|
|
589
|
+
to_add = ['manifest_type', 'has_header', 'table_metadata', 'schema']
|
|
581
590
|
attributes.extend(to_add)
|
|
582
591
|
|
|
583
592
|
elif stage == 'in':
|
|
@@ -773,13 +782,14 @@ class TableDefinition(IODefinition):
|
|
|
773
782
|
|
|
774
783
|
MANIFEST_ATTRIBUTES = {'in': INPUT_MANIFEST_ATTRIBUTES,
|
|
775
784
|
'out': OUTPUT_MANIFEST_ATTRIBUTES}
|
|
785
|
+
SCHEMA_TYPE = Union[Dict[str, ColumnDefinition], TypeOrderedDict[str, ColumnDefinition], List[str]]
|
|
776
786
|
|
|
777
787
|
def __init__(self, name: str,
|
|
778
788
|
full_path: Optional[Union[str, None]] = None,
|
|
779
789
|
is_sliced: Optional[bool] = False,
|
|
780
790
|
destination: Optional[str] = '',
|
|
781
791
|
primary_key: Optional[List[str]] = None,
|
|
782
|
-
schema:
|
|
792
|
+
schema: SCHEMA_TYPE = None,
|
|
783
793
|
incremental: Optional[bool] = None,
|
|
784
794
|
table_metadata: Optional[TableMetadata] = None,
|
|
785
795
|
enclosure: Optional[str] = '"',
|
|
@@ -788,6 +798,7 @@ class TableDefinition(IODefinition):
|
|
|
788
798
|
stage: Optional[str] = 'out',
|
|
789
799
|
write_always: Optional[bool] = False,
|
|
790
800
|
has_header: Optional[bool] = None,
|
|
801
|
+
description: Optional[str] = None,
|
|
791
802
|
# input
|
|
792
803
|
**kwargs
|
|
793
804
|
):
|
|
@@ -815,6 +826,7 @@ class TableDefinition(IODefinition):
|
|
|
815
826
|
write_always: Bool: If true, the table will be saved to Storage even when the job execution
|
|
816
827
|
fails.
|
|
817
828
|
schema: (dict|lis[str]) Mapping of column names andColumnDefinition objects, or a list of names
|
|
829
|
+
description: str: Table description
|
|
818
830
|
|
|
819
831
|
"""
|
|
820
832
|
super().__init__(full_path)
|
|
@@ -824,7 +836,7 @@ class TableDefinition(IODefinition):
|
|
|
824
836
|
# initialize manifest properties
|
|
825
837
|
self._destination = None
|
|
826
838
|
self.destination = destination
|
|
827
|
-
self._schema = dict()
|
|
839
|
+
self._schema: Dict[str, ColumnDefinition] = dict()
|
|
828
840
|
|
|
829
841
|
if schema:
|
|
830
842
|
self.schema = schema
|
|
@@ -845,6 +857,8 @@ class TableDefinition(IODefinition):
|
|
|
845
857
|
if not table_metadata:
|
|
846
858
|
table_metadata = TableMetadata()
|
|
847
859
|
self.table_metadata = table_metadata
|
|
860
|
+
if description:
|
|
861
|
+
self.table_metadata.add_table_description(description)
|
|
848
862
|
|
|
849
863
|
self.delete_where_values = None
|
|
850
864
|
self.delete_where_column = None
|
|
@@ -893,7 +907,8 @@ class TableDefinition(IODefinition):
|
|
|
893
907
|
delimiter: Optional[str] = ',',
|
|
894
908
|
delete_where: Optional[dict] = None,
|
|
895
909
|
write_always: Optional[bool] = False,
|
|
896
|
-
schema:
|
|
910
|
+
schema: SCHEMA_TYPE = None,
|
|
911
|
+
description: Optional[str] = None,
|
|
897
912
|
**kwargs
|
|
898
913
|
):
|
|
899
914
|
"""
|
|
@@ -914,6 +929,7 @@ class TableDefinition(IODefinition):
|
|
|
914
929
|
delete_where (Optional[dict]): Criteria for row deletion in incremental loads. Defaults to None.
|
|
915
930
|
write_always (Optional[bool]): If True, the table will be saved to storage even if the job fails.
|
|
916
931
|
schema (Optional[List[ColumnDefinition]]): Dictionary of ColumnDefinition objects.
|
|
932
|
+
description (Optional[str]): The description of the table. Defaults to None.
|
|
917
933
|
|
|
918
934
|
Returns:
|
|
919
935
|
TableDefinition: An instance of TableDefinition configured for output tables.
|
|
@@ -929,6 +945,7 @@ class TableDefinition(IODefinition):
|
|
|
929
945
|
delete_where=delete_where,
|
|
930
946
|
write_always=write_always,
|
|
931
947
|
schema=schema,
|
|
948
|
+
description=description,
|
|
932
949
|
**kwargs
|
|
933
950
|
)
|
|
934
951
|
|
|
@@ -1155,7 +1172,7 @@ class TableDefinition(IODefinition):
|
|
|
1155
1172
|
name=name,
|
|
1156
1173
|
destination=manifest.get('destination'),
|
|
1157
1174
|
schema=cls.return_schema_from_manifest(manifest),
|
|
1158
|
-
incremental=manifest.get('incremental'),
|
|
1175
|
+
incremental=manifest.get('incremental', False),
|
|
1159
1176
|
primary_key=manifest.get('primary_key'),
|
|
1160
1177
|
write_always=manifest.get('write_always', False),
|
|
1161
1178
|
delimiter=manifest.get('delimiter', ','),
|
|
@@ -1255,7 +1272,6 @@ class TableDefinition(IODefinition):
|
|
|
1255
1272
|
'column_metadata': self.table_metadata._get_legacy_column_metadata_for_manifest(),
|
|
1256
1273
|
'manifest_type': manifest_type,
|
|
1257
1274
|
'has_header': self.has_header,
|
|
1258
|
-
'description': None,
|
|
1259
1275
|
'table_metadata': self.table_metadata.get_table_metadata_for_manifest(),
|
|
1260
1276
|
'delete_where_column': self.delete_where_column,
|
|
1261
1277
|
'delete_where_values': self.delete_where_values,
|
|
@@ -1263,6 +1279,7 @@ class TableDefinition(IODefinition):
|
|
|
1263
1279
|
'schema': [col.to_dict(name)
|
|
1264
1280
|
for name, col in self.schema.items()] if isinstance(self.schema, (OrderedDict, dict)) else []
|
|
1265
1281
|
}
|
|
1282
|
+
|
|
1266
1283
|
if legacy_manifest or self.stage == 'in':
|
|
1267
1284
|
fields['columns'] = self.column_names
|
|
1268
1285
|
|
|
@@ -1387,8 +1404,8 @@ class TableDefinition(IODefinition):
|
|
|
1387
1404
|
|
|
1388
1405
|
@incremental.setter
|
|
1389
1406
|
def incremental(self, incremental: bool):
|
|
1390
|
-
if incremental:
|
|
1391
|
-
self._incremental =
|
|
1407
|
+
if incremental is not None:
|
|
1408
|
+
self._incremental = incremental
|
|
1392
1409
|
|
|
1393
1410
|
@property
|
|
1394
1411
|
def write_always(self) -> bool:
|
|
@@ -18,7 +18,7 @@ from pygelf import GelfUdpHandler, GelfTcpHandler
|
|
|
18
18
|
from pytz import utc
|
|
19
19
|
|
|
20
20
|
from . import dao
|
|
21
|
-
from .dao import ColumnDefinition
|
|
21
|
+
from .dao import ColumnDefinition, TableDefinition
|
|
22
22
|
from .exceptions import UserException
|
|
23
23
|
|
|
24
24
|
|
|
@@ -338,7 +338,8 @@ class CommonInterface:
|
|
|
338
338
|
write_always: bool = False,
|
|
339
339
|
schema: Union[
|
|
340
340
|
OrderedDict[str, ColumnDefinition], list[str]] = None,
|
|
341
|
-
has_header: Optional[bool] = None
|
|
341
|
+
has_header: Optional[bool] = None,
|
|
342
|
+
description: Optional[str] = None) -> dao.TableDefinition:
|
|
342
343
|
"""
|
|
343
344
|
Helper method for dao.TableDefinition creation along with the "manifest".
|
|
344
345
|
It initializes path according to the storage_stage type.
|
|
@@ -381,6 +382,7 @@ class CommonInterface:
|
|
|
381
382
|
primary_key=primary_key,
|
|
382
383
|
columns=columns,
|
|
383
384
|
incremental=incremental,
|
|
385
|
+
description=description,
|
|
384
386
|
table_metadata=table_metadata,
|
|
385
387
|
enclosure=enclosure,
|
|
386
388
|
delimiter=delimiter,
|
|
@@ -427,13 +429,11 @@ class CommonInterface:
|
|
|
427
429
|
delete_where=delete_where,
|
|
428
430
|
schema=schema)
|
|
429
431
|
|
|
430
|
-
SCHEMA_TYPE = Union[Dict[str, ColumnDefinition], OrderedDict[str, ColumnDefinition], List[str]]
|
|
431
|
-
|
|
432
432
|
def create_out_table_definition(self, name: str,
|
|
433
433
|
is_sliced: bool = False,
|
|
434
434
|
destination: str = '',
|
|
435
435
|
primary_key: List[str] = None,
|
|
436
|
-
schema: SCHEMA_TYPE = None,
|
|
436
|
+
schema: TableDefinition.SCHEMA_TYPE = None,
|
|
437
437
|
incremental: bool = None,
|
|
438
438
|
table_metadata: dao.TableMetadata = None,
|
|
439
439
|
enclosure: str = '"',
|
|
@@ -441,6 +441,7 @@ class CommonInterface:
|
|
|
441
441
|
delete_where: dict = None,
|
|
442
442
|
write_always: bool = False,
|
|
443
443
|
has_header: Optional[bool] = None,
|
|
444
|
+
description: Optional[str] = None,
|
|
444
445
|
**kwargs
|
|
445
446
|
) -> dao.TableDefinition:
|
|
446
447
|
"""
|
|
@@ -464,6 +465,7 @@ class CommonInterface:
|
|
|
464
465
|
fails.
|
|
465
466
|
has_header:Optional[bool] = flag whether the header is present in the file,
|
|
466
467
|
if None legacy method is used
|
|
468
|
+
description: Table description
|
|
467
469
|
"""
|
|
468
470
|
|
|
469
471
|
return self._create_table_definition(name=name,
|
|
@@ -479,7 +481,8 @@ class CommonInterface:
|
|
|
479
481
|
delete_where=delete_where,
|
|
480
482
|
write_always=write_always,
|
|
481
483
|
schema=schema,
|
|
482
|
-
has_header=has_header
|
|
484
|
+
has_header=has_header,
|
|
485
|
+
description=description)
|
|
483
486
|
|
|
484
487
|
# # File processing
|
|
485
488
|
|
|
@@ -956,7 +959,6 @@ class CommonInterface:
|
|
|
956
959
|
"""
|
|
957
960
|
|
|
958
961
|
if not legacy_manifest:
|
|
959
|
-
|
|
960
962
|
legacy_manifest = self._expects_legacy_manifest()
|
|
961
963
|
|
|
962
964
|
manifest = io_definition.get_manifest_dictionary(legacy_queue=self.is_legacy_queue,
|
|
@@ -967,7 +969,7 @@ class CommonInterface:
|
|
|
967
969
|
json.dump(manifest, manifest_file)
|
|
968
970
|
|
|
969
971
|
def _expects_legacy_manifest(self) -> bool:
|
|
970
|
-
legacy_manifest
|
|
972
|
+
legacy_manifest = \
|
|
971
973
|
(self._running_in_kbc and self.environment_variables.data_type_support not in ('authoritative', 'hints'))
|
|
972
974
|
|
|
973
975
|
om_override = self.configuration.config_data.get('storage', {}).get('output', {}).get('data_type_support')
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{keboola.component-1.6.7 → keboola.component-1.6.8}/src/keboola.component.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{keboola.component-1.6.7 → keboola.component-1.6.8}/src/keboola.component.egg-info/not-zip-safe
RENAMED
|
File without changes
|
{keboola.component-1.6.7 → keboola.component-1.6.8}/src/keboola.component.egg-info/requires.txt
RENAMED
|
File without changes
|
{keboola.component-1.6.7 → keboola.component-1.6.8}/src/keboola.component.egg-info/top_level.txt
RENAMED
|
File without changes
|