python-table-processor 0.2.29__py3-none-any.whl → 0.3.1__py3-none-any.whl

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-table-processor
3
- Version: 0.2.29
3
+ Version: 0.3.1
4
4
  Summary: A table data processor
5
5
  Home-page: https://github.com/akivajp/python-table-processor
6
6
  License: MIT
@@ -0,0 +1,23 @@
1
+ table_processor/__init__.py,sha256=7U6Yq5pgarhomICnrlEYAI32ycMhvYb4mYoUd4axAyU,52
2
+ table_processor/cli.py,sha256=uluf_VsBzq3Ldxh3ePGseSrv8--lI7huu-6RjDaHPPg,2170
3
+ table_processor/commands/convert_tables.py,sha256=j25KL0zRl5ikrBk73jAkKn4rPmDq7SecChZxecDpILQ,2123
4
+ table_processor/commands/merge_tables.py,sha256=Uu-hjfPh69Of0_OZrY8sY0oscpLSdK4jwJ_t1qgfPMg,1485
5
+ table_processor/core/actions.py,sha256=rXdXXo8AXUaLnrzDp8vRduU0XxIOD7PQdkjHiJzOzq8,19702
6
+ table_processor/core/config.py,sha256=irJxJBhBQNz5cp9XlMjVpZ47hxclG6pkTphK-SCrZQ0,11727
7
+ table_processor/core/constants.py,sha256=w-1TxtpXywb6Qh8M4YWuzcCHUvCjy5zJYxaXC3RQS6A,158
8
+ table_processor/core/convert.py,sha256=2R9zf0SzRZEpNEd51eym10mJ3kb5vLSnsY81z4dDXCA,11566
9
+ table_processor/core/functions/assign_id.py,sha256=dA-wgZA7E01gbx8qGvo1PeMd3aq9PhMdyITzr3BKXIE,4204
10
+ table_processor/core/functions/flatten_row.py,sha256=2l-s4YXgBM58IthpfVzd7L4EGUCekSi7ss5CaM_3MUU,686
11
+ table_processor/core/functions/get_nested_field_value.py,sha256=vF4pH6nxR3-2bDfAvrMfHcPFNiS4MnGkXL8FdcScdIw,685
12
+ table_processor/core/functions/nest_row.py,sha256=b5AKfxE39g-NOLranQRy0dfTZq-27Or8ZlgCB8N5kFs,640
13
+ table_processor/core/functions/search_column_value.py,sha256=GscwLaMTORHFDhdCdjzdoy46UGyFHrGwDQA2b_tZhsQ,740
14
+ table_processor/core/functions/set_flat_field_value.py,sha256=7-BgD2yEUGyBaFaIJ18bYv82Qdy0CN8NiC5ZtsAdv44,531
15
+ table_processor/core/functions/set_nested_field_value.py,sha256=csO0v_nW94q-M9bNL91xR-TLHPXDDxnLK8gN-0LLd6k,595
16
+ table_processor/core/functions/set_row_value.py,sha256=wlF_nVGZY74XCzd6pBJJyti62m6y0s1kc5Q6uq9jn8o,641
17
+ table_processor/core/merge.py,sha256=Yc5OV9n1xV9QtgY4srl6Susd5cOKbuYseEtYuBampDw,4672
18
+ table_processor/core/types.py,sha256=vqm7Jyktrcd3qvfJspu8421MwsXI-jxnCeXAbmpTDHw,2498
19
+ python_table_processor-0.3.1.dist-info/LICENSE,sha256=1_Gn0I1neLPxDLfLiHEyxjDg-pbAra1p2iHEqutGS_c,1068
20
+ python_table_processor-0.3.1.dist-info/METADATA,sha256=nAAAO4VF74FJv3Qd-Jd1lNRTQVvEOKDcZWu-13C04_g,1098
21
+ python_table_processor-0.3.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
22
+ python_table_processor-0.3.1.dist-info/entry_points.txt,sha256=lq97F6m51yZ93qmVIqkUHJfbILZuYLxrMWXSqrP4JpM,118
23
+ python_table_processor-0.3.1.dist-info/RECORD,,
@@ -1,2 +1,2 @@
1
- __version__ = "0.2.29"
2
- __version_tuple__ = (0, 2, 29)
1
+ __version__ = "0.3.1"
2
+ __version_tuple__ = (0, 3, 1)
table_processor/cli.py CHANGED
@@ -34,7 +34,21 @@ def command_convert_tables(
34
34
  )
35
35
  else:
36
36
  command_parser = parser
37
- from table_converter.commands.convert_tables import setup_parser
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)
@@ -34,6 +34,7 @@ from . types import (
34
34
  OmitConfig,
35
35
  ParseConfig,
36
36
  PickConfig,
37
+ PushConfig,
37
38
  SplitConfig,
38
39
  Row,
39
40
  )
@@ -131,10 +132,12 @@ def setup_actions_with_args(
131
132
  context = options.get('context', None)
132
133
  if context:
133
134
  context = context.split(',')
135
+ reverse = options.get('reverse', False)
134
136
  config.actions.append(AssignIdConfig(
135
137
  target = target,
136
138
  primary = [source],
137
139
  context = context,
140
+ reverse = reverse,
138
141
  ))
139
142
  continue
140
143
  if action_name == 'filter-empty':
@@ -187,6 +190,14 @@ def setup_actions_with_args(
187
190
  required = required,
188
191
  ))
189
192
  continue
193
+ if action_name == 'push':
194
+ condition = options.get('condition', None)
195
+ config.actions.append(PushConfig(
196
+ target = target,
197
+ source = source,
198
+ condition = condition,
199
+ ))
200
+ continue
190
201
  if action_name == 'split':
191
202
  delimiter = options.get('delimiter', None)
192
203
  if delimiter == '\\n':
@@ -302,6 +313,8 @@ def do_action(
302
313
  return parse(row, action)
303
314
  if isinstance(action, OmitConfig):
304
315
  return omit_field(row, action)
316
+ if isinstance(action, PushConfig):
317
+ return push_field(row, action)
305
318
  if isinstance(action, SplitConfig):
306
319
  return split_field(row, action)
307
320
  raise ValueError(
@@ -488,7 +501,8 @@ def assign_format(
488
501
  params[key] = f'__{key}__undefined__'
489
502
  except:
490
503
  #ic(params)
491
- ic(params.keys())
504
+ #ic(params.keys())
505
+ ic(row.flat)
492
506
  raise
493
507
  set_row_staging_value(row, config.target, formatted)
494
508
  return row
@@ -599,3 +613,25 @@ def parse(
599
613
  parsed = value
600
614
  set_row_staging_value(row, config.target, parsed)
601
615
  return row
616
+
617
+ def push_field(
618
+ row: Row,
619
+ config: PushConfig,
620
+ ):
621
+ source_value, found = search_column_value(row.nested, config.source)
622
+ do_append = False
623
+ if config.condition is None:
624
+ do_append = True
625
+ else:
626
+ condition_value, found = search_column_value(row.nested, config.condition)
627
+ if condition_value:
628
+ do_append = True
629
+ if do_append:
630
+ target_value, found = search_column_value(row.nested, config.target)
631
+ if found:
632
+ array = target_value
633
+ else:
634
+ array = []
635
+ set_row_staging_value(row, config.target, array)
636
+ array.append(source_value)
637
+ return row
@@ -31,17 +31,10 @@ class AssignArrayConfig:
31
31
  field: str
32
32
  optional: bool = True
33
33
 
34
- @dataclasses.dataclass
35
- class PushConfig:
36
- target: str
37
- source: str
38
- condition: str | None = None
39
-
40
34
  @dataclasses.dataclass
41
35
  class ProcessConfig:
42
36
  assign_array: Mapping[str, list[AssignArrayConfig]] = dataclasses.field(default_factory=OrderedDict)
43
37
  assign_length: FlatFieldMap = dataclasses.field(default_factory=OrderedDict)
44
- push: list[PushConfig] = dataclasses.field(default_factory=list)
45
38
 
46
39
  def __setitem__(self, key, value):
47
40
  setattr(self, key, value)
@@ -20,7 +20,6 @@ import pandas as pd
20
20
 
21
21
  from . config import (
22
22
  AssignArrayConfig,
23
- PushConfig,
24
23
  setup_config,
25
24
  setup_pick_with_args,
26
25
  )
@@ -63,6 +62,15 @@ def register_loader(
63
62
  return loader
64
63
  return decorator
65
64
 
65
+ def load(
66
+ input_file: str,
67
+ ):
68
+ ext = os.path.splitext(input_file)[1]
69
+ if ext not in dict_loaders:
70
+ raise ValueError(f'Unsupported file type: {ext}')
71
+ loader = dict_loaders[ext]
72
+ return loader(input_file)
73
+
66
74
  dict_savers: dict[str, callable] = {}
67
75
  def register_saver(
68
76
  ext: str,
@@ -72,6 +80,16 @@ def register_saver(
72
80
  return saver
73
81
  return decorator
74
82
 
83
+ def save(
84
+ df: pd.DataFrame,
85
+ output_file: str,
86
+ ):
87
+ ext = os.path.splitext(output_file)[1]
88
+ if ext not in dict_savers:
89
+ raise ValueError(f'Unsupported file type: {ext}')
90
+ saver = dict_savers[ext]
91
+ saver(df, output_file)
92
+
75
93
  @register_loader('.csv')
76
94
  def load_csv(
77
95
  input_file: str,
@@ -245,28 +263,6 @@ def search_column_value_from_nested(
245
263
  return None, False
246
264
 
247
265
 
248
- def push_fields(
249
- row: OrderedDict,
250
- list_config: list[PushConfig],
251
- ):
252
- nested_row = nest(row)
253
- for config in list_config:
254
- target_value, found = search_column_value_from_nested(nested_row, config.target)
255
- if found:
256
- array = target_value
257
- else:
258
- array = []
259
- #set_field_value(nested_row, f'{STAGING_FIELD}.{config.target}', array)
260
- set_row_staging_value(nested_row, config.target, array)
261
- source_value, found = search_column_value_from_nested(nested_row, config.source)
262
- if config.condition is None:
263
- array.append(source_value)
264
- continue
265
- condition_value, found = search_column_value_from_nested(nested_row, config.condition)
266
- if condition_value:
267
- array.append(source_value)
268
- return flatten_row(nested_row)
269
-
270
266
  def assign_length(
271
267
  row: OrderedDict,
272
268
  dict_fields: OrderedDict,
@@ -352,8 +348,6 @@ def convert(
352
348
  set_row_staging_value(row, INPUT_FIELD, orig_row.nested)
353
349
  if config.process.assign_array:
354
350
  row.flat= assign_array(row.flat, config.process.assign_array)
355
- if config.process.push:
356
- row.flat = push_fields(row.flat, config.process.push)
357
351
  if config.process.assign_length:
358
352
  row.flat = assign_length(row.flat, config.process.assign_length)
359
353
  if config.actions:
@@ -35,15 +35,17 @@ from .. types import (
35
35
  Row,
36
36
  )
37
37
 
38
- def assign_id(
39
- id_context_map: IdContextMap,
38
+ def get_key_value(
40
39
  row: Row,
41
- config: Config,
40
+ primary: list[str],
41
+ context: list[str],
42
42
  ):
43
+ if not primary:
44
+ raise ValueError('Primary columns must be specified')
43
45
  context_columns = []
44
46
  context_values = []
45
- if config.context:
46
- for context_column in config.context:
47
+ if context:
48
+ for context_column in context:
47
49
  value, found = search_column_value(row.nested, context_column)
48
50
  if not found:
49
51
  raise KeyError(f'Column not found: {context_column}, existing columns: {row.flat.keys()}')
@@ -51,7 +53,7 @@ def assign_id(
51
53
  context_values.append(value)
52
54
  primary_columns = []
53
55
  primary_values = []
54
- for primary_column in config.primary:
56
+ for primary_column in primary:
55
57
  value, found = search_column_value(row.nested, primary_column)
56
58
  if not found:
57
59
  raise KeyError(f'Column not found: {primary_column}, existing columns: {row.flat.keys()}')
@@ -63,13 +65,89 @@ def assign_id(
63
65
  tuple(primary_columns),
64
66
  )
65
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
+ )
66
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)
67
84
  if primary_value not in id_map.dict_value_to_id:
68
85
  field_id = id_map.max_id + 1
69
86
  id_map.max_id = field_id
70
87
  id_map.dict_value_to_id[primary_value] = field_id
71
88
  id_map.dict_id_to_value[field_id] = primary_value
89
+ id_exists = False
72
90
  else:
73
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)
74
152
  set_row_staging_value(row, config.target, field_id)
75
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)
@@ -44,6 +44,7 @@ class AssignIdConfig:
44
44
  target: str
45
45
  primary: list[str]
46
46
  context: list[str] | None = None
47
+ reverse: bool = False
47
48
 
48
49
  @dataclasses.dataclass
49
50
  class FilterConfig:
@@ -76,6 +77,12 @@ class PickConfig:
76
77
  target: str
77
78
  source: str
78
79
 
80
+ @dataclasses.dataclass
81
+ class PushConfig:
82
+ target: str
83
+ source: str
84
+ condition: str | None = None
85
+
79
86
  @dataclasses.dataclass
80
87
  class SplitConfig:
81
88
  target: str
@@ -1,21 +0,0 @@
1
- table_processor/__init__.py,sha256=i7SFej_-ia2PplNZ0Wf3m0M9G_ymn8Q72-ONSBkO8r8,54
2
- table_processor/cli.py,sha256=Q5eshXdgfeoiyJkFlQOCX695_6xi1dcibin0kUKOMX0,1574
3
- table_processor/commands/convert_tables.py,sha256=j25KL0zRl5ikrBk73jAkKn4rPmDq7SecChZxecDpILQ,2123
4
- table_processor/core/actions.py,sha256=-xyZp-RHjPz75JHNeKjDvdaBkDlZYAZbE2lpIJZfRDg,18524
5
- table_processor/core/config.py,sha256=iiHAcJlO4RyXyrXFAd2ZRU3bJBnJIFM79AdfcEMMI5o,11903
6
- table_processor/core/constants.py,sha256=w-1TxtpXywb6Qh8M4YWuzcCHUvCjy5zJYxaXC3RQS6A,158
7
- table_processor/core/convert.py,sha256=uoBHgB85VLn_Yg9ugcC0KgwTVtJHnCyEZnv2FCpbwos,12062
8
- table_processor/core/functions/assign_id.py,sha256=5xJuLpyWvSQ1DhzXiAOLQAwfPo9RKICzS_oka0wzHgA,2065
9
- table_processor/core/functions/flatten_row.py,sha256=2l-s4YXgBM58IthpfVzd7L4EGUCekSi7ss5CaM_3MUU,686
10
- table_processor/core/functions/get_nested_field_value.py,sha256=3u1TA2Ov5biHDLLZQLqwO0WdHMmJNsbfrI8EgstX6yA,635
11
- table_processor/core/functions/nest_row.py,sha256=b5AKfxE39g-NOLranQRy0dfTZq-27Or8ZlgCB8N5kFs,640
12
- table_processor/core/functions/search_column_value.py,sha256=GscwLaMTORHFDhdCdjzdoy46UGyFHrGwDQA2b_tZhsQ,740
13
- table_processor/core/functions/set_flat_field_value.py,sha256=7-BgD2yEUGyBaFaIJ18bYv82Qdy0CN8NiC5ZtsAdv44,531
14
- table_processor/core/functions/set_nested_field_value.py,sha256=csO0v_nW94q-M9bNL91xR-TLHPXDDxnLK8gN-0LLd6k,595
15
- table_processor/core/functions/set_row_value.py,sha256=wlF_nVGZY74XCzd6pBJJyti62m6y0s1kc5Q6uq9jn8o,641
16
- table_processor/core/types.py,sha256=jRPRut8Jr2E458SOYvB3kxKxuMWDHk5KJ8aCqmiFvMs,2365
17
- python_table_processor-0.2.29.dist-info/LICENSE,sha256=1_Gn0I1neLPxDLfLiHEyxjDg-pbAra1p2iHEqutGS_c,1068
18
- python_table_processor-0.2.29.dist-info/METADATA,sha256=6YjaO5gDbtQupOZiv45NHODCGYdDBX7oqKiO-WfYs4k,1099
19
- python_table_processor-0.2.29.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
20
- python_table_processor-0.2.29.dist-info/entry_points.txt,sha256=lq97F6m51yZ93qmVIqkUHJfbILZuYLxrMWXSqrP4JpM,118
21
- python_table_processor-0.2.29.dist-info/RECORD,,