python-table-processor 0.3.10__tar.gz → 0.3.12__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.
Files changed (29) hide show
  1. {python_table_processor-0.3.10 → python_table_processor-0.3.12}/PKG-INFO +1 -1
  2. {python_table_processor-0.3.10 → python_table_processor-0.3.12}/pyproject.toml +1 -1
  3. python_table_processor-0.3.12/table_processor/__init__.py +7 -0
  4. {python_table_processor-0.3.10 → python_table_processor-0.3.12}/table_processor/core/convert.py +8 -200
  5. python_table_processor-0.3.12/table_processor/core/io/__init__.py +12 -0
  6. python_table_processor-0.3.12/table_processor/core/io/io_csv.py +41 -0
  7. python_table_processor-0.3.12/table_processor/core/io/io_excel.py +45 -0
  8. python_table_processor-0.3.12/table_processor/core/io/io_json.py +86 -0
  9. python_table_processor-0.3.12/table_processor/core/io/loader.py +33 -0
  10. python_table_processor-0.3.12/table_processor/core/io/saver.py +31 -0
  11. {python_table_processor-0.3.10 → python_table_processor-0.3.12}/table_processor/core/merge.py +10 -1
  12. python_table_processor-0.3.10/table_processor/__init__.py +0 -2
  13. {python_table_processor-0.3.10 → python_table_processor-0.3.12}/LICENSE +0 -0
  14. {python_table_processor-0.3.10 → python_table_processor-0.3.12}/README.md +0 -0
  15. {python_table_processor-0.3.10 → python_table_processor-0.3.12}/table_processor/cli.py +0 -0
  16. {python_table_processor-0.3.10 → python_table_processor-0.3.12}/table_processor/commands/convert_tables.py +0 -0
  17. {python_table_processor-0.3.10 → python_table_processor-0.3.12}/table_processor/commands/merge_tables.py +0 -0
  18. {python_table_processor-0.3.10 → python_table_processor-0.3.12}/table_processor/core/actions.py +0 -0
  19. {python_table_processor-0.3.10 → python_table_processor-0.3.12}/table_processor/core/config.py +0 -0
  20. {python_table_processor-0.3.10 → python_table_processor-0.3.12}/table_processor/core/constants.py +0 -0
  21. {python_table_processor-0.3.10 → python_table_processor-0.3.12}/table_processor/core/functions/assign_id.py +0 -0
  22. {python_table_processor-0.3.10 → python_table_processor-0.3.12}/table_processor/core/functions/flatten_row.py +0 -0
  23. {python_table_processor-0.3.10 → python_table_processor-0.3.12}/table_processor/core/functions/get_nested_field_value.py +0 -0
  24. {python_table_processor-0.3.10 → python_table_processor-0.3.12}/table_processor/core/functions/nest_row.py +0 -0
  25. {python_table_processor-0.3.10 → python_table_processor-0.3.12}/table_processor/core/functions/search_column_value.py +0 -0
  26. {python_table_processor-0.3.10 → python_table_processor-0.3.12}/table_processor/core/functions/set_flat_field_value.py +0 -0
  27. {python_table_processor-0.3.10 → python_table_processor-0.3.12}/table_processor/core/functions/set_nested_field_value.py +0 -0
  28. {python_table_processor-0.3.10 → python_table_processor-0.3.12}/table_processor/core/functions/set_row_value.py +0 -0
  29. {python_table_processor-0.3.10 → python_table_processor-0.3.12}/table_processor/core/types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-table-processor
3
- Version: 0.3.10
3
+ Version: 0.3.12
4
4
  Summary: A table data processor
5
5
  Home-page: https://github.com/akivajp/python-table-processor
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-table-processor"
3
- version = "0.3.10"
3
+ version = "0.3.12"
4
4
  description = "A table data processor"
5
5
  authors = ["Akiva Miura <akiva.miura@gmail.com>"]
6
6
  license = "MIT"
@@ -0,0 +1,7 @@
1
+ __version__ = "0.3.12"
2
+ __version_tuple__ = (0, 3, 12)
3
+
4
+ from . core.io import (
5
+ load,
6
+ save,
7
+ )
@@ -30,10 +30,8 @@ from . constants import (
30
30
  INPUT_FIELD,
31
31
  STAGING_FIELD,
32
32
  )
33
- from . functions.flatten_row import flatten_row
34
33
  from . functions.get_nested_field_value import get_nested_field_value
35
34
  from . functions.get_nested_field_value import get_nested_field_value
36
- from . functions.nest_row import nest_row as nest
37
35
  from . functions.search_column_value import search_column_value
38
36
  from . functions.set_nested_field_value import set_nested_field_value
39
37
  from . functions.set_row_value import (
@@ -53,199 +51,12 @@ from . types import (
53
51
  GlobalStatus,
54
52
  )
55
53
 
56
- dict_loaders: dict[str, callable] = {}
57
- def register_loader(
58
- ext: str,
59
- ):
60
- def decorator(loader):
61
- dict_loaders[ext] = loader
62
- return loader
63
- return decorator
64
-
65
- def load(
66
- input_file: str,
67
- **kwargs,
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, **kwargs)
74
-
75
- dict_savers: dict[str, callable] = {}
76
- def register_saver(
77
- ext: str,
78
- ):
79
- def decorator(saver):
80
- dict_savers[ext] = saver
81
- return saver
82
- return decorator
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
-
94
- @register_loader('.csv')
95
- def load_csv(
96
- input_file: str,
97
- **kwargs,
98
- ):
99
- skip_header = kwargs.get('skip_header', False)
100
- # utf-8
101
- #df = pd.read_csv(input_file)
102
- # UTF-8 with BOM
103
- if skip_header:
104
- df = pd.read_csv(
105
- input_file,
106
- encoding='utf-8-sig',
107
- header=None,
108
- )
109
- #new_column_names = [f'__values__.{i}' for i in df.columns]
110
- new_column_names = [f'{i}' for i in df.columns]
111
- df = df.rename(columns=dict(
112
- zip(df.columns, new_column_names)
113
- ))
114
- else:
115
- df = pd.read_csv(
116
- input_file,
117
- encoding='utf-8-sig',
118
- )
119
- return df
120
-
121
- @register_loader('.xlsx')
122
- def load_excel(
123
- input_file: str,
124
- **kwargs,
125
- ):
126
- #df = pd.read_excel(input_file)
127
- # NOTE: Excelで勝手に日時データなどに変換されてしまうことを防ぐため
128
- df = pd.read_excel(input_file, dtype=str)
129
- # NOTE: 列番号でもアクセスできるようフィールドを追加する
130
- df_with_column_number = pd.read_excel(
131
- input_file, dtype=str, header=None, skiprows=1
132
- )
133
- new_column_names = [f'__values__.{i}' for i in df_with_column_number.columns]
134
- df2 = df_with_column_number.rename(columns=dict(
135
- zip(df_with_column_number.columns, new_column_names)
136
- ))
137
- df = pd.concat([df, df2], axis=1)
138
- df = df.dropna(axis=0, how='all')
139
- df = df.dropna(axis=1, how='all')
140
- return df
141
-
142
- @register_loader('.json')
143
- def load_json(
144
- input_file: str,
145
- **kiwargs,
146
- ):
147
- with open(input_file, 'r') as f:
148
- data = json.load(f)
149
- if not isinstance(data, list):
150
- raise ValueError(f'Invalid JSON array data: {input_file}')
151
- #ic(data[0])
152
- rows = []
153
- for row in data:
154
- new_row = flatten_row(row)
155
- rows.append(new_row)
156
- df = pd.DataFrame(rows)
157
- return df
158
-
159
- @register_saver('.json')
160
- def save_json(
161
- df: pd.DataFrame,
162
- output_file: str,
163
- ):
164
- # NOTE: この方法だとスラッシュがすべてエスケープされてしまった
165
- #df.to_json(
166
- # output_file,
167
- # orient='records',
168
- # force_ascii=False,
169
- # indent=2,
170
- # escape_forward_slashes=False,
171
- #)
172
- #ic(df.iloc[0])
173
- data = df.to_dict(orient='records')
174
- #ic(data[0])
175
- data = [nest(row) for row in data]
176
- #ic(data[0])
177
- with open(output_file, 'w') as f:
178
- json.dump(
179
- data,
180
- f,
181
- indent=2,
182
- ensure_ascii=False,
183
- )
184
-
185
- @register_loader('.jsonl')
186
- def load_jsonl(
187
- input_file: str,
188
- **kwargs,
189
- ):
190
- rows = []
191
- with open(input_file, 'r') as f:
192
- for line in f:
193
- row = json.loads(line)
194
- rows.append(row)
195
- df = pd.DataFrame(rows)
196
- return df
197
-
198
- @register_saver('.jsonl')
199
- def save_jsonl(
200
- df: pd.DataFrame,
201
- output_file: str,
202
- ):
203
- # NOTE: この方法だとスラッシュがすべてエスケープされてしまった
204
- #df.to_json(
205
- # output_file,
206
- # orient='records',
207
- # lines=True,
208
- # force_ascii=False,
209
- #)
210
- with open(output_file, 'w') as f:
211
- for index, row in df.iterrows():
212
- data = row.to_dict()
213
- json.dump(
214
- data,
215
- f,
216
- ensure_ascii=False,
217
- )
218
- f.write('\n')
219
-
220
- @register_saver('.csv')
221
- def save_csv(
222
- df: pd.DataFrame,
223
- output_file: str,
224
- ):
225
- # utf-8
226
- #df.to_csv(output_file, index=False)
227
- # UTF-8 with BOM
228
- df.to_csv(output_file, index=False, encoding='utf-8-sig')
229
-
230
- @register_saver('.xlsx')
231
- def save_excel(
232
- df: pd.DataFrame,
233
- output_file: str,
234
- ):
235
- # openpyxl
236
- df.to_excel(output_file, index=False)
237
- # xlsxwriter
238
- #writer = pd.ExcelWriter(
239
- # output_file,
240
- # engine='xlsxwriter',
241
- # engine_kwargs={
242
- # 'options': {
243
- # 'strings_to_urls': False,
244
- # },
245
- # }
246
- #)
247
- #df.to_excel(writer, index=False)
248
- #writer.close()
54
+ from . io import (
55
+ get_loader,
56
+ get_saver,
57
+ load,
58
+ save,
59
+ )
249
60
 
250
61
  def assign_array(
251
62
  row: OrderedDict,
@@ -317,10 +128,7 @@ def convert(
317
128
  action_delimiter=action_delimiter
318
129
  )
319
130
  if output_file:
320
- ext = os.path.splitext(output_file)[1]
321
- if ext not in dict_savers:
322
- raise ValueError(f'Unsupported file type: {ext}')
323
- saver = dict_savers[ext]
131
+ saver = get_saver(output_file)
324
132
  ic(config)
325
133
  #return # debug return
326
134
  for input_file in input_files:
@@ -391,7 +199,7 @@ def convert(
391
199
  #ic(all_df.columns)
392
200
  #ic(all_df.iloc[0])
393
201
  if output_file:
394
- ic('Saing to: ', output_file)
202
+ ic('Saving to: ', output_file)
395
203
  saver(all_df, output_file)
396
204
  else:
397
205
  ic(all_df)
@@ -0,0 +1,12 @@
1
+ from . loader import (
2
+ get_loader,
3
+ load,
4
+ )
5
+ from . saver import (
6
+ get_saver,
7
+ save,
8
+ )
9
+
10
+ from . import io_csv
11
+ from . import io_excel
12
+ from . import io_json
@@ -0,0 +1,41 @@
1
+ import pandas as pd
2
+
3
+ from . loader import register_loader
4
+ from . saver import register_saver
5
+
6
+ @register_loader('.csv')
7
+ def load_csv(
8
+ input_file: str,
9
+ **kwargs,
10
+ ):
11
+ skip_header = kwargs.get('skip_header', False)
12
+ # utf-8
13
+ #df = pd.read_csv(input_file)
14
+ # UTF-8 with BOM
15
+ if skip_header:
16
+ df = pd.read_csv(
17
+ input_file,
18
+ encoding='utf-8-sig',
19
+ header=None,
20
+ )
21
+ #new_column_names = [f'__values__.{i}' for i in df.columns]
22
+ new_column_names = [f'{i}' for i in df.columns]
23
+ df = df.rename(columns=dict(
24
+ zip(df.columns, new_column_names)
25
+ ))
26
+ else:
27
+ df = pd.read_csv(
28
+ input_file,
29
+ encoding='utf-8-sig',
30
+ )
31
+ return df
32
+
33
+ @register_saver('.csv')
34
+ def save_csv(
35
+ df: pd.DataFrame,
36
+ output_file: str,
37
+ ):
38
+ # utf-8
39
+ #df.to_csv(output_file, index=False)
40
+ # UTF-8 with BOM
41
+ df.to_csv(output_file, index=False, encoding='utf-8-sig')
@@ -0,0 +1,45 @@
1
+ import pandas as pd
2
+
3
+ from . loader import register_loader
4
+ from . saver import register_saver
5
+
6
+ @register_loader('.xlsx')
7
+ def load_excel(
8
+ input_file: str,
9
+ **kwargs,
10
+ ):
11
+ #df = pd.read_excel(input_file)
12
+ # NOTE: Excelで勝手に日時データなどに変換されてしまうことを防ぐため
13
+ df = pd.read_excel(input_file, dtype=str)
14
+ # NOTE: 列番号でもアクセスできるようフィールドを追加する
15
+ df_with_column_number = pd.read_excel(
16
+ input_file, dtype=str, header=None, skiprows=1
17
+ )
18
+ new_column_names = [f'__values__.{i}' for i in df_with_column_number.columns]
19
+ df2 = df_with_column_number.rename(columns=dict(
20
+ zip(df_with_column_number.columns, new_column_names)
21
+ ))
22
+ df = pd.concat([df, df2], axis=1)
23
+ df = df.dropna(axis=0, how='all')
24
+ df = df.dropna(axis=1, how='all')
25
+ return df
26
+
27
+ @register_saver('.xlsx')
28
+ def save_excel(
29
+ df: pd.DataFrame,
30
+ output_file: str,
31
+ ):
32
+ # openpyxl
33
+ df.to_excel(output_file, index=False)
34
+ # xlsxwriter
35
+ #writer = pd.ExcelWriter(
36
+ # output_file,
37
+ # engine='xlsxwriter',
38
+ # engine_kwargs={
39
+ # 'options': {
40
+ # 'strings_to_urls': False,
41
+ # },
42
+ # }
43
+ #)
44
+ #df.to_excel(writer, index=False)
45
+ #writer.close()
@@ -0,0 +1,86 @@
1
+ import json
2
+ import pandas as pd
3
+
4
+ from . loader import register_loader
5
+ from . saver import register_saver
6
+
7
+ from .. functions.flatten_row import flatten_row
8
+ from .. functions.nest_row import nest_row
9
+
10
+ @register_loader('.json')
11
+ def load_json(
12
+ input_file: str,
13
+ **kiwargs,
14
+ ):
15
+ with open(input_file, 'r') as f:
16
+ data = json.load(f)
17
+ if not isinstance(data, list):
18
+ raise ValueError(f'Invalid JSON array data: {input_file}')
19
+ #ic(data[0])
20
+ rows = []
21
+ for row in data:
22
+ new_row = flatten_row(row)
23
+ rows.append(new_row)
24
+ df = pd.DataFrame(rows)
25
+ return df
26
+
27
+ @register_saver('.json')
28
+ def save_json(
29
+ df: pd.DataFrame,
30
+ output_file: str,
31
+ ):
32
+ # NOTE: この方法だとスラッシュがすべてエスケープされてしまった
33
+ #df.to_json(
34
+ # output_file,
35
+ # orient='records',
36
+ # force_ascii=False,
37
+ # indent=2,
38
+ # escape_forward_slashes=False,
39
+ #)
40
+ #ic(df.iloc[0])
41
+ data = df.to_dict(orient='records')
42
+ #ic(data[0])
43
+ data = [nest_row(row) for row in data]
44
+ #ic(data[0])
45
+ with open(output_file, 'w') as f:
46
+ json.dump(
47
+ data,
48
+ f,
49
+ indent=2,
50
+ ensure_ascii=False,
51
+ )
52
+
53
+ @register_loader('.jsonl')
54
+ def load_jsonl(
55
+ input_file: str,
56
+ **kwargs,
57
+ ):
58
+ rows = []
59
+ with open(input_file, 'r') as f:
60
+ for line in f:
61
+ row = json.loads(line)
62
+ rows.append(row)
63
+ df = pd.DataFrame(rows)
64
+ return df
65
+
66
+ @register_saver('.jsonl')
67
+ def save_jsonl(
68
+ df: pd.DataFrame,
69
+ output_file: str,
70
+ ):
71
+ # NOTE: この方法だとスラッシュがすべてエスケープされてしまった
72
+ #df.to_json(
73
+ # output_file,
74
+ # orient='records',
75
+ # lines=True,
76
+ # force_ascii=False,
77
+ #)
78
+ with open(output_file, 'w') as f:
79
+ for index, row in df.iterrows():
80
+ data = row.to_dict()
81
+ json.dump(
82
+ data,
83
+ f,
84
+ ensure_ascii=False,
85
+ )
86
+ f.write('\n')
@@ -0,0 +1,33 @@
1
+ import os
2
+ from typing import Any, Protocol
3
+
4
+ import pandas as pd
5
+
6
+ class LoaderType(Protocol):
7
+ def __call__(self, input_file: str, **kwargs: Any) -> pd.DataFrame:
8
+ ...
9
+
10
+ dict_loaders: dict[str, LoaderType] = {}
11
+ def register_loader(
12
+ ext: str,
13
+ ):
14
+ def decorator(loader):
15
+ dict_loaders[ext] = loader
16
+ return loader
17
+ return decorator
18
+
19
+ def get_loader(
20
+ input_file: str,
21
+ ):
22
+ ext = os.path.splitext(input_file)[1]
23
+ if ext not in dict_loaders:
24
+ raise ValueError(f'Unsupported file type: {ext}')
25
+ loader = dict_loaders[ext]
26
+ return loader
27
+
28
+ def load(
29
+ input_file: str,
30
+ **kwargs,
31
+ ):
32
+ loader = get_loader(input_file)
33
+ return loader(input_file, **kwargs)
@@ -0,0 +1,31 @@
1
+ import os.path
2
+ import pandas as pd
3
+
4
+ from typing import Callable
5
+
6
+ type Saver = Callable[[pd.DataFrame, str], None]
7
+
8
+ dict_savers: dict[str, Saver] = {}
9
+ def register_saver(
10
+ ext: str,
11
+ ):
12
+ def decorator(saver):
13
+ dict_savers[ext] = saver
14
+ return saver
15
+ return decorator
16
+
17
+ def get_saver(
18
+ output_file: str,
19
+ ):
20
+ ext = os.path.splitext(output_file)[1]
21
+ if ext not in dict_savers:
22
+ raise ValueError(f'Unsupported file type: {ext}')
23
+ saver = dict_savers[ext]
24
+ return saver
25
+
26
+ def save(
27
+ df: pd.DataFrame,
28
+ output_file: str,
29
+ ):
30
+ saver = get_saver(output_file)
31
+ saver(df, output_file)
@@ -34,7 +34,9 @@ from . actions import (
34
34
  prepare_row,
35
35
  )
36
36
 
37
- from . convert import (
37
+ from . io import (
38
+ get_loader,
39
+ get_saver,
38
40
  load,
39
41
  save,
40
42
  )
@@ -75,6 +77,13 @@ def merge(
75
77
  all_modified_rows = []
76
78
  list_ignored_keys = []
77
79
  num_modified = 0
80
+ for output_path in [
81
+ output_base_data_file,
82
+ output_modified_data_file,
83
+ output_remaining_data_file,
84
+ ]:
85
+ if output_path:
86
+ get_saver(output_path)
78
87
  for previous_file in previous_files:
79
88
  if not os.path.exists(previous_file):
80
89
  raise FileNotFoundError(f'File not found: {previous_file}')
@@ -1,2 +0,0 @@
1
- __version__ = "0.3.10"
2
- __version_tuple__ = (0, 3, 10)