python-table-converter 0.2.9__tar.gz → 0.2.11__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.
- {python_table_converter-0.2.9 → python_table_converter-0.2.11}/PKG-INFO +1 -1
- {python_table_converter-0.2.9 → python_table_converter-0.2.11}/pyproject.toml +1 -1
- python_table_converter-0.2.11/table_converter/__init__.py +2 -0
- {python_table_converter-0.2.9 → python_table_converter-0.2.11}/table_converter/commands/convert_tables.py +12 -0
- {python_table_converter-0.2.9 → python_table_converter-0.2.11}/table_converter/core/config.py +57 -4
- {python_table_converter-0.2.9 → python_table_converter-0.2.11}/table_converter/core/convert.py +79 -17
- python_table_converter-0.2.9/table_converter/__init__.py +0 -2
- {python_table_converter-0.2.9 → python_table_converter-0.2.11}/LICENSE +0 -0
- {python_table_converter-0.2.9 → python_table_converter-0.2.11}/README.md +0 -0
- {python_table_converter-0.2.9 → python_table_converter-0.2.11}/table_converter/cli.py +0 -0
- {python_table_converter-0.2.9 → python_table_converter-0.2.11}/table_converter/core/constants.py +0 -0
- {python_table_converter-0.2.9 → python_table_converter-0.2.11}/table_converter/core/functions/assign_id.py +0 -0
- {python_table_converter-0.2.9 → python_table_converter-0.2.11}/table_converter/core/functions/flatten.py +0 -0
- {python_table_converter-0.2.9 → python_table_converter-0.2.11}/table_converter/core/functions/get_field_value.py +0 -0
- {python_table_converter-0.2.9 → python_table_converter-0.2.11}/table_converter/core/functions/search_column_value.py +0 -0
- {python_table_converter-0.2.9 → python_table_converter-0.2.11}/table_converter/core/functions/set_field_value.py +0 -0
|
@@ -15,9 +15,11 @@ def run(
|
|
|
15
15
|
config_path = args.config,
|
|
16
16
|
assign_constants = args.assign_constants,
|
|
17
17
|
assign_formats = args.assign_formats,
|
|
18
|
+
str_filters = args.filters,
|
|
18
19
|
pickup_columns= args.pickup_columns,
|
|
19
20
|
fields_to_split_by_newline = args.split_by_newline,
|
|
20
21
|
fields_to_assign_ids = args.assign_ids,
|
|
22
|
+
str_omit_fields= args.omit_fields,
|
|
21
23
|
output_debug = args.output_debug,
|
|
22
24
|
)
|
|
23
25
|
|
|
@@ -66,6 +68,16 @@ def setup_parser(
|
|
|
66
68
|
type=str,
|
|
67
69
|
help='Field to assign formats',
|
|
68
70
|
)
|
|
71
|
+
parser.add_argument(
|
|
72
|
+
'--filters', '--filter', '-f',
|
|
73
|
+
type=str,
|
|
74
|
+
help='Expression list to filter records',
|
|
75
|
+
)
|
|
76
|
+
parser.add_argument(
|
|
77
|
+
'--omit-fields', '--omit',
|
|
78
|
+
type=str,
|
|
79
|
+
help='Field to omit',
|
|
80
|
+
)
|
|
69
81
|
parser.add_argument(
|
|
70
82
|
'--output-debug',
|
|
71
83
|
action='store_true',
|
{python_table_converter-0.2.9 → python_table_converter-0.2.11}/table_converter/core/config.py
RENAMED
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
from collections import OrderedDict
|
|
4
4
|
import dataclasses
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import (
|
|
6
|
+
Literal,
|
|
7
|
+
Mapping,
|
|
8
|
+
)
|
|
6
9
|
|
|
7
10
|
from icecream import ic
|
|
8
11
|
import yaml
|
|
@@ -18,13 +21,27 @@ class AssignIdConfig:
|
|
|
18
21
|
primary: list[str]
|
|
19
22
|
context: list[str] | None = None
|
|
20
23
|
|
|
24
|
+
@dataclasses.dataclass
|
|
25
|
+
class FilterConfig:
|
|
26
|
+
field: str
|
|
27
|
+
operator: Literal['==', '!=', '>', '>=', '<', '<=']
|
|
28
|
+
value: str
|
|
29
|
+
|
|
30
|
+
@dataclasses.dataclass
|
|
31
|
+
class SplitConfig:
|
|
32
|
+
field: str
|
|
33
|
+
delimiter: str
|
|
34
|
+
|
|
21
35
|
@dataclasses.dataclass
|
|
22
36
|
class ProcessConfig:
|
|
23
37
|
assign_constants: FlatFieldMap = dataclasses.field(default_factory=OrderedDict)
|
|
24
38
|
assign_formats: FlatFieldMap = dataclasses.field(default_factory=OrderedDict)
|
|
25
|
-
#assign_ids: FlatFieldMap = dataclasses.field(default_factory=OrderedDict)
|
|
26
39
|
assign_ids: Mapping[str, AssignIdConfig] = dataclasses.field(default_factory=OrderedDict)
|
|
27
|
-
|
|
40
|
+
#filter_eq: FlatFieldMap = dataclasses.field(default_factory=OrderedDict)
|
|
41
|
+
filter: list[FilterConfig] = dataclasses.field(default_factory=list)
|
|
42
|
+
omit_fields: list[str] = dataclasses.field(default_factory=list)
|
|
43
|
+
#split_by_newline: FlatFieldMap = dataclasses.field(default_factory=OrderedDict)
|
|
44
|
+
split: Mapping[str, SplitConfig] = dataclasses.field(default_factory=OrderedDict)
|
|
28
45
|
|
|
29
46
|
def __setitem__(self, key, value):
|
|
30
47
|
setattr(self, key, value)
|
|
@@ -65,12 +82,12 @@ def setup_process_config(
|
|
|
65
82
|
for process_key in [
|
|
66
83
|
'assign_constants',
|
|
67
84
|
'assign_formats',
|
|
68
|
-
'split_by_newline',
|
|
69
85
|
]:
|
|
70
86
|
dict_subprocess = dict_process.get(process_key)
|
|
71
87
|
if isinstance(dict_subprocess, Mapping):
|
|
72
88
|
config.process[process_key] = flatten(loaded['process'][process_key])
|
|
73
89
|
setup_process_assign_ids_config(config, dict_process)
|
|
90
|
+
setup_process_split_config(config, dict_process)
|
|
74
91
|
|
|
75
92
|
def setup_process_assign_ids_config(
|
|
76
93
|
config: Config,
|
|
@@ -108,3 +125,39 @@ def setup_process_assign_ids_config(
|
|
|
108
125
|
raise ValueError(
|
|
109
126
|
f'Unsupported assign_ids value type: {type(value)}'
|
|
110
127
|
)
|
|
128
|
+
|
|
129
|
+
def setup_process_split_config(
|
|
130
|
+
config: Config,
|
|
131
|
+
dict_process: Mapping,
|
|
132
|
+
):
|
|
133
|
+
dict_subprocess = dict_process.get('split')
|
|
134
|
+
if isinstance(dict_subprocess, Mapping):
|
|
135
|
+
for key, value in dict_subprocess.items():
|
|
136
|
+
if isinstance(value, Mapping):
|
|
137
|
+
field = value.get('field')
|
|
138
|
+
if not field:
|
|
139
|
+
ic.enable()
|
|
140
|
+
ic(value)
|
|
141
|
+
ic(value.get('field'))
|
|
142
|
+
raise ValueError(
|
|
143
|
+
'Field is required for split.'
|
|
144
|
+
)
|
|
145
|
+
delimiter = value.get('delimiter')
|
|
146
|
+
if not delimiter:
|
|
147
|
+
ic.enable()
|
|
148
|
+
ic(value)
|
|
149
|
+
ic(value.get('delimiter'))
|
|
150
|
+
raise ValueError(
|
|
151
|
+
'Delimiter is required for split.'
|
|
152
|
+
)
|
|
153
|
+
config.process.split[key] = SplitConfig(
|
|
154
|
+
field = field,
|
|
155
|
+
delimiter = delimiter,
|
|
156
|
+
)
|
|
157
|
+
else:
|
|
158
|
+
ic.enable()
|
|
159
|
+
ic(value)
|
|
160
|
+
ic(type(value))
|
|
161
|
+
raise ValueError(
|
|
162
|
+
f'Unsupported assign_ids value type: {type(value)}'
|
|
163
|
+
)
|
{python_table_converter-0.2.9 → python_table_converter-0.2.11}/table_converter/core/convert.py
RENAMED
|
@@ -14,7 +14,11 @@ import pandas as pd
|
|
|
14
14
|
|
|
15
15
|
# local
|
|
16
16
|
|
|
17
|
-
from . config import
|
|
17
|
+
from . config import (
|
|
18
|
+
FilterConfig,
|
|
19
|
+
SplitConfig,
|
|
20
|
+
setup_config,
|
|
21
|
+
)
|
|
18
22
|
from . constants import (
|
|
19
23
|
FILE_FIELD,
|
|
20
24
|
INPUT_FIELD,
|
|
@@ -65,7 +69,7 @@ def load_json(
|
|
|
65
69
|
data = json.load(f)
|
|
66
70
|
if not isinstance(data, list):
|
|
67
71
|
raise ValueError(f'Invalid JSON array data: {input_file}')
|
|
68
|
-
ic(data[0])
|
|
72
|
+
#ic(data[0])
|
|
69
73
|
rows = []
|
|
70
74
|
for row in data:
|
|
71
75
|
new_row = flatten(row)
|
|
@@ -103,9 +107,9 @@ def save_json(
|
|
|
103
107
|
#)
|
|
104
108
|
#ic(df.iloc[0])
|
|
105
109
|
data = df.to_dict(orient='records')
|
|
106
|
-
ic(data[0])
|
|
110
|
+
#ic(data[0])
|
|
107
111
|
data = [nest(row) for row in data]
|
|
108
|
-
ic(data[0])
|
|
112
|
+
#ic(data[0])
|
|
109
113
|
with open(output_file, 'w') as f:
|
|
110
114
|
json.dump(
|
|
111
115
|
data,
|
|
@@ -190,27 +194,50 @@ def remap_columns(
|
|
|
190
194
|
new_row[column] = row[column]
|
|
191
195
|
return new_row
|
|
192
196
|
|
|
193
|
-
def
|
|
197
|
+
def split_fields(
|
|
194
198
|
row: OrderedDict,
|
|
195
|
-
|
|
199
|
+
dict_config: list[SplitConfig],
|
|
196
200
|
):
|
|
197
201
|
new_row = OrderedDict(row)
|
|
198
|
-
for
|
|
199
|
-
value, found = search_column_value(row,
|
|
202
|
+
for dst, config in dict_config.items():
|
|
203
|
+
value, found = search_column_value(row, config.field)
|
|
200
204
|
if found:
|
|
201
205
|
if isinstance(value, str):
|
|
202
|
-
new_value = value.split(
|
|
203
|
-
|
|
206
|
+
new_value = value.split(config.delimiter)
|
|
207
|
+
new_value = list(filter(None, new_value))
|
|
208
|
+
if not new_value:
|
|
209
|
+
ic(dst, config, value)
|
|
210
|
+
new_row[f'{STAGING_FIELD}.{dst}'] = new_value
|
|
204
211
|
else:
|
|
205
|
-
new_row[f'{STAGING_FIELD}.{
|
|
212
|
+
new_row[f'{STAGING_FIELD}.{dst}'] = value
|
|
206
213
|
return new_row
|
|
207
214
|
|
|
215
|
+
def filter_row(
|
|
216
|
+
row: OrderedDict,
|
|
217
|
+
list_filters: list[FilterConfig],
|
|
218
|
+
):
|
|
219
|
+
for config in list_filters:
|
|
220
|
+
value, found = search_column_value(row, config.field)
|
|
221
|
+
if config.operator == '==':
|
|
222
|
+
if not found:
|
|
223
|
+
return False
|
|
224
|
+
if str(value) != str(config.value):
|
|
225
|
+
return False
|
|
226
|
+
elif config.operator == '!=':
|
|
227
|
+
if str(value) == str(config.value):
|
|
228
|
+
return False
|
|
229
|
+
else:
|
|
230
|
+
raise ValueError(f'Unsupported operator: {config.operator}')
|
|
231
|
+
return True
|
|
232
|
+
|
|
208
233
|
def convert(
|
|
209
234
|
input_files: list[str],
|
|
210
235
|
output_file: str | None = None,
|
|
211
236
|
config_path: str | None = None,
|
|
212
237
|
assign_constants: str | None = None,
|
|
213
238
|
assign_formats: str | None = None,
|
|
239
|
+
str_filters: str | None = None,
|
|
240
|
+
str_omit_fields: str | None = None,
|
|
214
241
|
pickup_columns: str | None = None,
|
|
215
242
|
fields_to_split_by_newline: str | None = None,
|
|
216
243
|
fields_to_assign_ids: str | None = None,
|
|
@@ -252,9 +279,36 @@ def convert(
|
|
|
252
279
|
for field in fields:
|
|
253
280
|
if '=' in field:
|
|
254
281
|
dst, src = field.split('=')
|
|
255
|
-
config.process.split_by_newline[dst] = src
|
|
282
|
+
#config.process.split_by_newline[dst] = src
|
|
283
|
+
config.process.split[dst] = SplitConfig(
|
|
284
|
+
field = src,
|
|
285
|
+
delimiter = '\n',
|
|
286
|
+
)
|
|
256
287
|
else:
|
|
257
288
|
raise ValueError(f'Invalid split by newline: {field}')
|
|
289
|
+
if str_filters:
|
|
290
|
+
fields = str_filters.split(',')
|
|
291
|
+
for field in fields:
|
|
292
|
+
if '==' in field:
|
|
293
|
+
column, value = field.split('==')
|
|
294
|
+
config.process.filter.append(FilterConfig(
|
|
295
|
+
field = column,
|
|
296
|
+
operator = '==',
|
|
297
|
+
value = value,
|
|
298
|
+
))
|
|
299
|
+
elif '!=' in field:
|
|
300
|
+
column, value = field.split('!=')
|
|
301
|
+
config.process.filter.append(FilterConfig(
|
|
302
|
+
field = column,
|
|
303
|
+
operator = '!=',
|
|
304
|
+
value = value,
|
|
305
|
+
))
|
|
306
|
+
else:
|
|
307
|
+
raise ValueError(f'Invalid filter eq: {field}')
|
|
308
|
+
if str_omit_fields:
|
|
309
|
+
fields = str_omit_fields.split(',')
|
|
310
|
+
for field in fields:
|
|
311
|
+
config.process.omit_fields.append(field)
|
|
258
312
|
if fields_to_assign_ids:
|
|
259
313
|
setup_assign_ids(config, fields_to_assign_ids)
|
|
260
314
|
if output_file:
|
|
@@ -293,24 +347,32 @@ def convert(
|
|
|
293
347
|
new_flat_row = map_constants(new_flat_row, config.process.assign_constants)
|
|
294
348
|
if config.map:
|
|
295
349
|
new_flat_row = remap_columns(new_flat_row, config.map)
|
|
296
|
-
if config.process.
|
|
297
|
-
new_flat_row =
|
|
350
|
+
if config.process.split:
|
|
351
|
+
new_flat_row = split_fields(new_flat_row, config.process.split)
|
|
298
352
|
if config.process.assign_ids:
|
|
299
353
|
new_flat_row = assign_id(new_flat_row, config.process.assign_ids, id_context_map)
|
|
300
354
|
if config.process.assign_formats:
|
|
301
355
|
new_flat_row = map_formats(new_flat_row, config.process.assign_formats)
|
|
302
356
|
if config.map:
|
|
303
357
|
new_flat_row = remap_columns(new_flat_row, config.map)
|
|
358
|
+
if config.process.filter:
|
|
359
|
+
if not filter_row(new_flat_row, config.process.filter):
|
|
360
|
+
continue
|
|
361
|
+
if config.process.omit_fields:
|
|
362
|
+
for field in config.process.omit_fields:
|
|
363
|
+
new_flat_row.pop(field, None)
|
|
304
364
|
if not output_debug:
|
|
305
|
-
new_flat_row.
|
|
365
|
+
for key in list(new_flat_row.keys()):
|
|
366
|
+
if key.startswith(STAGING_FIELD):
|
|
367
|
+
new_flat_row.pop(key)
|
|
306
368
|
new_flat_rows.append(new_flat_row)
|
|
307
369
|
new_df = pd.DataFrame(new_flat_rows)
|
|
308
370
|
df_list.append(new_df)
|
|
309
371
|
all_df = pd.concat(df_list)
|
|
310
372
|
#ic(all_df)
|
|
311
373
|
ic(len(all_df))
|
|
312
|
-
ic(all_df.columns)
|
|
313
|
-
ic(all_df.iloc[0])
|
|
374
|
+
#ic(all_df.columns)
|
|
375
|
+
#ic(all_df.iloc[0])
|
|
314
376
|
if output_file:
|
|
315
377
|
ic('Saing to: ', output_file)
|
|
316
378
|
saver(all_df, output_file)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_table_converter-0.2.9 → python_table_converter-0.2.11}/table_converter/core/constants.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|