keboola.component 1.6.7__tar.gz → 1.6.9__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.9}/PKG-INFO +9 -6
- {keboola.component-1.6.7 → keboola.component-1.6.9}/README.md +8 -5
- {keboola.component-1.6.7 → keboola.component-1.6.9}/setup.py +1 -1
- {keboola.component-1.6.7 → keboola.component-1.6.9}/src/keboola/component/base.py +52 -18
- {keboola.component-1.6.7 → keboola.component-1.6.9}/src/keboola/component/dao.py +33 -17
- {keboola.component-1.6.7 → keboola.component-1.6.9}/src/keboola/component/interface.py +18 -12
- {keboola.component-1.6.7 → keboola.component-1.6.9/src/keboola.component.egg-info}/PKG-INFO +9 -6
- {keboola.component-1.6.7 → keboola.component-1.6.9}/LICENSE +0 -0
- {keboola.component-1.6.7 → keboola.component-1.6.9}/setup.cfg +0 -0
- {keboola.component-1.6.7 → keboola.component-1.6.9}/src/keboola/component/__init__.py +0 -0
- {keboola.component-1.6.7 → keboola.component-1.6.9}/src/keboola/component/exceptions.py +0 -0
- {keboola.component-1.6.7 → keboola.component-1.6.9}/src/keboola/component/sync_actions.py +0 -0
- {keboola.component-1.6.7 → keboola.component-1.6.9}/src/keboola/component/table_schema.py +0 -0
- {keboola.component-1.6.7 → keboola.component-1.6.9}/src/keboola.component.egg-info/SOURCES.txt +0 -0
- {keboola.component-1.6.7 → keboola.component-1.6.9}/src/keboola.component.egg-info/dependency_links.txt +0 -0
- {keboola.component-1.6.7 → keboola.component-1.6.9}/src/keboola.component.egg-info/not-zip-safe +0 -0
- {keboola.component-1.6.7 → keboola.component-1.6.9}/src/keboola.component.egg-info/requires.txt +0 -0
- {keboola.component-1.6.7 → keboola.component-1.6.9}/src/keboola.component.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: keboola.component
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.9
|
|
4
4
|
Summary: General library for Python applications running in Keboola Connection environment
|
|
5
5
|
Home-page: https://github.com/keboola/python-component
|
|
6
6
|
Author: Keboola KDS Team
|
|
@@ -98,8 +98,11 @@ e.g.
|
|
|
98
98
|
- All Environment variables are loaded
|
|
99
99
|
|
|
100
100
|
The optional parameter `data_folder_path` of the constructor is the path to the data directory. If not
|
|
101
|
-
provided
|
|
102
|
-
|
|
101
|
+
provided it will be determined in this order:
|
|
102
|
+
1. [`KBC_DATADIR` environment variable](/extend/common-interface/environment/#environment-variables) if present
|
|
103
|
+
2. -d / --data argument from the command line if present
|
|
104
|
+
3. data folder inside the current working directory if present
|
|
105
|
+
4. data folder inside the parent directory of the current working directory if present
|
|
103
106
|
|
|
104
107
|
The class can be either extended or just instantiated and manipulated like object. The `CommonInterface` class is
|
|
105
108
|
exposed in the `keboola.component` namespace:
|
|
@@ -182,7 +185,7 @@ first_table = input_tables[0]
|
|
|
182
185
|
logging.info(f'The first table named: "{first_table.name}" is at path: {first_table.full_path}')
|
|
183
186
|
|
|
184
187
|
# get information from table manifest
|
|
185
|
-
logging.info(f'The first table has following columns defined in the manifest {first_table.
|
|
188
|
+
logging.info(f'The first table has following columns defined in the manifest {first_table.column_names}')
|
|
186
189
|
|
|
187
190
|
```
|
|
188
191
|
|
|
@@ -242,7 +245,7 @@ ci = CommonInterface(data_folder_path='data')
|
|
|
242
245
|
|
|
243
246
|
# create container for the result
|
|
244
247
|
out = ci.create_out_table_definition("testDef",
|
|
245
|
-
|
|
248
|
+
schema=['foo', 'bar'],
|
|
246
249
|
destination='some-destination',
|
|
247
250
|
primary_key=['foo'],
|
|
248
251
|
incremental=True,
|
|
@@ -641,7 +644,7 @@ class Component(ComponentBase):
|
|
|
641
644
|
product_schema = self.get_table_schema_by_name('product')
|
|
642
645
|
product_table = self.create_out_table_definition_from_schema(product_schema)
|
|
643
646
|
with open(product_table.full_path, 'w') as outfile:
|
|
644
|
-
writer = csv.DictWriter(outfile, fieldnames=product_table.
|
|
647
|
+
writer = csv.DictWriter(outfile, fieldnames=product_table.column_names)
|
|
645
648
|
writer.writerows(DUMMY_PRODUCT_DATA)
|
|
646
649
|
self.write_manifest(product_table)
|
|
647
650
|
```
|
|
@@ -79,8 +79,11 @@ e.g.
|
|
|
79
79
|
- All Environment variables are loaded
|
|
80
80
|
|
|
81
81
|
The optional parameter `data_folder_path` of the constructor is the path to the data directory. If not
|
|
82
|
-
provided
|
|
83
|
-
|
|
82
|
+
provided it will be determined in this order:
|
|
83
|
+
1. [`KBC_DATADIR` environment variable](/extend/common-interface/environment/#environment-variables) if present
|
|
84
|
+
2. -d / --data argument from the command line if present
|
|
85
|
+
3. data folder inside the current working directory if present
|
|
86
|
+
4. data folder inside the parent directory of the current working directory if present
|
|
84
87
|
|
|
85
88
|
The class can be either extended or just instantiated and manipulated like object. The `CommonInterface` class is
|
|
86
89
|
exposed in the `keboola.component` namespace:
|
|
@@ -163,7 +166,7 @@ first_table = input_tables[0]
|
|
|
163
166
|
logging.info(f'The first table named: "{first_table.name}" is at path: {first_table.full_path}')
|
|
164
167
|
|
|
165
168
|
# get information from table manifest
|
|
166
|
-
logging.info(f'The first table has following columns defined in the manifest {first_table.
|
|
169
|
+
logging.info(f'The first table has following columns defined in the manifest {first_table.column_names}')
|
|
167
170
|
|
|
168
171
|
```
|
|
169
172
|
|
|
@@ -223,7 +226,7 @@ ci = CommonInterface(data_folder_path='data')
|
|
|
223
226
|
|
|
224
227
|
# create container for the result
|
|
225
228
|
out = ci.create_out_table_definition("testDef",
|
|
226
|
-
|
|
229
|
+
schema=['foo', 'bar'],
|
|
227
230
|
destination='some-destination',
|
|
228
231
|
primary_key=['foo'],
|
|
229
232
|
incremental=True,
|
|
@@ -622,7 +625,7 @@ class Component(ComponentBase):
|
|
|
622
625
|
product_schema = self.get_table_schema_by_name('product')
|
|
623
626
|
product_table = self.create_out_table_definition_from_schema(product_schema)
|
|
624
627
|
with open(product_table.full_path, 'w') as outfile:
|
|
625
|
-
writer = csv.DictWriter(outfile, fieldnames=product_table.
|
|
628
|
+
writer = csv.DictWriter(outfile, fieldnames=product_table.column_names)
|
|
626
629
|
writer.writerows(DUMMY_PRODUCT_DATA)
|
|
627
630
|
self.write_manifest(product_table)
|
|
628
631
|
```
|
|
@@ -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.
|
|
@@ -496,7 +505,6 @@ class ColumnDefinition:
|
|
|
496
505
|
Represents the definition of a column within a table schema.
|
|
497
506
|
|
|
498
507
|
Attributes:
|
|
499
|
-
name (Optional[str]): The name of the column. Defaults to None.
|
|
500
508
|
data_types (Optional[Union[Dict[str, DataType], BaseType]]): Data types of the column for specified backend.
|
|
501
509
|
This can be a specific `DataType` or a `BaseType`, or a dictionary mapping from a string to one of these types.
|
|
502
510
|
Defaults to BaseType.String.
|
|
@@ -577,7 +585,7 @@ class SupportedManifestAttributes(SubscriptableDataclass):
|
|
|
577
585
|
to_remove = ['primary_key', 'columns', 'distribution_key', 'column_metadata', 'metadata']
|
|
578
586
|
attributes = list(set(attributes).difference(to_remove))
|
|
579
587
|
|
|
580
|
-
to_add = ['manifest_type', 'has_header', '
|
|
588
|
+
to_add = ['manifest_type', 'has_header', 'table_metadata', 'schema']
|
|
581
589
|
attributes.extend(to_add)
|
|
582
590
|
|
|
583
591
|
elif stage == 'in':
|
|
@@ -773,13 +781,14 @@ class TableDefinition(IODefinition):
|
|
|
773
781
|
|
|
774
782
|
MANIFEST_ATTRIBUTES = {'in': INPUT_MANIFEST_ATTRIBUTES,
|
|
775
783
|
'out': OUTPUT_MANIFEST_ATTRIBUTES}
|
|
784
|
+
SCHEMA_TYPE = Union[Dict[str, ColumnDefinition], TypeOrderedDict[str, ColumnDefinition], List[str]]
|
|
776
785
|
|
|
777
786
|
def __init__(self, name: str,
|
|
778
787
|
full_path: Optional[Union[str, None]] = None,
|
|
779
788
|
is_sliced: Optional[bool] = False,
|
|
780
789
|
destination: Optional[str] = '',
|
|
781
790
|
primary_key: Optional[List[str]] = None,
|
|
782
|
-
schema:
|
|
791
|
+
schema: SCHEMA_TYPE = None,
|
|
783
792
|
incremental: Optional[bool] = None,
|
|
784
793
|
table_metadata: Optional[TableMetadata] = None,
|
|
785
794
|
enclosure: Optional[str] = '"',
|
|
@@ -788,6 +797,7 @@ class TableDefinition(IODefinition):
|
|
|
788
797
|
stage: Optional[str] = 'out',
|
|
789
798
|
write_always: Optional[bool] = False,
|
|
790
799
|
has_header: Optional[bool] = None,
|
|
800
|
+
description: Optional[str] = None,
|
|
791
801
|
# input
|
|
792
802
|
**kwargs
|
|
793
803
|
):
|
|
@@ -815,6 +825,7 @@ class TableDefinition(IODefinition):
|
|
|
815
825
|
write_always: Bool: If true, the table will be saved to Storage even when the job execution
|
|
816
826
|
fails.
|
|
817
827
|
schema: (dict|lis[str]) Mapping of column names andColumnDefinition objects, or a list of names
|
|
828
|
+
description: str: Table description
|
|
818
829
|
|
|
819
830
|
"""
|
|
820
831
|
super().__init__(full_path)
|
|
@@ -824,7 +835,7 @@ class TableDefinition(IODefinition):
|
|
|
824
835
|
# initialize manifest properties
|
|
825
836
|
self._destination = None
|
|
826
837
|
self.destination = destination
|
|
827
|
-
self._schema = dict()
|
|
838
|
+
self._schema: Dict[str, ColumnDefinition] = dict()
|
|
828
839
|
|
|
829
840
|
if schema:
|
|
830
841
|
self.schema = schema
|
|
@@ -845,6 +856,8 @@ class TableDefinition(IODefinition):
|
|
|
845
856
|
if not table_metadata:
|
|
846
857
|
table_metadata = TableMetadata()
|
|
847
858
|
self.table_metadata = table_metadata
|
|
859
|
+
if description:
|
|
860
|
+
self.table_metadata.add_table_description(description)
|
|
848
861
|
|
|
849
862
|
self.delete_where_values = None
|
|
850
863
|
self.delete_where_column = None
|
|
@@ -893,7 +906,8 @@ class TableDefinition(IODefinition):
|
|
|
893
906
|
delimiter: Optional[str] = ',',
|
|
894
907
|
delete_where: Optional[dict] = None,
|
|
895
908
|
write_always: Optional[bool] = False,
|
|
896
|
-
schema:
|
|
909
|
+
schema: SCHEMA_TYPE = None,
|
|
910
|
+
description: Optional[str] = None,
|
|
897
911
|
**kwargs
|
|
898
912
|
):
|
|
899
913
|
"""
|
|
@@ -914,6 +928,7 @@ class TableDefinition(IODefinition):
|
|
|
914
928
|
delete_where (Optional[dict]): Criteria for row deletion in incremental loads. Defaults to None.
|
|
915
929
|
write_always (Optional[bool]): If True, the table will be saved to storage even if the job fails.
|
|
916
930
|
schema (Optional[List[ColumnDefinition]]): Dictionary of ColumnDefinition objects.
|
|
931
|
+
description (Optional[str]): The description of the table. Defaults to None.
|
|
917
932
|
|
|
918
933
|
Returns:
|
|
919
934
|
TableDefinition: An instance of TableDefinition configured for output tables.
|
|
@@ -929,6 +944,7 @@ class TableDefinition(IODefinition):
|
|
|
929
944
|
delete_where=delete_where,
|
|
930
945
|
write_always=write_always,
|
|
931
946
|
schema=schema,
|
|
947
|
+
description=description,
|
|
932
948
|
**kwargs
|
|
933
949
|
)
|
|
934
950
|
|
|
@@ -1155,7 +1171,7 @@ class TableDefinition(IODefinition):
|
|
|
1155
1171
|
name=name,
|
|
1156
1172
|
destination=manifest.get('destination'),
|
|
1157
1173
|
schema=cls.return_schema_from_manifest(manifest),
|
|
1158
|
-
incremental=manifest.get('incremental'),
|
|
1174
|
+
incremental=manifest.get('incremental', False),
|
|
1159
1175
|
primary_key=manifest.get('primary_key'),
|
|
1160
1176
|
write_always=manifest.get('write_always', False),
|
|
1161
1177
|
delimiter=manifest.get('delimiter', ','),
|
|
@@ -1255,7 +1271,6 @@ class TableDefinition(IODefinition):
|
|
|
1255
1271
|
'column_metadata': self.table_metadata._get_legacy_column_metadata_for_manifest(),
|
|
1256
1272
|
'manifest_type': manifest_type,
|
|
1257
1273
|
'has_header': self.has_header,
|
|
1258
|
-
'description': None,
|
|
1259
1274
|
'table_metadata': self.table_metadata.get_table_metadata_for_manifest(),
|
|
1260
1275
|
'delete_where_column': self.delete_where_column,
|
|
1261
1276
|
'delete_where_values': self.delete_where_values,
|
|
@@ -1263,6 +1278,7 @@ class TableDefinition(IODefinition):
|
|
|
1263
1278
|
'schema': [col.to_dict(name)
|
|
1264
1279
|
for name, col in self.schema.items()] if isinstance(self.schema, (OrderedDict, dict)) else []
|
|
1265
1280
|
}
|
|
1281
|
+
|
|
1266
1282
|
if legacy_manifest or self.stage == 'in':
|
|
1267
1283
|
fields['columns'] = self.column_names
|
|
1268
1284
|
|
|
@@ -1387,8 +1403,8 @@ class TableDefinition(IODefinition):
|
|
|
1387
1403
|
|
|
1388
1404
|
@incremental.setter
|
|
1389
1405
|
def incremental(self, incremental: bool):
|
|
1390
|
-
if incremental:
|
|
1391
|
-
self._incremental =
|
|
1406
|
+
if incremental is not None:
|
|
1407
|
+
self._incremental = incremental
|
|
1392
1408
|
|
|
1393
1409
|
@property
|
|
1394
1410
|
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
|
|
|
@@ -134,10 +134,14 @@ class CommonInterface:
|
|
|
134
134
|
args, unknown = argparser.parse_known_args()
|
|
135
135
|
data_folder_path = args.data_dir
|
|
136
136
|
|
|
137
|
-
if data_folder_path
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
137
|
+
if not data_folder_path:
|
|
138
|
+
cwd = Path(os.getcwd())
|
|
139
|
+
if self.environment_variables.data_dir:
|
|
140
|
+
data_folder_path = self.environment_variables.data_dir
|
|
141
|
+
elif cwd.resolve().joinpath('data').is_dir():
|
|
142
|
+
data_folder_path = cwd.resolve().joinpath('data').as_posix()
|
|
143
|
+
elif cwd.resolve().parent.joinpath('data').is_dir():
|
|
144
|
+
data_folder_path = cwd.resolve().parent.joinpath('data').as_posix()
|
|
141
145
|
|
|
142
146
|
return data_folder_path
|
|
143
147
|
|
|
@@ -338,7 +342,8 @@ class CommonInterface:
|
|
|
338
342
|
write_always: bool = False,
|
|
339
343
|
schema: Union[
|
|
340
344
|
OrderedDict[str, ColumnDefinition], list[str]] = None,
|
|
341
|
-
has_header: Optional[bool] = None
|
|
345
|
+
has_header: Optional[bool] = None,
|
|
346
|
+
description: Optional[str] = None) -> dao.TableDefinition:
|
|
342
347
|
"""
|
|
343
348
|
Helper method for dao.TableDefinition creation along with the "manifest".
|
|
344
349
|
It initializes path according to the storage_stage type.
|
|
@@ -381,6 +386,7 @@ class CommonInterface:
|
|
|
381
386
|
primary_key=primary_key,
|
|
382
387
|
columns=columns,
|
|
383
388
|
incremental=incremental,
|
|
389
|
+
description=description,
|
|
384
390
|
table_metadata=table_metadata,
|
|
385
391
|
enclosure=enclosure,
|
|
386
392
|
delimiter=delimiter,
|
|
@@ -427,13 +433,11 @@ class CommonInterface:
|
|
|
427
433
|
delete_where=delete_where,
|
|
428
434
|
schema=schema)
|
|
429
435
|
|
|
430
|
-
SCHEMA_TYPE = Union[Dict[str, ColumnDefinition], OrderedDict[str, ColumnDefinition], List[str]]
|
|
431
|
-
|
|
432
436
|
def create_out_table_definition(self, name: str,
|
|
433
437
|
is_sliced: bool = False,
|
|
434
438
|
destination: str = '',
|
|
435
439
|
primary_key: List[str] = None,
|
|
436
|
-
schema: SCHEMA_TYPE = None,
|
|
440
|
+
schema: TableDefinition.SCHEMA_TYPE = None,
|
|
437
441
|
incremental: bool = None,
|
|
438
442
|
table_metadata: dao.TableMetadata = None,
|
|
439
443
|
enclosure: str = '"',
|
|
@@ -441,6 +445,7 @@ class CommonInterface:
|
|
|
441
445
|
delete_where: dict = None,
|
|
442
446
|
write_always: bool = False,
|
|
443
447
|
has_header: Optional[bool] = None,
|
|
448
|
+
description: Optional[str] = None,
|
|
444
449
|
**kwargs
|
|
445
450
|
) -> dao.TableDefinition:
|
|
446
451
|
"""
|
|
@@ -464,6 +469,7 @@ class CommonInterface:
|
|
|
464
469
|
fails.
|
|
465
470
|
has_header:Optional[bool] = flag whether the header is present in the file,
|
|
466
471
|
if None legacy method is used
|
|
472
|
+
description: Table description
|
|
467
473
|
"""
|
|
468
474
|
|
|
469
475
|
return self._create_table_definition(name=name,
|
|
@@ -479,7 +485,8 @@ class CommonInterface:
|
|
|
479
485
|
delete_where=delete_where,
|
|
480
486
|
write_always=write_always,
|
|
481
487
|
schema=schema,
|
|
482
|
-
has_header=has_header
|
|
488
|
+
has_header=has_header,
|
|
489
|
+
description=description)
|
|
483
490
|
|
|
484
491
|
# # File processing
|
|
485
492
|
|
|
@@ -956,7 +963,6 @@ class CommonInterface:
|
|
|
956
963
|
"""
|
|
957
964
|
|
|
958
965
|
if not legacy_manifest:
|
|
959
|
-
|
|
960
966
|
legacy_manifest = self._expects_legacy_manifest()
|
|
961
967
|
|
|
962
968
|
manifest = io_definition.get_manifest_dictionary(legacy_queue=self.is_legacy_queue,
|
|
@@ -967,7 +973,7 @@ class CommonInterface:
|
|
|
967
973
|
json.dump(manifest, manifest_file)
|
|
968
974
|
|
|
969
975
|
def _expects_legacy_manifest(self) -> bool:
|
|
970
|
-
legacy_manifest
|
|
976
|
+
legacy_manifest = \
|
|
971
977
|
(self._running_in_kbc and self.environment_variables.data_type_support not in ('authoritative', 'hints'))
|
|
972
978
|
|
|
973
979
|
om_override = self.configuration.config_data.get('storage', {}).get('output', {}).get('data_type_support')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: keboola.component
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.9
|
|
4
4
|
Summary: General library for Python applications running in Keboola Connection environment
|
|
5
5
|
Home-page: https://github.com/keboola/python-component
|
|
6
6
|
Author: Keboola KDS Team
|
|
@@ -98,8 +98,11 @@ e.g.
|
|
|
98
98
|
- All Environment variables are loaded
|
|
99
99
|
|
|
100
100
|
The optional parameter `data_folder_path` of the constructor is the path to the data directory. If not
|
|
101
|
-
provided
|
|
102
|
-
|
|
101
|
+
provided it will be determined in this order:
|
|
102
|
+
1. [`KBC_DATADIR` environment variable](/extend/common-interface/environment/#environment-variables) if present
|
|
103
|
+
2. -d / --data argument from the command line if present
|
|
104
|
+
3. data folder inside the current working directory if present
|
|
105
|
+
4. data folder inside the parent directory of the current working directory if present
|
|
103
106
|
|
|
104
107
|
The class can be either extended or just instantiated and manipulated like object. The `CommonInterface` class is
|
|
105
108
|
exposed in the `keboola.component` namespace:
|
|
@@ -182,7 +185,7 @@ first_table = input_tables[0]
|
|
|
182
185
|
logging.info(f'The first table named: "{first_table.name}" is at path: {first_table.full_path}')
|
|
183
186
|
|
|
184
187
|
# get information from table manifest
|
|
185
|
-
logging.info(f'The first table has following columns defined in the manifest {first_table.
|
|
188
|
+
logging.info(f'The first table has following columns defined in the manifest {first_table.column_names}')
|
|
186
189
|
|
|
187
190
|
```
|
|
188
191
|
|
|
@@ -242,7 +245,7 @@ ci = CommonInterface(data_folder_path='data')
|
|
|
242
245
|
|
|
243
246
|
# create container for the result
|
|
244
247
|
out = ci.create_out_table_definition("testDef",
|
|
245
|
-
|
|
248
|
+
schema=['foo', 'bar'],
|
|
246
249
|
destination='some-destination',
|
|
247
250
|
primary_key=['foo'],
|
|
248
251
|
incremental=True,
|
|
@@ -641,7 +644,7 @@ class Component(ComponentBase):
|
|
|
641
644
|
product_schema = self.get_table_schema_by_name('product')
|
|
642
645
|
product_table = self.create_out_table_definition_from_schema(product_schema)
|
|
643
646
|
with open(product_table.full_path, 'w') as outfile:
|
|
644
|
-
writer = csv.DictWriter(outfile, fieldnames=product_table.
|
|
647
|
+
writer = csv.DictWriter(outfile, fieldnames=product_table.column_names)
|
|
645
648
|
writer.writerows(DUMMY_PRODUCT_DATA)
|
|
646
649
|
self.write_manifest(product_table)
|
|
647
650
|
```
|
|
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.9}/src/keboola.component.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{keboola.component-1.6.7 → keboola.component-1.6.9}/src/keboola.component.egg-info/not-zip-safe
RENAMED
|
File without changes
|
{keboola.component-1.6.7 → keboola.component-1.6.9}/src/keboola.component.egg-info/requires.txt
RENAMED
|
File without changes
|
{keboola.component-1.6.7 → keboola.component-1.6.9}/src/keboola.component.egg-info/top_level.txt
RENAMED
|
File without changes
|