python-table-converter 0.1.2__tar.gz → 0.2.1__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-table-converter
3
- Version: 0.1.2
3
+ Version: 0.2.1
4
4
  Summary: A table data converter
5
5
  Home-page: https://github.com/akivajp/python-table-converter
6
6
  License: MIT
@@ -16,6 +16,7 @@ Requires-Dist: icecream (>=2.1.3,<3.0.0)
16
16
  Requires-Dist: logzero (>=1.7.0,<2.0.0)
17
17
  Requires-Dist: openpyxl (>=3.1.5,<4.0.0)
18
18
  Requires-Dist: pandas (>=2.2.3,<3.0.0)
19
+ Requires-Dist: pyyaml (>=6.0.2,<7.0.0)
19
20
  Requires-Dist: tqdm (>=4.67.0,<5.0.0)
20
21
  Project-URL: Repository, https://github.com/akivajp/python-table-converter
21
22
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-table-converter"
3
- version = "0.1.2"
3
+ version = "0.2.1"
4
4
  description = "A table data converter"
5
5
  authors = ["Akiva Miura <akiva.miura@gmail.com>"]
6
6
  license = "MIT"
@@ -25,6 +25,7 @@ logzero = "^1.7.0"
25
25
  tqdm = "^4.67.0"
26
26
  pandas = "^2.2.3"
27
27
  openpyxl = "^3.1.5"
28
+ pyyaml = "^6.0.2"
28
29
 
29
30
 
30
31
  [build-system]
@@ -0,0 +1,2 @@
1
+ __version__ = "0.2.1"
2
+ __version_tuple__ = (0, 2, 1)
@@ -2,6 +2,7 @@
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
4
  import argparse
5
+ import os
5
6
  import sys
6
7
 
7
8
  from icecream import ic
@@ -9,9 +10,14 @@ from icecream import ic
9
10
  def parse_and_run(
10
11
  parser: argparse.ArgumentParser,
11
12
  ):
12
- ic.disable()
13
+ if os.environ.get('DEBUG', '').lower() in ['1', 'true', 'yes', 'on']:
14
+ pass
15
+ else:
16
+ ic.disable()
13
17
  ic()
14
18
  args = parser.parse_args()
19
+ if args.verbose:
20
+ ic.enable()
15
21
  ic(args)
16
22
  if args.handler:
17
23
  args.handler(args)
@@ -28,10 +34,10 @@ def command_convert_tables(
28
34
  )
29
35
  else:
30
36
  command_parser = parser
31
- from . commands.convert_tables import setup_parser
37
+ from table_converter.commands.convert_tables import setup_parser
32
38
  setup_parser(command_parser)
33
39
  if parser is None:
34
- parse_and_run(parser)
40
+ parse_and_run(command_parser)
35
41
 
36
42
  def main():
37
43
  parser = argparse.ArgumentParser(description='Table Data Converter')
@@ -12,6 +12,7 @@ def run(
12
12
  convert(
13
13
  input_files = args.input_files,
14
14
  output_file = args.output_file,
15
+ config_path = args.config,
15
16
  assign_constants = args.assign_constants,
16
17
  assign_formats = args.assign_formats,
17
18
  pickup_columns= args.pickup_columns,
@@ -23,6 +24,10 @@ def run(
23
24
  def setup_parser(
24
25
  parser: argparse.ArgumentParser,
25
26
  ):
27
+ parser.add_argument(
28
+ '--verbose', '-v',
29
+ action='store_true',
30
+ )
26
31
  parser.add_argument(
27
32
  'input_files',
28
33
  metavar='INPUT_FILE',
@@ -30,11 +35,16 @@ def setup_parser(
30
35
  help='Path to the input file.'
31
36
  )
32
37
  parser.add_argument(
33
- '-o', '--output-file',
38
+ '--output-file', '-o',
34
39
  metavar='OUTPUT_FILE',
35
40
  required=True,
36
41
  help='Path to the output file.'
37
42
  )
43
+ parser.add_argument(
44
+ '--config', '-c',
45
+ type=str,
46
+ help='Path to the configuration file.',
47
+ )
38
48
  parser.add_argument(
39
49
  '--pickup-columns',
40
50
  type=str,
@@ -0,0 +1,59 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from collections import OrderedDict
4
+ import dataclasses
5
+ from typing import Mapping
6
+
7
+ from icecream import ic
8
+ import yaml
9
+
10
+ type FlatFieldMap = Mapping[str, str]
11
+ type FieldMap = Mapping[str, str|FieldMap]
12
+
13
+ @dataclasses.dataclass
14
+ class ProcessConfig:
15
+ split_by_newline: FlatFieldMap = dataclasses.field(default_factory=OrderedDict)
16
+
17
+ @dataclasses.dataclass
18
+ class Config:
19
+ map: FieldMap = dataclasses.field(default_factory=OrderedDict)
20
+ process: ProcessConfig = dataclasses.field(default_factory=ProcessConfig)
21
+
22
+ def flatten(
23
+ mapping: FieldMap,
24
+ parent_key: str = '',
25
+ new_mapping: FlatFieldMap | None = None,
26
+ ) -> FlatFieldMap:
27
+ if new_mapping is None:
28
+ new_mapping = OrderedDict()
29
+ for key, mapped in mapping.items():
30
+ new_key = f'{parent_key}.{key}' if parent_key else key
31
+ if isinstance(mapped, Mapping):
32
+ flatten(mapped, new_key, new_mapping)
33
+ else:
34
+ new_mapping[new_key] = mapped
35
+ return new_mapping
36
+
37
+ def setup_config(
38
+ config_path: str | None = None,
39
+ ):
40
+ config = Config()
41
+ if config_path:
42
+ if config_path.endswith('.yaml'):
43
+ yaml.add_constructor(
44
+ yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
45
+ lambda loader, node: OrderedDict(loader.construct_pairs(node)),
46
+ )
47
+ with open(config_path, 'r') as f:
48
+ loaded = yaml.load(f, yaml.Loader)
49
+ else:
50
+ raise ValueError(
51
+ 'Only YAML configuration files are supported.'
52
+ )
53
+ ic(loaded)
54
+ if 'map' in loaded:
55
+ config.map = flatten(loaded['map'])
56
+ if 'process' in loaded:
57
+ if 'split_by_newline' in loaded['process']:
58
+ config.process.split_by_newline = flatten(loaded['process']['split_by_newline'])
59
+ return config
@@ -5,9 +5,15 @@ import os
5
5
 
6
6
  from collections import OrderedDict
7
7
 
8
+ # 3-rd party modules
9
+
10
+ from icecream import ic
8
11
  import numpy as np
9
12
  import pandas as pd
10
- from icecream import ic
13
+
14
+ # local
15
+
16
+ from . config import setup_config
11
17
 
12
18
  dict_loaders: dict[str, callable] = {}
13
19
  def register_loader(
@@ -227,6 +233,7 @@ def assign_id(
227
233
  def convert(
228
234
  input_files: list[str],
229
235
  output_file: str | None = None,
236
+ config_path: str | None = None,
230
237
  assign_constants: str | None = None,
231
238
  assign_formats: str | None = None,
232
239
  pickup_columns: str | None = None,
@@ -234,16 +241,16 @@ def convert(
234
241
  fields_to_assign_ids: str | None = None,
235
242
  output_debug: bool = False,
236
243
  ):
244
+ ic.enable()
237
245
  ic()
238
246
  ic(input_files)
239
247
  df_list = []
240
248
  dict_constants: OrderedDict | None = None
241
- dict_columns: OrderedDict | None = None
242
249
  dict_formats: OrderedDict | None = None
243
- #list_fields_to_split_by_newline = None
244
- dict_split_by_newline: OrderedDict | None = None
245
250
  dict_assign_ids= None
246
251
  root_id_stat = create_id_stat_node()
252
+ config = setup_config(config_path)
253
+ ic(config)
247
254
  if assign_constants:
248
255
  dict_constants = OrderedDict()
249
256
  fields = assign_constants.split(',')
@@ -263,22 +270,19 @@ def convert(
263
270
  else:
264
271
  raise ValueError(f'Invalid template assignment: {field}')
265
272
  if pickup_columns:
266
- dict_columns = OrderedDict()
267
273
  fields = pickup_columns.split(',')
268
274
  for field in fields:
269
275
  if '=' in field:
270
276
  dst, value = field.split('=')
271
- dict_columns[dst] = value
277
+ config.map[dst] = value
272
278
  else:
273
- dict_columns[field] = field
279
+ config.map[field] = field
274
280
  if fields_to_split_by_newline:
275
- #list_fields_to_split_by_newline = fields_to_split_by_newline.split(',')
276
- dict_split_by_newline = OrderedDict()
277
281
  fields = fields_to_split_by_newline.split(',')
278
282
  for field in fields:
279
283
  if '=' in field:
280
284
  dst, src = field.split('=')
281
- dict_split_by_newline[dst] = src
285
+ config.process.split_by_newline[dst] = src
282
286
  else:
283
287
  raise ValueError(f'Invalid split by newline: {field}')
284
288
  if fields_to_assign_ids:
@@ -295,6 +299,7 @@ def convert(
295
299
  if ext not in dict_savers:
296
300
  raise ValueError(f'Unsupported file type: {ext}')
297
301
  saver = dict_savers[ext]
302
+ ic(config)
298
303
  for input_file in input_files:
299
304
  ic(input_file)
300
305
  if not os.path.exists(input_file):
@@ -318,18 +323,16 @@ def convert(
318
323
  set_field_value(new_row, '__debug__.__file__', input_file)
319
324
  if dict_constants:
320
325
  new_row = map_constants(new_row, dict_constants)
321
- if dict_columns:
322
- new_row = remap_columns(new_row, dict_columns)
323
- #if list_fields_to_split_by_newline:
324
- # new_row = apply_fields_split_by_newline(new_row, list_fields_to_split_by_newline)
325
- if dict_split_by_newline:
326
- new_row = apply_fields_split_by_newline(new_row, dict_split_by_newline)
326
+ if config.map:
327
+ new_row = remap_columns(new_row, config.map)
328
+ if config.process.split_by_newline:
329
+ new_row = apply_fields_split_by_newline(new_row, config.process.split_by_newline)
327
330
  if dict_assign_ids:
328
331
  new_row = assign_id(new_row, dict_assign_ids, root_id_stat)
329
332
  if dict_formats:
330
333
  new_row = map_formats(new_row, dict_formats)
331
- if dict_columns:
332
- new_row = remap_columns(new_row, dict_columns)
334
+ if config.map:
335
+ new_row = remap_columns(new_row, config.map)
333
336
  if not output_debug:
334
337
  new_row.pop('__debug__', None)
335
338
  new_rows.append(new_row)
@@ -1,2 +0,0 @@
1
- __version__ = "0.1.2"
2
- __version_tuple__ = (0, 1, 2)