python-table-converter 0.2.8__tar.gz → 0.2.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.
- {python_table_converter-0.2.8 → python_table_converter-0.2.9}/PKG-INFO +1 -1
- {python_table_converter-0.2.8 → python_table_converter-0.2.9}/pyproject.toml +1 -1
- python_table_converter-0.2.9/table_converter/__init__.py +2 -0
- {python_table_converter-0.2.8 → python_table_converter-0.2.9}/table_converter/core/config.py +5 -18
- {python_table_converter-0.2.8 → python_table_converter-0.2.9}/table_converter/core/convert.py +67 -51
- {python_table_converter-0.2.8 → python_table_converter-0.2.9}/table_converter/core/functions/assign_id.py +6 -2
- python_table_converter-0.2.9/table_converter/core/functions/flatten.py +24 -0
- python_table_converter-0.2.9/table_converter/core/functions/search_column_value.py +25 -0
- {python_table_converter-0.2.8 → python_table_converter-0.2.9}/table_converter/core/functions/set_field_value.py +1 -0
- python_table_converter-0.2.8/table_converter/__init__.py +0 -2
- python_table_converter-0.2.8/table_converter/core/functions/search_column_value.py +0 -30
- {python_table_converter-0.2.8 → python_table_converter-0.2.9}/LICENSE +0 -0
- {python_table_converter-0.2.8 → python_table_converter-0.2.9}/README.md +0 -0
- {python_table_converter-0.2.8 → python_table_converter-0.2.9}/table_converter/cli.py +0 -0
- {python_table_converter-0.2.8 → python_table_converter-0.2.9}/table_converter/commands/convert_tables.py +0 -0
- {python_table_converter-0.2.8 → python_table_converter-0.2.9}/table_converter/core/constants.py +0 -0
- {python_table_converter-0.2.8 → python_table_converter-0.2.9}/table_converter/core/functions/get_field_value.py +0 -0
{python_table_converter-0.2.8 → python_table_converter-0.2.9}/table_converter/core/config.py
RENAMED
|
@@ -7,13 +7,15 @@ from typing import Mapping
|
|
|
7
7
|
from icecream import ic
|
|
8
8
|
import yaml
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
from . functions.flatten import (
|
|
11
|
+
FieldMap,
|
|
12
|
+
FlatFieldMap,
|
|
13
|
+
flatten,
|
|
14
|
+
)
|
|
12
15
|
|
|
13
16
|
@dataclasses.dataclass
|
|
14
17
|
class AssignIdConfig:
|
|
15
18
|
primary: list[str]
|
|
16
|
-
#given: list[str] | None = None
|
|
17
19
|
context: list[str] | None = None
|
|
18
20
|
|
|
19
21
|
@dataclasses.dataclass
|
|
@@ -32,21 +34,6 @@ class Config:
|
|
|
32
34
|
map: FieldMap = dataclasses.field(default_factory=OrderedDict)
|
|
33
35
|
process: ProcessConfig = dataclasses.field(default_factory=ProcessConfig)
|
|
34
36
|
|
|
35
|
-
def flatten(
|
|
36
|
-
mapping: FieldMap,
|
|
37
|
-
parent_key: str = '',
|
|
38
|
-
new_mapping: FlatFieldMap | None = None,
|
|
39
|
-
) -> FlatFieldMap:
|
|
40
|
-
if new_mapping is None:
|
|
41
|
-
new_mapping = OrderedDict()
|
|
42
|
-
for key, mapped in mapping.items():
|
|
43
|
-
new_key = f'{parent_key}.{key}' if parent_key else key
|
|
44
|
-
if isinstance(mapped, Mapping):
|
|
45
|
-
flatten(mapped, new_key, new_mapping)
|
|
46
|
-
else:
|
|
47
|
-
new_mapping[new_key] = mapped
|
|
48
|
-
return new_mapping
|
|
49
|
-
|
|
50
37
|
def setup_config(
|
|
51
38
|
config_path: str | None = None,
|
|
52
39
|
):
|
{python_table_converter-0.2.8 → python_table_converter-0.2.9}/table_converter/core/convert.py
RENAMED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
+
import math
|
|
4
5
|
import os
|
|
5
6
|
|
|
6
7
|
from collections import OrderedDict
|
|
@@ -24,7 +25,11 @@ from . functions.assign_id import (
|
|
|
24
25
|
create_id_context_map,
|
|
25
26
|
setup_assign_ids,
|
|
26
27
|
)
|
|
28
|
+
from . functions.flatten import (
|
|
29
|
+
flatten,
|
|
30
|
+
)
|
|
27
31
|
from . functions.get_field_value import get_field_value
|
|
32
|
+
from . functions.search_column_value import search_column_value
|
|
28
33
|
from . functions.set_field_value import set_field_value
|
|
29
34
|
|
|
30
35
|
dict_loaders: dict[str, callable] = {}
|
|
@@ -58,9 +63,31 @@ def load_json(
|
|
|
58
63
|
):
|
|
59
64
|
with open(input_file, 'r') as f:
|
|
60
65
|
data = json.load(f)
|
|
61
|
-
|
|
66
|
+
if not isinstance(data, list):
|
|
67
|
+
raise ValueError(f'Invalid JSON array data: {input_file}')
|
|
68
|
+
ic(data[0])
|
|
69
|
+
rows = []
|
|
70
|
+
for row in data:
|
|
71
|
+
new_row = flatten(row)
|
|
72
|
+
rows.append(new_row)
|
|
73
|
+
df = pd.DataFrame(rows)
|
|
62
74
|
return df
|
|
63
75
|
|
|
76
|
+
def nest(
|
|
77
|
+
row: OrderedDict,
|
|
78
|
+
remove_nan: bool = True,
|
|
79
|
+
):
|
|
80
|
+
new_row = OrderedDict()
|
|
81
|
+
for key, value in row.items():
|
|
82
|
+
if isinstance(value, OrderedDict):
|
|
83
|
+
value = nest(value)
|
|
84
|
+
if isinstance(value, float):
|
|
85
|
+
if math.isnan(value):
|
|
86
|
+
if remove_nan:
|
|
87
|
+
continue
|
|
88
|
+
set_field_value(new_row, key, value)
|
|
89
|
+
return new_row
|
|
90
|
+
|
|
64
91
|
@register_saver('.json')
|
|
65
92
|
def save_json(
|
|
66
93
|
df: pd.DataFrame,
|
|
@@ -76,6 +103,9 @@ def save_json(
|
|
|
76
103
|
#)
|
|
77
104
|
#ic(df.iloc[0])
|
|
78
105
|
data = df.to_dict(orient='records')
|
|
106
|
+
ic(data[0])
|
|
107
|
+
data = [nest(row) for row in data]
|
|
108
|
+
ic(data[0])
|
|
79
109
|
with open(output_file, 'w') as f:
|
|
80
110
|
json.dump(
|
|
81
111
|
data,
|
|
@@ -106,34 +136,13 @@ def save_jsonl(
|
|
|
106
136
|
)
|
|
107
137
|
f.write('\n')
|
|
108
138
|
|
|
109
|
-
def search_column_value(
|
|
110
|
-
row: OrderedDict,
|
|
111
|
-
column: str,
|
|
112
|
-
):
|
|
113
|
-
if STAGING_FIELD in row:
|
|
114
|
-
value, found = get_field_value(row[STAGING_FIELD], column)
|
|
115
|
-
if found:
|
|
116
|
-
return value, True
|
|
117
|
-
value, found = get_field_value(row[STAGING_FIELD], column)
|
|
118
|
-
original, found = get_field_value(row, f'{STAGING_FIELD}.{INPUT_FIELD}')
|
|
119
|
-
if found:
|
|
120
|
-
value, found = get_field_value(original, column)
|
|
121
|
-
if found:
|
|
122
|
-
return value, True
|
|
123
|
-
value, found = get_field_value(row, column)
|
|
124
|
-
if found:
|
|
125
|
-
set_field_value(row, column, value)
|
|
126
|
-
return value, True
|
|
127
|
-
return None, False
|
|
128
|
-
|
|
129
139
|
def map_constants(
|
|
130
140
|
row: OrderedDict,
|
|
131
141
|
dict_constants: OrderedDict,
|
|
132
142
|
):
|
|
133
143
|
new_row = OrderedDict(row)
|
|
134
144
|
for column in dict_constants.keys():
|
|
135
|
-
|
|
136
|
-
set_field_value(new_row, f'{STAGING_FIELD}.{column}', dict_constants[column])
|
|
145
|
+
new_row[f'{STAGING_FIELD}.{column}'] = dict_constants[column]
|
|
137
146
|
return new_row
|
|
138
147
|
|
|
139
148
|
def map_formats(
|
|
@@ -144,7 +153,11 @@ def map_formats(
|
|
|
144
153
|
for column in dict_formats.keys():
|
|
145
154
|
template = dict_formats[column]
|
|
146
155
|
params = {}
|
|
147
|
-
|
|
156
|
+
for key, value in row.items():
|
|
157
|
+
prefix = f'{STAGING_FIELD}.'
|
|
158
|
+
if key.startswith(prefix):
|
|
159
|
+
rest = key[len(prefix):]
|
|
160
|
+
params[rest] = value
|
|
148
161
|
params.update(row)
|
|
149
162
|
formatted = None
|
|
150
163
|
while formatted is None:
|
|
@@ -158,7 +171,7 @@ def map_formats(
|
|
|
158
171
|
params[key] = f'__{key}__undefined__'
|
|
159
172
|
except:
|
|
160
173
|
raise
|
|
161
|
-
|
|
174
|
+
new_row[f'{STAGING_FIELD}.{column}'] = formatted
|
|
162
175
|
return new_row
|
|
163
176
|
|
|
164
177
|
def remap_columns(
|
|
@@ -169,11 +182,12 @@ def remap_columns(
|
|
|
169
182
|
for column in dict_remap.keys():
|
|
170
183
|
value, found = search_column_value(row, dict_remap[column])
|
|
171
184
|
if found:
|
|
172
|
-
|
|
185
|
+
new_row[column] = value
|
|
173
186
|
for column in row.keys():
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
187
|
+
prefix = f'{STAGING_FIELD}.'
|
|
188
|
+
if column.startswith(prefix):
|
|
189
|
+
# NOTE: Leave staging fields as is
|
|
190
|
+
new_row[column] = row[column]
|
|
177
191
|
return new_row
|
|
178
192
|
|
|
179
193
|
def apply_fields_split_by_newline(
|
|
@@ -183,13 +197,12 @@ def apply_fields_split_by_newline(
|
|
|
183
197
|
new_row = OrderedDict(row)
|
|
184
198
|
for column in dict_fields:
|
|
185
199
|
value, found = search_column_value(row, dict_fields[column])
|
|
186
|
-
#ic(value, found)
|
|
187
200
|
if found:
|
|
188
201
|
if isinstance(value, str):
|
|
189
202
|
new_value = value.split('\n')
|
|
190
|
-
|
|
203
|
+
new_row[f'{STAGING_FIELD}.{column}'] = new_value
|
|
191
204
|
else:
|
|
192
|
-
|
|
205
|
+
new_row[f'{STAGING_FIELD}.{column}'] = value
|
|
193
206
|
return new_row
|
|
194
207
|
|
|
195
208
|
def convert(
|
|
@@ -263,32 +276,35 @@ def convert(
|
|
|
263
276
|
# NOTE: NaN を None に変換しておかないと厄介
|
|
264
277
|
df = df.replace([np.nan], [None])
|
|
265
278
|
#ic(df)
|
|
266
|
-
ic(len(df))
|
|
267
|
-
ic(df.columns)
|
|
268
|
-
ic(df.iloc[0])
|
|
269
|
-
new_rows = []
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
279
|
+
#ic(len(df))
|
|
280
|
+
#ic(df.columns)
|
|
281
|
+
#ic(df.iloc[0])
|
|
282
|
+
#new_rows = []
|
|
283
|
+
new_flat_rows = []
|
|
284
|
+
for index, flat_row in df.iterrows():
|
|
285
|
+
orig = OrderedDict(flat_row)
|
|
286
|
+
new_flat_row = OrderedDict(flat_row)
|
|
287
|
+
new_nested_row = nest(new_flat_row)
|
|
288
|
+
if STAGING_FIELD not in new_nested_row:
|
|
289
|
+
new_flat_row[f'{STAGING_FIELD}.{FILE_FIELD}'] = input_file
|
|
290
|
+
for key, value in orig.items():
|
|
291
|
+
new_flat_row[f'{STAGING_FIELD}.{INPUT_FIELD}.{key}'] = value
|
|
276
292
|
if config.process.assign_constants:
|
|
277
|
-
|
|
293
|
+
new_flat_row = map_constants(new_flat_row, config.process.assign_constants)
|
|
278
294
|
if config.map:
|
|
279
|
-
|
|
295
|
+
new_flat_row = remap_columns(new_flat_row, config.map)
|
|
280
296
|
if config.process.split_by_newline:
|
|
281
|
-
|
|
297
|
+
new_flat_row = apply_fields_split_by_newline(new_flat_row, config.process.split_by_newline)
|
|
282
298
|
if config.process.assign_ids:
|
|
283
|
-
|
|
299
|
+
new_flat_row = assign_id(new_flat_row, config.process.assign_ids, id_context_map)
|
|
284
300
|
if config.process.assign_formats:
|
|
285
|
-
|
|
301
|
+
new_flat_row = map_formats(new_flat_row, config.process.assign_formats)
|
|
286
302
|
if config.map:
|
|
287
|
-
|
|
303
|
+
new_flat_row = remap_columns(new_flat_row, config.map)
|
|
288
304
|
if not output_debug:
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
new_df = pd.DataFrame(
|
|
305
|
+
new_flat_row.pop(STAGING_FIELD, None)
|
|
306
|
+
new_flat_rows.append(new_flat_row)
|
|
307
|
+
new_df = pd.DataFrame(new_flat_rows)
|
|
292
308
|
df_list.append(new_df)
|
|
293
309
|
all_df = pd.concat(df_list)
|
|
294
310
|
#ic(all_df)
|
|
@@ -16,7 +16,11 @@ import pandas as pd
|
|
|
16
16
|
|
|
17
17
|
# local
|
|
18
18
|
|
|
19
|
-
from ..
|
|
19
|
+
from .. constants import (
|
|
20
|
+
STAGING_FIELD,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
from .. config import (
|
|
20
24
|
AssignIdConfig,
|
|
21
25
|
Config,
|
|
22
26
|
)
|
|
@@ -87,7 +91,7 @@ def assign_id(
|
|
|
87
91
|
id_map.dict_id_to_value[field_id] = primary_value
|
|
88
92
|
else:
|
|
89
93
|
field_id = id_map.dict_value_to_id[primary_value]
|
|
90
|
-
|
|
94
|
+
new_row[f'{STAGING_FIELD}.{column}'] = field_id
|
|
91
95
|
return new_row
|
|
92
96
|
|
|
93
97
|
def setup_assign_ids(
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'''
|
|
2
|
+
This module contains the function to flatten a nested dictionary.
|
|
3
|
+
'''
|
|
4
|
+
|
|
5
|
+
from collections import OrderedDict
|
|
6
|
+
from typing import Mapping
|
|
7
|
+
|
|
8
|
+
type FlatFieldMap = Mapping[str]
|
|
9
|
+
type FieldMap = Mapping[str, str|FieldMap]
|
|
10
|
+
|
|
11
|
+
def flatten(
|
|
12
|
+
mapping: FieldMap,
|
|
13
|
+
parent_key: str = '',
|
|
14
|
+
new_mapping: FlatFieldMap | None = None,
|
|
15
|
+
) -> FlatFieldMap:
|
|
16
|
+
if new_mapping is None:
|
|
17
|
+
new_mapping = OrderedDict()
|
|
18
|
+
for key, mapped in mapping.items():
|
|
19
|
+
new_key = f'{parent_key}.{key}' if parent_key else key
|
|
20
|
+
if isinstance(mapped, Mapping):
|
|
21
|
+
flatten(mapped, new_key, new_mapping)
|
|
22
|
+
else:
|
|
23
|
+
new_mapping[new_key] = mapped
|
|
24
|
+
return new_mapping
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'''
|
|
2
|
+
This function is used to search for a column value in a row. It will first search in the '__debug__' field, then in the '__debug__.__original__' field, and finally in the row itself. If the value is found, it will be set in the row and returned.
|
|
3
|
+
'''
|
|
4
|
+
|
|
5
|
+
from .. constants import (
|
|
6
|
+
INPUT_FIELD,
|
|
7
|
+
STAGING_FIELD,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from collections import OrderedDict
|
|
11
|
+
|
|
12
|
+
def search_column_value(
|
|
13
|
+
row: OrderedDict,
|
|
14
|
+
column: str,
|
|
15
|
+
):
|
|
16
|
+
if f'{STAGING_FIELD}.{column}' in row:
|
|
17
|
+
value = row[f'{STAGING_FIELD}.{column}']
|
|
18
|
+
return value, True
|
|
19
|
+
if f'{STAGING_FIELD}.{INPUT_FIELD}.{column}' in row:
|
|
20
|
+
value = row[f'{STAGING_FIELD}.{INPUT_FIELD}.{column}']
|
|
21
|
+
return value, True
|
|
22
|
+
if column in row:
|
|
23
|
+
value = row[column]
|
|
24
|
+
return value, True
|
|
25
|
+
return None, False
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
'''
|
|
2
|
-
This function is used to search for a column value in a row. It will first search in the '__debug__' field, then in the '__debug__.__original__' field, and finally in the row itself. If the value is found, it will be set in the row and returned.
|
|
3
|
-
'''
|
|
4
|
-
|
|
5
|
-
from .. constants import STAGING_FIELD
|
|
6
|
-
|
|
7
|
-
from collections import OrderedDict
|
|
8
|
-
|
|
9
|
-
from . get_field_value import get_field_value
|
|
10
|
-
from . set_field_value import set_field_value
|
|
11
|
-
|
|
12
|
-
def search_column_value(
|
|
13
|
-
row: OrderedDict,
|
|
14
|
-
column: str,
|
|
15
|
-
):
|
|
16
|
-
if STAGING_FIELD in row:
|
|
17
|
-
value, found = get_field_value(row[STAGING_FIELD], column)
|
|
18
|
-
if found:
|
|
19
|
-
return value, True
|
|
20
|
-
value, found = get_field_value(row[STAGING_FIELD], column)
|
|
21
|
-
original, found = get_field_value(row, f'{STAGING_FIELD}.__original__')
|
|
22
|
-
if found:
|
|
23
|
-
value, found = get_field_value(original, column)
|
|
24
|
-
if found:
|
|
25
|
-
return value, True
|
|
26
|
-
value, found = get_field_value(row, column)
|
|
27
|
-
if found:
|
|
28
|
-
set_field_value(row, column, value)
|
|
29
|
-
return value, True
|
|
30
|
-
return None, False
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_table_converter-0.2.8 → python_table_converter-0.2.9}/table_converter/core/constants.py
RENAMED
|
File without changes
|
|
File without changes
|