python-table-converter 0.1.1__tar.gz → 0.2.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.
@@ -1,7 +1,8 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-table-converter
3
- Version: 0.1.1
3
+ Version: 0.2.0
4
4
  Summary: A table data converter
5
+ Home-page: https://github.com/akivajp/python-table-converter
5
6
  License: MIT
6
7
  Author: Akiva Miura
7
8
  Author-email: akiva.miura@gmail.com
@@ -15,7 +16,9 @@ Requires-Dist: icecream (>=2.1.3,<3.0.0)
15
16
  Requires-Dist: logzero (>=1.7.0,<2.0.0)
16
17
  Requires-Dist: openpyxl (>=3.1.5,<4.0.0)
17
18
  Requires-Dist: pandas (>=2.2.3,<3.0.0)
19
+ Requires-Dist: pyyaml (>=6.0.2,<7.0.0)
18
20
  Requires-Dist: tqdm (>=4.67.0,<5.0.0)
21
+ Project-URL: Repository, https://github.com/akivajp/python-table-converter
19
22
  Description-Content-Type: text/markdown
20
23
 
21
24
  # Table Data Converter
@@ -1,10 +1,11 @@
1
1
  [tool.poetry]
2
2
  name = "python-table-converter"
3
- version = "0.1.1"
3
+ version = "0.2.0"
4
4
  description = "A table data converter"
5
5
  authors = ["Akiva Miura <akiva.miura@gmail.com>"]
6
6
  license = "MIT"
7
7
  readme = "README.md"
8
+ repository = "https://github.com/akivajp/python-table-converter"
8
9
  packages = [
9
10
  { include = "table_converter" },
10
11
  ]
@@ -24,6 +25,7 @@ logzero = "^1.7.0"
24
25
  tqdm = "^4.67.0"
25
26
  pandas = "^2.2.3"
26
27
  openpyxl = "^3.1.5"
28
+ pyyaml = "^6.0.2"
27
29
 
28
30
 
29
31
  [build-system]
@@ -0,0 +1,2 @@
1
+ __version__ = "0.2.0"
2
+ __version_tuple__ = (0, 2, 0)
@@ -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,56 @@
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 Config:
15
+ #map: OrderedDict|None = dataclasses.field(default_factory=lambda: None)
16
+ map: FieldMap|None = dataclasses.field(default_factory=lambda: None)
17
+
18
+ def flatten(
19
+ mapping: FieldMap,
20
+ parent_key: str = '',
21
+ new_mapping: FlatFieldMap | None = None,
22
+ ) -> FlatFieldMap:
23
+ if new_mapping is None:
24
+ new_mapping = OrderedDict()
25
+ for key, mapped in mapping.items():
26
+ new_key = f'{parent_key}.{key}' if parent_key else key
27
+ if isinstance(mapped, Mapping):
28
+ flatten(mapped, new_key, new_mapping)
29
+ else:
30
+ new_mapping[new_key] = mapped
31
+ return new_mapping
32
+
33
+ def setup_config(
34
+ config_path: str | None = None,
35
+ ):
36
+ if config_path:
37
+ if config_path.endswith('.yaml'):
38
+ yaml.add_constructor(
39
+ yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
40
+ lambda loader, node: OrderedDict(loader.construct_pairs(node)),
41
+ )
42
+ with open(config_path, 'r') as f:
43
+ data = yaml.load(f, yaml.Loader)
44
+ #ic(data)
45
+ config = Config(
46
+ #**data,
47
+ map = flatten(data.get('map', {})),
48
+ )
49
+ else:
50
+ raise ValueError(
51
+ 'Only YAML configuration files are supported.'
52
+ )
53
+ else:
54
+ config = Config(
55
+ )
56
+ 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,17 @@ 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
250
  dict_split_by_newline: OrderedDict | None = None
245
251
  dict_assign_ids= None
246
252
  root_id_stat = create_id_stat_node()
253
+ config = setup_config(config_path)
254
+ ic(config)
247
255
  if assign_constants:
248
256
  dict_constants = OrderedDict()
249
257
  fields = assign_constants.split(',')
@@ -263,14 +271,15 @@ def convert(
263
271
  else:
264
272
  raise ValueError(f'Invalid template assignment: {field}')
265
273
  if pickup_columns:
266
- dict_columns = OrderedDict()
274
+ if config.map is None:
275
+ config.map = OrderedDict()
267
276
  fields = pickup_columns.split(',')
268
277
  for field in fields:
269
278
  if '=' in field:
270
279
  dst, value = field.split('=')
271
- dict_columns[dst] = value
280
+ set_field_value(config.map, dst, value)
272
281
  else:
273
- dict_columns[field] = field
282
+ set_field_value(config.map, field, field)
274
283
  if fields_to_split_by_newline:
275
284
  #list_fields_to_split_by_newline = fields_to_split_by_newline.split(',')
276
285
  dict_split_by_newline = OrderedDict()
@@ -295,6 +304,7 @@ def convert(
295
304
  if ext not in dict_savers:
296
305
  raise ValueError(f'Unsupported file type: {ext}')
297
306
  saver = dict_savers[ext]
307
+ ic(config)
298
308
  for input_file in input_files:
299
309
  ic(input_file)
300
310
  if not os.path.exists(input_file):
@@ -318,18 +328,16 @@ def convert(
318
328
  set_field_value(new_row, '__debug__.__file__', input_file)
319
329
  if dict_constants:
320
330
  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)
331
+ if config.map:
332
+ new_row = remap_columns(new_row, config.map)
325
333
  if dict_split_by_newline:
326
334
  new_row = apply_fields_split_by_newline(new_row, dict_split_by_newline)
327
335
  if dict_assign_ids:
328
336
  new_row = assign_id(new_row, dict_assign_ids, root_id_stat)
329
337
  if dict_formats:
330
338
  new_row = map_formats(new_row, dict_formats)
331
- if dict_columns:
332
- new_row = remap_columns(new_row, dict_columns)
339
+ if config.map:
340
+ new_row = remap_columns(new_row, config.map)
333
341
  if not output_debug:
334
342
  new_row.pop('__debug__', None)
335
343
  new_rows.append(new_row)
@@ -1,2 +0,0 @@
1
- __version__ = "0.1.1"
2
- __version_tuple__ = (0, 1, 1)