python-table-processor 0.2.29__tar.gz → 0.3.0__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_processor-0.2.29 → python_table_processor-0.3.0}/PKG-INFO +1 -1
- {python_table_processor-0.2.29 → python_table_processor-0.3.0}/pyproject.toml +1 -1
- python_table_processor-0.3.0/table_processor/__init__.py +2 -0
- {python_table_processor-0.2.29 → python_table_processor-0.3.0}/table_processor/cli.py +22 -1
- python_table_processor-0.3.0/table_processor/commands/merge_tables.py +58 -0
- {python_table_processor-0.2.29 → python_table_processor-0.3.0}/table_processor/core/actions.py +4 -1
- {python_table_processor-0.2.29 → python_table_processor-0.3.0}/table_processor/core/convert.py +19 -0
- python_table_processor-0.3.0/table_processor/core/functions/assign_id.py +153 -0
- {python_table_processor-0.2.29 → python_table_processor-0.3.0}/table_processor/core/functions/get_nested_field_value.py +3 -0
- python_table_processor-0.3.0/table_processor/core/merge.py +145 -0
- {python_table_processor-0.2.29 → python_table_processor-0.3.0}/table_processor/core/types.py +1 -0
- python_table_processor-0.2.29/table_processor/__init__.py +0 -2
- python_table_processor-0.2.29/table_processor/core/functions/assign_id.py +0 -75
- {python_table_processor-0.2.29 → python_table_processor-0.3.0}/LICENSE +0 -0
- {python_table_processor-0.2.29 → python_table_processor-0.3.0}/README.md +0 -0
- {python_table_processor-0.2.29 → python_table_processor-0.3.0}/table_processor/commands/convert_tables.py +0 -0
- {python_table_processor-0.2.29 → python_table_processor-0.3.0}/table_processor/core/config.py +0 -0
- {python_table_processor-0.2.29 → python_table_processor-0.3.0}/table_processor/core/constants.py +0 -0
- {python_table_processor-0.2.29 → python_table_processor-0.3.0}/table_processor/core/functions/flatten_row.py +0 -0
- {python_table_processor-0.2.29 → python_table_processor-0.3.0}/table_processor/core/functions/nest_row.py +0 -0
- {python_table_processor-0.2.29 → python_table_processor-0.3.0}/table_processor/core/functions/search_column_value.py +0 -0
- {python_table_processor-0.2.29 → python_table_processor-0.3.0}/table_processor/core/functions/set_flat_field_value.py +0 -0
- {python_table_processor-0.2.29 → python_table_processor-0.3.0}/table_processor/core/functions/set_nested_field_value.py +0 -0
- {python_table_processor-0.2.29 → python_table_processor-0.3.0}/table_processor/core/functions/set_row_value.py +0 -0
|
@@ -34,7 +34,21 @@ def command_convert_tables(
|
|
|
34
34
|
)
|
|
35
35
|
else:
|
|
36
36
|
command_parser = parser
|
|
37
|
-
from
|
|
37
|
+
from table_processor.commands.convert_tables import setup_parser
|
|
38
|
+
setup_parser(command_parser)
|
|
39
|
+
if parser is None:
|
|
40
|
+
parse_and_run(command_parser)
|
|
41
|
+
|
|
42
|
+
def command_merge_tables(
|
|
43
|
+
parser: argparse.ArgumentParser|None = None,
|
|
44
|
+
):
|
|
45
|
+
if parser is None:
|
|
46
|
+
command_parser = argparse.ArgumentParser(
|
|
47
|
+
description='Merge tables.'
|
|
48
|
+
)
|
|
49
|
+
else:
|
|
50
|
+
command_parser = parser
|
|
51
|
+
from table_processor.commands.merge_tables import setup_parser
|
|
38
52
|
setup_parser(command_parser)
|
|
39
53
|
if parser is None:
|
|
40
54
|
parse_and_run(command_parser)
|
|
@@ -60,6 +74,13 @@ def main():
|
|
|
60
74
|
setup_common_args(parser_convert_tables)
|
|
61
75
|
command_convert_tables(parser_convert_tables)
|
|
62
76
|
|
|
77
|
+
parser_merge_tables = subparsers.add_parser(
|
|
78
|
+
'merge',
|
|
79
|
+
help='Merge tables.'
|
|
80
|
+
)
|
|
81
|
+
setup_common_args(parser_merge_tables)
|
|
82
|
+
command_merge_tables(parser_merge_tables)
|
|
83
|
+
|
|
63
84
|
parse_and_run(parser)
|
|
64
85
|
|
|
65
86
|
if __name__ == '__main__':
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
|
|
5
|
+
from icecream import ic
|
|
6
|
+
|
|
7
|
+
from .. core.merge import merge
|
|
8
|
+
|
|
9
|
+
def run(
|
|
10
|
+
args: argparse.Namespace,
|
|
11
|
+
):
|
|
12
|
+
merge(
|
|
13
|
+
previous_files=args.previous_files,
|
|
14
|
+
modification_files=args.modification_files,
|
|
15
|
+
keys=args.keys,
|
|
16
|
+
allow_duplicate_keys=args.allow_duplicate_keys,
|
|
17
|
+
ignore_not_found=args.ignore_not_found,
|
|
18
|
+
output_file=args.output_file,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
def setup_parser(
|
|
22
|
+
parser: argparse.ArgumentParser,
|
|
23
|
+
):
|
|
24
|
+
parser.add_argument(
|
|
25
|
+
'--previous-files', '--previous-file', '--previous', '--old', '-P',
|
|
26
|
+
nargs='+',
|
|
27
|
+
required=True,
|
|
28
|
+
help='Previous files to merge',
|
|
29
|
+
)
|
|
30
|
+
parser.add_argument(
|
|
31
|
+
'--modification-files', '--modification', '--modify', '--modified', '--new', '-M',
|
|
32
|
+
nargs='+',
|
|
33
|
+
required=True,
|
|
34
|
+
help='Modification files to merge',
|
|
35
|
+
)
|
|
36
|
+
parser.add_argument(
|
|
37
|
+
'--keys', '-K',
|
|
38
|
+
nargs='+',
|
|
39
|
+
required=True,
|
|
40
|
+
help='Primary keys',
|
|
41
|
+
)
|
|
42
|
+
parser.add_argument(
|
|
43
|
+
'--allow-duplicate-keys', '--allow-duplicate',
|
|
44
|
+
action='store_true',
|
|
45
|
+
help='Allow duplicate keys',
|
|
46
|
+
)
|
|
47
|
+
parser.add_argument(
|
|
48
|
+
'--ignore-not-found',
|
|
49
|
+
action='store_true',
|
|
50
|
+
help='Ignore not found',
|
|
51
|
+
)
|
|
52
|
+
parser.add_argument(
|
|
53
|
+
'--output-file', '--output', '-o',
|
|
54
|
+
metavar='OUTPUT_FILE',
|
|
55
|
+
required=False,
|
|
56
|
+
help='Path to the output file.',
|
|
57
|
+
)
|
|
58
|
+
parser.set_defaults(handler=run)
|
{python_table_processor-0.2.29 → python_table_processor-0.3.0}/table_processor/core/actions.py
RENAMED
|
@@ -131,10 +131,12 @@ def setup_actions_with_args(
|
|
|
131
131
|
context = options.get('context', None)
|
|
132
132
|
if context:
|
|
133
133
|
context = context.split(',')
|
|
134
|
+
reverse = options.get('reverse', False)
|
|
134
135
|
config.actions.append(AssignIdConfig(
|
|
135
136
|
target = target,
|
|
136
137
|
primary = [source],
|
|
137
138
|
context = context,
|
|
139
|
+
reverse = reverse,
|
|
138
140
|
))
|
|
139
141
|
continue
|
|
140
142
|
if action_name == 'filter-empty':
|
|
@@ -488,7 +490,8 @@ def assign_format(
|
|
|
488
490
|
params[key] = f'__{key}__undefined__'
|
|
489
491
|
except:
|
|
490
492
|
#ic(params)
|
|
491
|
-
ic(params.keys())
|
|
493
|
+
#ic(params.keys())
|
|
494
|
+
ic(row.flat)
|
|
492
495
|
raise
|
|
493
496
|
set_row_staging_value(row, config.target, formatted)
|
|
494
497
|
return row
|
{python_table_processor-0.2.29 → python_table_processor-0.3.0}/table_processor/core/convert.py
RENAMED
|
@@ -63,6 +63,15 @@ def register_loader(
|
|
|
63
63
|
return loader
|
|
64
64
|
return decorator
|
|
65
65
|
|
|
66
|
+
def load(
|
|
67
|
+
input_file: str,
|
|
68
|
+
):
|
|
69
|
+
ext = os.path.splitext(input_file)[1]
|
|
70
|
+
if ext not in dict_loaders:
|
|
71
|
+
raise ValueError(f'Unsupported file type: {ext}')
|
|
72
|
+
loader = dict_loaders[ext]
|
|
73
|
+
return loader(input_file)
|
|
74
|
+
|
|
66
75
|
dict_savers: dict[str, callable] = {}
|
|
67
76
|
def register_saver(
|
|
68
77
|
ext: str,
|
|
@@ -72,6 +81,16 @@ def register_saver(
|
|
|
72
81
|
return saver
|
|
73
82
|
return decorator
|
|
74
83
|
|
|
84
|
+
def save(
|
|
85
|
+
df: pd.DataFrame,
|
|
86
|
+
output_file: str,
|
|
87
|
+
):
|
|
88
|
+
ext = os.path.splitext(output_file)[1]
|
|
89
|
+
if ext not in dict_savers:
|
|
90
|
+
raise ValueError(f'Unsupported file type: {ext}')
|
|
91
|
+
saver = dict_savers[ext]
|
|
92
|
+
saver(df, output_file)
|
|
93
|
+
|
|
75
94
|
@register_loader('.csv')
|
|
76
95
|
def load_csv(
|
|
77
96
|
input_file: str,
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
import dataclasses
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
from collections import OrderedDict
|
|
8
|
+
from collections import defaultdict
|
|
9
|
+
from typing import Mapping
|
|
10
|
+
|
|
11
|
+
# 3-rd party modules
|
|
12
|
+
|
|
13
|
+
from icecream import ic
|
|
14
|
+
import numpy as np
|
|
15
|
+
import pandas as pd
|
|
16
|
+
|
|
17
|
+
# local
|
|
18
|
+
|
|
19
|
+
from .. constants import (
|
|
20
|
+
STAGING_FIELD,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
from .. config import (
|
|
24
|
+
AssignIdConfig,
|
|
25
|
+
Config,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
from . search_column_value import search_column_value
|
|
29
|
+
from . set_nested_field_value import set_nested_field_value
|
|
30
|
+
from . set_row_value import set_row_staging_value
|
|
31
|
+
|
|
32
|
+
from .. types import (
|
|
33
|
+
AssignIdConfig,
|
|
34
|
+
IdContextMap,
|
|
35
|
+
Row,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
def get_key_value(
|
|
39
|
+
row: Row,
|
|
40
|
+
primary: list[str],
|
|
41
|
+
context: list[str],
|
|
42
|
+
):
|
|
43
|
+
if not primary:
|
|
44
|
+
raise ValueError('Primary columns must be specified')
|
|
45
|
+
context_columns = []
|
|
46
|
+
context_values = []
|
|
47
|
+
if context:
|
|
48
|
+
for context_column in context:
|
|
49
|
+
value, found = search_column_value(row.nested, context_column)
|
|
50
|
+
if not found:
|
|
51
|
+
raise KeyError(f'Column not found: {context_column}, existing columns: {row.flat.keys()}')
|
|
52
|
+
context_columns.append(context_column)
|
|
53
|
+
context_values.append(value)
|
|
54
|
+
primary_columns = []
|
|
55
|
+
primary_values = []
|
|
56
|
+
for primary_column in primary:
|
|
57
|
+
value, found = search_column_value(row.nested, primary_column)
|
|
58
|
+
if not found:
|
|
59
|
+
raise KeyError(f'Column not found: {primary_column}, existing columns: {row.flat.keys()}')
|
|
60
|
+
primary_columns.append(primary_column)
|
|
61
|
+
primary_values.append(value)
|
|
62
|
+
context_key = (
|
|
63
|
+
tuple(context_columns),
|
|
64
|
+
tuple(context_values),
|
|
65
|
+
tuple(primary_columns),
|
|
66
|
+
)
|
|
67
|
+
primary_value = tuple(primary_values)
|
|
68
|
+
return context_key, primary_value
|
|
69
|
+
|
|
70
|
+
def get_id(
|
|
71
|
+
id_context_map: IdContextMap,
|
|
72
|
+
row: Row,
|
|
73
|
+
primary: list[str],
|
|
74
|
+
context: list[str],
|
|
75
|
+
):
|
|
76
|
+
context_key, primary_value = get_key_value(
|
|
77
|
+
row=row,
|
|
78
|
+
primary=primary,
|
|
79
|
+
context=context,
|
|
80
|
+
)
|
|
81
|
+
id_map = id_context_map[context_key]
|
|
82
|
+
#ic(primary_value, context_key)
|
|
83
|
+
#ic(primary_value in id_map.dict_value_to_id)
|
|
84
|
+
if primary_value not in id_map.dict_value_to_id:
|
|
85
|
+
field_id = id_map.max_id + 1
|
|
86
|
+
id_map.max_id = field_id
|
|
87
|
+
id_map.dict_value_to_id[primary_value] = field_id
|
|
88
|
+
id_map.dict_id_to_value[field_id] = primary_value
|
|
89
|
+
id_exists = False
|
|
90
|
+
else:
|
|
91
|
+
field_id = id_map.dict_value_to_id[primary_value]
|
|
92
|
+
id_exists = True
|
|
93
|
+
return field_id, id_exists
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def set_id(
|
|
97
|
+
id_context_map: IdContextMap,
|
|
98
|
+
row: Row,
|
|
99
|
+
primary: list[str],
|
|
100
|
+
context: list[str],
|
|
101
|
+
id_value: int,
|
|
102
|
+
):
|
|
103
|
+
context_key, primary_value = get_key_value(
|
|
104
|
+
row=row,
|
|
105
|
+
primary=primary,
|
|
106
|
+
context=context,
|
|
107
|
+
)
|
|
108
|
+
id_map = id_context_map[context_key]
|
|
109
|
+
if id_value in id_map.dict_id_to_value:
|
|
110
|
+
#raise ValueError(f'ID already exists: {id_value}')
|
|
111
|
+
field_id = id_map.dict_id_to_value[id_value]
|
|
112
|
+
if field_id != primary_value:
|
|
113
|
+
raise ValueError(f'ID already exists: {id_value} for {field_id}')
|
|
114
|
+
id_map.dict_value_to_id[primary_value] = id_value
|
|
115
|
+
id_map.dict_id_to_value[id_value] = primary_value
|
|
116
|
+
id_map.max_id = max(id_map.max_id, id_value)
|
|
117
|
+
return
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def assign_id(
|
|
121
|
+
id_context_map: IdContextMap,
|
|
122
|
+
row: Row,
|
|
123
|
+
config: Config,
|
|
124
|
+
):
|
|
125
|
+
if config.reverse:
|
|
126
|
+
#ic(row)
|
|
127
|
+
#ic(type(row))
|
|
128
|
+
#ic(config)
|
|
129
|
+
value, found = search_column_value(row.nested, config.target)
|
|
130
|
+
#ic(row, value, found)
|
|
131
|
+
if type(value) is str:
|
|
132
|
+
if value.isdigit():
|
|
133
|
+
value = int(value)
|
|
134
|
+
if type(value) is int:
|
|
135
|
+
field_id = value
|
|
136
|
+
set_id(
|
|
137
|
+
id_context_map=id_context_map,
|
|
138
|
+
row=row,
|
|
139
|
+
primary=config.primary,
|
|
140
|
+
context=config.context,
|
|
141
|
+
id_value=field_id,
|
|
142
|
+
)
|
|
143
|
+
#return field_id, True
|
|
144
|
+
return row
|
|
145
|
+
field_id, id_exists = get_id(
|
|
146
|
+
id_context_map=id_context_map,
|
|
147
|
+
row=row,
|
|
148
|
+
primary=config.primary,
|
|
149
|
+
context=config.context,
|
|
150
|
+
)
|
|
151
|
+
#ic(config, field_id, id_exists)
|
|
152
|
+
set_row_staging_value(row, config.target, field_id)
|
|
153
|
+
return row
|
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
from collections import OrderedDict
|
|
4
4
|
|
|
5
|
+
from icecream import ic
|
|
6
|
+
|
|
5
7
|
def get_nested_field_value(
|
|
6
8
|
data: OrderedDict | list,
|
|
7
9
|
field: str,
|
|
8
10
|
):
|
|
9
11
|
if isinstance(data, list):
|
|
12
|
+
#ic(data, field)
|
|
10
13
|
if field.isdigit():
|
|
11
14
|
index = int(field)
|
|
12
15
|
if index < len(data):
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import math
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
from collections import OrderedDict
|
|
8
|
+
|
|
9
|
+
from typing import (
|
|
10
|
+
Mapping,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
# 3-rd party modules
|
|
14
|
+
|
|
15
|
+
from icecream import ic
|
|
16
|
+
import numpy as np
|
|
17
|
+
import pandas as pd
|
|
18
|
+
from tqdm.auto import tqdm
|
|
19
|
+
|
|
20
|
+
# local
|
|
21
|
+
|
|
22
|
+
from . functions.flatten_row import flatten_row
|
|
23
|
+
from . functions.get_nested_field_value import get_nested_field_value
|
|
24
|
+
from . functions.get_nested_field_value import get_nested_field_value
|
|
25
|
+
from . functions.nest_row import nest_row as nest
|
|
26
|
+
from . functions.search_column_value import search_column_value
|
|
27
|
+
from . functions.set_nested_field_value import set_nested_field_value
|
|
28
|
+
from . functions.set_row_value import (
|
|
29
|
+
set_row_value,
|
|
30
|
+
set_row_staging_value,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
from . actions import (
|
|
34
|
+
prepare_row,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
from . convert import (
|
|
38
|
+
load,
|
|
39
|
+
save,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
def merge(
|
|
43
|
+
previous_files: list[str],
|
|
44
|
+
modification_files: list[str],
|
|
45
|
+
keys: list[str],
|
|
46
|
+
allow_duplicate_keys: bool = False,
|
|
47
|
+
ignore_not_found: bool = False,
|
|
48
|
+
output_file: str | None = None,
|
|
49
|
+
):
|
|
50
|
+
ic.enable()
|
|
51
|
+
ic()
|
|
52
|
+
ic(previous_files)
|
|
53
|
+
ic(modification_files)
|
|
54
|
+
ic(keys)
|
|
55
|
+
dict_key_to_row = {}
|
|
56
|
+
all_rows = []
|
|
57
|
+
list_ignored_keys = []
|
|
58
|
+
num_modified = 0
|
|
59
|
+
for previous_file in previous_files:
|
|
60
|
+
if not os.path.exists(previous_file):
|
|
61
|
+
raise FileNotFoundError(f'File not found: {previous_file}')
|
|
62
|
+
df = load(previous_file)
|
|
63
|
+
# NOTE: NaN を None に変換しておかないと厄介
|
|
64
|
+
df = df.replace([np.nan], [None])
|
|
65
|
+
#ic(df)
|
|
66
|
+
ic(len(df))
|
|
67
|
+
#ic(df.columns)
|
|
68
|
+
#ic(df.iloc[0])
|
|
69
|
+
for index, flat_row in tqdm(
|
|
70
|
+
df.iterrows(),
|
|
71
|
+
desc=f'Loading: {previous_file}',
|
|
72
|
+
total=len(df),
|
|
73
|
+
):
|
|
74
|
+
row = prepare_row(flat_row)
|
|
75
|
+
list_keys = []
|
|
76
|
+
for key in keys:
|
|
77
|
+
value, found = search_column_value(row.nested, key)
|
|
78
|
+
if not found:
|
|
79
|
+
raise KeyError(f'Column not found: {key}, existing columns: {row.flat.keys()}')
|
|
80
|
+
list_keys.append(value)
|
|
81
|
+
primary_key = tuple(list_keys)
|
|
82
|
+
#ic(key)
|
|
83
|
+
if not allow_duplicate_keys:
|
|
84
|
+
if primary_key in dict_key_to_row:
|
|
85
|
+
ic(index)
|
|
86
|
+
raise ValueError(f'Duplicate key: {key}')
|
|
87
|
+
dict_key_to_row[primary_key] = row
|
|
88
|
+
all_rows.append(row)
|
|
89
|
+
for modification_file in modification_files:
|
|
90
|
+
if not os.path.exists(modification_file):
|
|
91
|
+
raise FileNotFoundError(f'File not found: {modification_file}')
|
|
92
|
+
df = load(modification_file)
|
|
93
|
+
# NOTE: NaN を None に変換しておかないと厄介
|
|
94
|
+
df = df.replace([np.nan], [None])
|
|
95
|
+
#ic(df)
|
|
96
|
+
ic(len(df))
|
|
97
|
+
#ic(df.columns)
|
|
98
|
+
#ic(df.iloc[0])
|
|
99
|
+
for index, flat_row in tqdm(
|
|
100
|
+
df.iterrows(),
|
|
101
|
+
desc=f'Processing: {modification_file}',
|
|
102
|
+
total=len(df),
|
|
103
|
+
):
|
|
104
|
+
row = prepare_row(flat_row)
|
|
105
|
+
list_keys = []
|
|
106
|
+
for key in keys:
|
|
107
|
+
value, found = search_column_value(row.nested, key)
|
|
108
|
+
if not found:
|
|
109
|
+
raise KeyError(f'Column not found: {key}, existing columns: {row.flat.keys()}')
|
|
110
|
+
list_keys.append(value)
|
|
111
|
+
primary_key = tuple(list_keys)
|
|
112
|
+
#ic(key)
|
|
113
|
+
#if key not in dict_key_to_row:
|
|
114
|
+
# dict_key_to_row[key] = row
|
|
115
|
+
#else:
|
|
116
|
+
# dict_key_to_row[key].flat.update(row.flat)
|
|
117
|
+
if primary_key not in dict_key_to_row:
|
|
118
|
+
if ignore_not_found:
|
|
119
|
+
list_ignored_keys.append(primary_key)
|
|
120
|
+
continue
|
|
121
|
+
ic(index)
|
|
122
|
+
raise ValueError(f'Key not found: {key}')
|
|
123
|
+
previous_row = dict_key_to_row[primary_key]
|
|
124
|
+
#ic(previous_row)
|
|
125
|
+
#ic(previous_row.flat)
|
|
126
|
+
for key, value in row.flat.items():
|
|
127
|
+
if key.startswith('__staging__.'):
|
|
128
|
+
continue
|
|
129
|
+
ic(key, value)
|
|
130
|
+
set_row_value(previous_row, key, value)
|
|
131
|
+
#set_row_value(previous_row, '指示追従性?', 'test')
|
|
132
|
+
#set_row_value(previous_row, 'modified', True)
|
|
133
|
+
#ic(previous_row)
|
|
134
|
+
#ic(previous_row.flat)
|
|
135
|
+
#raise
|
|
136
|
+
num_modified += 1
|
|
137
|
+
ic(num_modified)
|
|
138
|
+
if ignore_not_found:
|
|
139
|
+
ic(len(list_ignored_keys))
|
|
140
|
+
ic(list_ignored_keys)
|
|
141
|
+
if output_file:
|
|
142
|
+
#all_df = pd.DataFrame(all_rows)
|
|
143
|
+
all_df = pd.DataFrame([row.flat for row in all_rows])
|
|
144
|
+
ic('Saving to: ', output_file)
|
|
145
|
+
save(all_df, output_file)
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
|
|
3
|
-
import dataclasses
|
|
4
|
-
import json
|
|
5
|
-
import os
|
|
6
|
-
|
|
7
|
-
from collections import OrderedDict
|
|
8
|
-
from collections import defaultdict
|
|
9
|
-
from typing import Mapping
|
|
10
|
-
|
|
11
|
-
# 3-rd party modules
|
|
12
|
-
|
|
13
|
-
from icecream import ic
|
|
14
|
-
import numpy as np
|
|
15
|
-
import pandas as pd
|
|
16
|
-
|
|
17
|
-
# local
|
|
18
|
-
|
|
19
|
-
from .. constants import (
|
|
20
|
-
STAGING_FIELD,
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
from .. config import (
|
|
24
|
-
AssignIdConfig,
|
|
25
|
-
Config,
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
from . search_column_value import search_column_value
|
|
29
|
-
from . set_nested_field_value import set_nested_field_value
|
|
30
|
-
from . set_row_value import set_row_staging_value
|
|
31
|
-
|
|
32
|
-
from .. types import (
|
|
33
|
-
AssignIdConfig,
|
|
34
|
-
IdContextMap,
|
|
35
|
-
Row,
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
def assign_id(
|
|
39
|
-
id_context_map: IdContextMap,
|
|
40
|
-
row: Row,
|
|
41
|
-
config: Config,
|
|
42
|
-
):
|
|
43
|
-
context_columns = []
|
|
44
|
-
context_values = []
|
|
45
|
-
if config.context:
|
|
46
|
-
for context_column in config.context:
|
|
47
|
-
value, found = search_column_value(row.nested, context_column)
|
|
48
|
-
if not found:
|
|
49
|
-
raise KeyError(f'Column not found: {context_column}, existing columns: {row.flat.keys()}')
|
|
50
|
-
context_columns.append(context_column)
|
|
51
|
-
context_values.append(value)
|
|
52
|
-
primary_columns = []
|
|
53
|
-
primary_values = []
|
|
54
|
-
for primary_column in config.primary:
|
|
55
|
-
value, found = search_column_value(row.nested, primary_column)
|
|
56
|
-
if not found:
|
|
57
|
-
raise KeyError(f'Column not found: {primary_column}, existing columns: {row.flat.keys()}')
|
|
58
|
-
primary_columns.append(primary_column)
|
|
59
|
-
primary_values.append(value)
|
|
60
|
-
context_key = (
|
|
61
|
-
tuple(context_columns),
|
|
62
|
-
tuple(context_values),
|
|
63
|
-
tuple(primary_columns),
|
|
64
|
-
)
|
|
65
|
-
primary_value = tuple(primary_values)
|
|
66
|
-
id_map = id_context_map[context_key]
|
|
67
|
-
if primary_value not in id_map.dict_value_to_id:
|
|
68
|
-
field_id = id_map.max_id + 1
|
|
69
|
-
id_map.max_id = field_id
|
|
70
|
-
id_map.dict_value_to_id[primary_value] = field_id
|
|
71
|
-
id_map.dict_id_to_value[field_id] = primary_value
|
|
72
|
-
else:
|
|
73
|
-
field_id = id_map.dict_value_to_id[primary_value]
|
|
74
|
-
set_row_staging_value(row, config.target, field_id)
|
|
75
|
-
return row
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_table_processor-0.2.29 → python_table_processor-0.3.0}/table_processor/core/config.py
RENAMED
|
File without changes
|
{python_table_processor-0.2.29 → python_table_processor-0.3.0}/table_processor/core/constants.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|