excel-list-transform 0.5__tar.gz → 0.6.2__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 (39) hide show
  1. {excel_list_transform-0.5/excel_list_transform.egg-info → excel_list_transform-0.6.2}/PKG-INFO +9 -9
  2. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/README.md +18 -16
  3. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/README_pypi.md +3 -2
  4. {excel_list_transform-0.5 → excel_list_transform-0.6.2/excel_list_transform.egg-info}/PKG-INFO +9 -9
  5. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/excel_list_transform.egg-info/SOURCES.txt +1 -0
  6. excel_list_transform-0.6.2/excel_list_transform.egg-info/requires.txt +8 -0
  7. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/pyproject.toml +2 -2
  8. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/setup.py +7 -7
  9. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/config.py +43 -5
  10. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/config_excel_list_transform.py +12 -2
  11. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/generate_txt.py +14 -1
  12. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/handle_csv.py +15 -12
  13. excel_list_transform-0.6.2/src/excel_list_transform/py.typed +2 -0
  14. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/transform_func_named.py +2 -0
  15. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/transform_func_num.py +3 -1
  16. excel_list_transform-0.5/excel_list_transform.egg-info/requires.txt +0 -9
  17. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/LICENSE.txt +0 -0
  18. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/excel_list_transform.egg-info/dependency_links.txt +0 -0
  19. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/excel_list_transform.egg-info/top_level.txt +0 -0
  20. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/setup.cfg +0 -0
  21. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/__init__.py +0 -0
  22. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/__main__.py +0 -0
  23. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/check_indata_common.py +0 -0
  24. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/commontypes.py +0 -0
  25. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/config_enums.py +0 -0
  26. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/config_factory.py +0 -0
  27. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/config_xls_list_refmt_name.py +0 -0
  28. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/config_xls_list_refmt_num.py +0 -0
  29. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/file_extension.py +0 -0
  30. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/file_must_exist.py +0 -0
  31. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/generate_cfg.py +0 -0
  32. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/handle_empty_column.py +0 -0
  33. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/handle_excel.py +0 -0
  34. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/num_named_conversion.py +0 -0
  35. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/rewrite_value.py +0 -0
  36. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/str_to_enum.py +0 -0
  37. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/transform_cmd.py +0 -0
  38. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/transform_func.py +0 -0
  39. {excel_list_transform-0.5 → excel_list_transform-0.6.2}/src/excel_list_transform/transform_func_common.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: excel-list-transform
3
- Version: 0.5
3
+ Version: 0.6.2
4
4
  Summary: Transform a list in excel or CSV
5
5
  Author: Tom Björkholm
6
6
  Author-email: Tom Björkholm <klausuler_linnet0q@icloud.com>
@@ -8,17 +8,16 @@ Project-URL: Source code, https://bitbucket.org/tom-bjorkholm/excel-list-transfo
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.10.5
11
+ Requires-Python: >=3.12.6
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE.txt
14
14
  Requires-Dist: openpyxl>=3.1.5
15
- Requires-Dist: types-openpyxl>=3.1.5.20240822
15
+ Requires-Dist: types-openpyxl>=3.1.5.20240918
16
16
  Requires-Dist: pylightxl>=1.61
17
17
  Requires-Dist: XlsxWriter>=3.2.0
18
- Requires-Dist: pip>=23.2
19
- Requires-Dist: Pillow>=10.0.1
20
- Requires-Dist: setuptools>=74.0.0
21
- Requires-Dist: build>=1.2.1
18
+ Requires-Dist: pip>=24.2
19
+ Requires-Dist: setuptools>=75.1.0
20
+ Requires-Dist: build>=1.2.2
22
21
  Requires-Dist: wheel>=0.44.0
23
22
 
24
23
  # excel-list-transform
@@ -38,13 +37,14 @@ This small python application:
38
37
  * renames columns in the list
39
38
  * inserts columns in the list
40
39
  * rewrites columns in the list (like transforming telephone numbers from local/national format to international format)
41
- * writest the resulting data (that is a list with columns) to an excel file or to a comma separate values (CSV) file.
40
+ * writes the resulting data (that is a list with columns) to an excel file or to a comma separate values (CSV) file.
42
41
 
43
42
  How this is done is governed by a configuration file. The application can create a number of example configuration files with accompanying description text files.
44
43
 
45
44
  ## Installing it
46
45
 
47
- If you want to use it install it using pip. A precondition is that you have Python 3.10.5 or newer installed on you computer. Python can be downloaded from [https://www.python.org/downloads/](https://www.python.org/downloads/).
46
+ If you want to use it, install it using pip. A precondition is that you have Python 3.12.6 or newer installed on you computer. (Python version 3.10.5 or newer for version 0.5.)
47
+ Python can be downloaded from [https://www.python.org/downloads/](https://www.python.org/downloads/).
48
48
 
49
49
  ### Installing on mac and Linux
50
50
 
@@ -27,15 +27,16 @@ Please see [https://pypi.org/project/excel-list-transform](https://pypi.org/proj
27
27
  ## What it does
28
28
 
29
29
  This small python application:
30
- * reads data (that is a list with columns) from an excel file or from a comma separate values (CSV) file.
31
- * splits columns in the list (like creating "first name" and "last name" columns from "name" column)
32
- * merges columns in the list (like creating "name" column from "first name" and "last name" columns)
33
- * removes columns in the list
34
- * reorders columns in the list
35
- * renames columns in the list
36
- * inserts columns in the list
37
- * rewrites columns in the list (like transforming telephone numbers from local/national format to international format)
38
- * writest the resulting data (that is a list with columns) to an excel file or to a comma separate values (CSV) file.
30
+
31
+ * reads data (that is a list with columns) from an excel file or from a comma separate values (CSV) file.
32
+ * splits columns in the list (like creating "first name" and "last name" columns from "name" column)
33
+ * merges columns in the list (like creating "name" column from "first name" and "last name" columns)
34
+ * removes columns in the list
35
+ * reorders columns in the list
36
+ * renames columns in the list
37
+ * inserts columns in the list
38
+ * rewrites columns in the list (like transforming telephone numbers from local/national format to international format)
39
+ * writes the resulting data (that is a list with columns) to an excel file or to a comma separate values (CSV) file.
39
40
 
40
41
  How this is done is governed by a configuration file. The application can create a number of example configuration files with accompanying description text files.
41
42
 
@@ -49,7 +50,7 @@ For running the script and running the test suite you need a mac or a Linux comp
49
50
 
50
51
  #### Python version
51
52
 
52
- The tests and the script for running the tests, coverage, mypy etc. requires Python version 3.12.5 or newer.
53
+ The tests and the script for running the tests, coverage, mypy etc. requires Python version 3.12.6 or newer.
53
54
 
54
55
  #### Zsh
55
56
 
@@ -62,12 +63,13 @@ The internal APIs in this package are not guaranteed to be stable. They can chan
62
63
  ### Building application
63
64
 
64
65
  There are 3 scripts for building the application
65
- * setup_build_environment.zsh
66
- Run this script first to get the environment set up for building
67
- * doBuild.zsh
68
- Run this script to build an installation package (.whl) and to run the tests on it in a venv (virtual environment).
69
- * clean.zsh
70
- Deletes all files that was produced by the build to start over from a clean state.
66
+
67
+ * setup_build_environment.zsh
68
+ Run this script first to get the environment set up for building
69
+ * doBuild.zsh
70
+ Run this script to build an installation package (.whl) and to run the tests on it in a venv (virtual environment).
71
+ * clean.zsh
72
+ Deletes all files that was produced by the build to start over from a clean state.
71
73
 
72
74
  The "testing" includes pytest, pylint, flake8 and mypy.
73
75
 
@@ -15,13 +15,14 @@ This small python application:
15
15
  * renames columns in the list
16
16
  * inserts columns in the list
17
17
  * rewrites columns in the list (like transforming telephone numbers from local/national format to international format)
18
- * writest the resulting data (that is a list with columns) to an excel file or to a comma separate values (CSV) file.
18
+ * writes the resulting data (that is a list with columns) to an excel file or to a comma separate values (CSV) file.
19
19
 
20
20
  How this is done is governed by a configuration file. The application can create a number of example configuration files with accompanying description text files.
21
21
 
22
22
  ## Installing it
23
23
 
24
- If you want to use it install it using pip. A precondition is that you have Python 3.10.5 or newer installed on you computer. Python can be downloaded from [https://www.python.org/downloads/](https://www.python.org/downloads/).
24
+ If you want to use it, install it using pip. A precondition is that you have Python 3.12.6 or newer installed on you computer. (Python version 3.10.5 or newer for version 0.5.)
25
+ Python can be downloaded from [https://www.python.org/downloads/](https://www.python.org/downloads/).
25
26
 
26
27
  ### Installing on mac and Linux
27
28
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: excel-list-transform
3
- Version: 0.5
3
+ Version: 0.6.2
4
4
  Summary: Transform a list in excel or CSV
5
5
  Author: Tom Björkholm
6
6
  Author-email: Tom Björkholm <klausuler_linnet0q@icloud.com>
@@ -8,17 +8,16 @@ Project-URL: Source code, https://bitbucket.org/tom-bjorkholm/excel-list-transfo
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.10.5
11
+ Requires-Python: >=3.12.6
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE.txt
14
14
  Requires-Dist: openpyxl>=3.1.5
15
- Requires-Dist: types-openpyxl>=3.1.5.20240822
15
+ Requires-Dist: types-openpyxl>=3.1.5.20240918
16
16
  Requires-Dist: pylightxl>=1.61
17
17
  Requires-Dist: XlsxWriter>=3.2.0
18
- Requires-Dist: pip>=23.2
19
- Requires-Dist: Pillow>=10.0.1
20
- Requires-Dist: setuptools>=74.0.0
21
- Requires-Dist: build>=1.2.1
18
+ Requires-Dist: pip>=24.2
19
+ Requires-Dist: setuptools>=75.1.0
20
+ Requires-Dist: build>=1.2.2
22
21
  Requires-Dist: wheel>=0.44.0
23
22
 
24
23
  # excel-list-transform
@@ -38,13 +37,14 @@ This small python application:
38
37
  * renames columns in the list
39
38
  * inserts columns in the list
40
39
  * rewrites columns in the list (like transforming telephone numbers from local/national format to international format)
41
- * writest the resulting data (that is a list with columns) to an excel file or to a comma separate values (CSV) file.
40
+ * writes the resulting data (that is a list with columns) to an excel file or to a comma separate values (CSV) file.
42
41
 
43
42
  How this is done is governed by a configuration file. The application can create a number of example configuration files with accompanying description text files.
44
43
 
45
44
  ## Installing it
46
45
 
47
- If you want to use it install it using pip. A precondition is that you have Python 3.10.5 or newer installed on you computer. Python can be downloaded from [https://www.python.org/downloads/](https://www.python.org/downloads/).
46
+ If you want to use it, install it using pip. A precondition is that you have Python 3.12.6 or newer installed on you computer. (Python version 3.10.5 or newer for version 0.5.)
47
+ Python can be downloaded from [https://www.python.org/downloads/](https://www.python.org/downloads/).
48
48
 
49
49
  ### Installing on mac and Linux
50
50
 
@@ -26,6 +26,7 @@ src/excel_list_transform/handle_csv.py
26
26
  src/excel_list_transform/handle_empty_column.py
27
27
  src/excel_list_transform/handle_excel.py
28
28
  src/excel_list_transform/num_named_conversion.py
29
+ src/excel_list_transform/py.typed
29
30
  src/excel_list_transform/rewrite_value.py
30
31
  src/excel_list_transform/str_to_enum.py
31
32
  src/excel_list_transform/transform_cmd.py
@@ -0,0 +1,8 @@
1
+ openpyxl>=3.1.5
2
+ types-openpyxl>=3.1.5.20240918
3
+ pylightxl>=1.61
4
+ XlsxWriter>=3.2.0
5
+ pip>=24.2
6
+ setuptools>=75.1.0
7
+ build>=1.2.2
8
+ wheel>=0.44.0
@@ -4,13 +4,13 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "excel-list-transform"
7
- version = "0.5"
7
+ version = "0.6.2"
8
8
  authors = [
9
9
  { name="Tom Björkholm", email="klausuler_linnet0q@icloud.com" },
10
10
  ]
11
11
  description = "Transform a list in excel or CSV"
12
12
  readme = "README_pypi.md"
13
- requires-python = ">=3.10.5"
13
+ requires-python = ">=3.12.6"
14
14
  classifiers = [
15
15
  "Programming Language :: Python :: 3",
16
16
  "License :: OSI Approved :: MIT License",
@@ -5,22 +5,22 @@ from setuptools import setup
5
5
 
6
6
  setup(
7
7
  name='excel-list-transform',
8
- version='0.5',
8
+ version='0.6.2',
9
9
  description='Transform a list in excel or CSV.',
10
10
  author='Tom Björkholm',
11
11
  author_email='klausuler_linnet0q@icloud.com',
12
- python_requires='>=3.10.5',
12
+ python_requires='>=3.12.6',
13
13
  packages=['excel_list_transform'],
14
14
  package_dir={'excel_list_transform': 'src/excel_list_transform'},
15
+ package_data={'excel_list_transform': ['src/py.typed']},
15
16
  install_requires=[
16
17
  'openpyxl >= 3.1.5',
17
- 'types-openpyxl >= 3.1.5.20240822',
18
+ 'types-openpyxl >= 3.1.5.20240918',
18
19
  'pylightxl >= 1.61',
19
20
  'XlsxWriter >= 3.2.0',
20
- 'pip >= 23.2',
21
- 'Pillow >= 10.0.1',
22
- 'setuptools >= 74.0.0',
23
- 'build >= 1.2.1',
21
+ 'pip >= 24.2',
22
+ 'setuptools >= 75.1.0',
23
+ 'build >= 1.2.2',
24
24
  'wheel>=0.44.0'
25
25
  ]
26
26
  )
@@ -11,9 +11,11 @@ import sys
11
11
  import csv
12
12
  from typing import Any, Optional, Type, TypeVar, Mapping, NamedTuple, Callable
13
13
  from enum import Enum, IntEnum
14
+ from tempfile import TemporaryFile
14
15
  from excel_list_transform.str_to_enum import string_to_enum_best_match
15
16
  from excel_list_transform.config_enums import RewriteKind
16
17
  from excel_list_transform.file_must_exist import file_must_exist
18
+ from excel_list_transform.commontypes import JsonType
17
19
 
18
20
 
19
21
  Keya = TypeVar('Keya', str, Enum, RewriteKind)
@@ -151,6 +153,21 @@ class Config():
151
153
  ret[key] = parse_c.func(value, **parse_c.args)
152
154
  return ret
153
155
 
156
+ def _def_vals_for_optional(self) -> dict[str, JsonType]:
157
+ """Get default values for optional config parameters.
158
+
159
+ Derived class shall override this method if it has
160
+ optional config parameters.
161
+ """
162
+ return {}
163
+
164
+ def _add_optional_configs(self, json_data: dict[str, JsonType]) -> None:
165
+ """Add optional config parameters to json data as needed."""
166
+ defval = self._def_vals_for_optional()
167
+ for key, value in defval.items():
168
+ if key not in json_data:
169
+ json_data[key] = value
170
+
154
171
  def parse_json(self, from_json_text: str,
155
172
  ok_to_use_defaults: bool = False) -> None:
156
173
  """Parse a string of JSON data and set self to that."""
@@ -171,6 +188,7 @@ class Config():
171
188
  if isinstance(exc, json.JSONDecodeError):
172
189
  raise ConfigBadJson(msg=msg, doc=exc.doc, pos=exc.pos) from exc
173
190
  raise ConfigBadJson(msg=msg, doc='', pos=0) from exc
191
+ self._add_optional_configs(data)
174
192
  self_keys = [i for i in vars(self).keys() if not
175
193
  callable(getattr(self, i)) and not i.startswith('_')]
176
194
  self.check_key_match(self_keys, data.keys(), ok_to_use_defaults)
@@ -206,11 +224,12 @@ class Config():
206
224
  file.write(text)
207
225
 
208
226
  @staticmethod
209
- def get_csv_dialect(name: Optional[str], delimiter: Optional[str], # pylint: disable=too-many-arguments, line-too-long, too-many-branches # noqa: E501
210
- quoting: Optional[str], quotechar: Optional[str], # pylint: disable=too-many-arguments, line-too-long, too-many-branches # noqa: E501
211
- lineterminator: Optional[str], # pylint: disable=too-many-arguments, line-too-long, too-many-branches # noqa: E501
212
- escapechar: Optional[str] # pylint: disable=too-many-arguments, line-too-long, too-many-branches # noqa: E501
213
- ) -> type[csv.Dialect]: # pylint: disable=too-many-arguments, line-too-long, too-many-branches # noqa: E501
227
+ def get_csv_dialect(*, name: Optional[str], # pylint: disable=too-many-arguments, line-too-long, too-many-branches # noqa: E501
228
+ delimiter: Optional[str],
229
+ quoting: Optional[str], quotechar: Optional[str],
230
+ lineterminator: Optional[str],
231
+ escapechar: Optional[str]
232
+ ) -> type[csv.Dialect]:
214
233
  """Get CSV dialect object matching arguments."""
215
234
  ret: Optional[type[csv.Dialect]] = None
216
235
  if name is None or name.lower() == 'csv.excel':
@@ -356,3 +375,22 @@ class Config():
356
375
  return ParseConverter(result_type=enum_type,
357
376
  func=string_to_enum_best_match,
358
377
  args={'num_type': enum_type})
378
+
379
+ @staticmethod
380
+ def valid_char_encoding(enc: str) -> bool:
381
+ """Check if character encoding is valid."""
382
+ try:
383
+ with TemporaryFile(mode='w', encoding=enc) as _:
384
+ pass
385
+ except LookupError as exc:
386
+ if 'unknown encoding' in str(exc):
387
+ return False
388
+ raise exc # pragma: no cover
389
+ return True
390
+
391
+ @staticmethod
392
+ def check_char_encoding(enc: str) -> None:
393
+ """Report error and exit if character encoding is not valid."""
394
+ if not Config.valid_char_encoding(enc=enc):
395
+ print(f'{enc} is not a recognized encoding', file=sys.stderr)
396
+ sys.exit(1)
@@ -15,6 +15,7 @@ from excel_list_transform.config import Config, ParseConverter
15
15
  from excel_list_transform.config_enums import FileType, SplitWhere, \
16
16
  ExcelLib, RewriteKind, CaseSensitivity, ColumnRef
17
17
  from excel_list_transform.str_to_enum import string_to_enum_best_match
18
+ from excel_list_transform.commontypes import JsonType
18
19
 
19
20
 
20
21
  CsvSpec: TypeAlias = dict[str, Optional[str]]
@@ -59,7 +60,7 @@ class ColInfo(NamedTuple, Generic[Column]):
59
60
  class ConfigExcelListTransform(Config, Generic[Column]): # pylint: disable=too-many-instance-attributes, line-too-long # noqa: E501
60
61
  """Class with configuration for excel list transform."""
61
62
 
62
- def __init__(self, col_ref: ColumnRef, # pylint: disable=too-many-arguments # noqa: E501
63
+ def __init__(self, *, col_ref: ColumnRef, # pylint: disable=too-many-arguments # noqa: E501
63
64
  colinfo: ColInfo[Column], tinfo: Column,
64
65
  from_json_text: Optional[str] = None,
65
66
  from_json_filename: Optional[str] = None) -> None:
@@ -78,6 +79,8 @@ class ConfigExcelListTransform(Config, Generic[Column]): # pylint: disable=too-
78
79
  'quotechar': '"',
79
80
  'lineterminator': None,
80
81
  'escapechar': None}
82
+ self.in_csv_encoding = 'utf_8_sig'
83
+ self.out_csv_encoding = 'utf-8'
81
84
  self.in_type: FileType = FileType.EXCEL
82
85
  self.in_excel_library: ExcelLib = ExcelLib.PYLIGHTXL
83
86
  self.out_excel_library: ExcelLib = ExcelLib.PYLIGHTXL
@@ -122,6 +125,8 @@ class ConfigExcelListTransform(Config, Generic[Column]): # pylint: disable=too-
122
125
  self._check_no_duplicate_single(self.s6_insert_columns,
123
126
  's6_insert_columns', colinfo.tinfo)
124
127
  self.check_rewrite_configs(coltype=type(colinfo.tinfo))
128
+ self.check_char_encoding(self.in_csv_encoding)
129
+ self.check_char_encoding(self.out_csv_encoding)
125
130
 
126
131
  def get_out_csv_dialect(self) -> type[Dialect]:
127
132
  """Get CSV dialect for output file."""
@@ -134,7 +139,12 @@ class ConfigExcelListTransform(Config, Generic[Column]): # pylint: disable=too-
134
139
  return self.get_csv_dialect(**self.in_csv_dialect)
135
140
 
136
141
  def sort_sx_hook(self) -> None:
137
- """Sort s[0-9]_ as needed as needed (hook)."""
142
+ """Sort s[0-9]_ as needed (hook)."""
143
+
144
+ def _def_vals_for_optional(self) -> dict[str, JsonType]:
145
+ """Provide default values for optional encoding."""
146
+ return {'in_csv_encoding': 'utf_8_sig',
147
+ 'out_csv_encoding': 'utf-8'}
138
148
 
139
149
  @staticmethod
140
150
  def _duplicates_not_allowed(expanded_data: list[Column],
@@ -16,7 +16,10 @@ def generate_syntax_txt(filename: str, example_description: str,
16
16
  https://en.wikipedia.org/wiki/JSON
17
17
  The keywords and the nesting is important. The order of keywords
18
18
  have no significance (the examples use alphabetical order).
19
- Indentation and line breaks hanve no significance.
19
+ Indentation and line breaks have no significance.
20
+
21
+ The encoding for the configuration file must be UTF-8.
22
+ (US-ACII is a subset of UTF-8.)
20
23
 
21
24
  It is recommended that you let the command generate a configuration
22
25
  file and then edit that file to match your needs. It is NOT recommended
@@ -77,6 +80,16 @@ def generate_syntax_txt(filename: str, example_description: str,
77
80
  are read and written. They are always needed in the configuration
78
81
  file, but are not used if the input and output are excel files.
79
82
 
83
+ Comma separated values files might have different encoding for
84
+ the text in the file. https://en.wikipedia.org/wiki/Character_encoding
85
+ This is specified with "in_csv_encoding" and "out_csv_encoding".
86
+ Unless you know that you need another encoding leave these as
87
+ in the generated example configuration. (In version 0.5 these
88
+ configuration parameters are missing. To be compatible with 0.5
89
+ configuration files "in_csv_encoding" defaults to "utf_8_sig"
90
+ and "out_csv_encoding" defaults to "utf-8" if missing in the
91
+ configutation file.)
92
+
80
93
 
81
94
  Column manipulation
82
95
  ====================
@@ -12,12 +12,12 @@ from excel_list_transform.num_named_conversion import named_cols_from_num_cols
12
12
  from excel_list_transform.commontypes import NumData, NumDataSeq, NameData
13
13
 
14
14
 
15
- def read_csv_num(filename: str, dialect: type[Dialect],
15
+ def read_csv_num(filename: str, dialect: type[Dialect], encoding: str,
16
16
  max_column_read: int) -> NumData:
17
17
  """Read a csv file in specified dialect (numbered columns)."""
18
18
  res: NumDataSeq = []
19
19
  with open(file=filename, mode="r",
20
- encoding='utf_8_sig', newline='') as cfile:
20
+ encoding=encoding, newline='') as cfile:
21
21
  creader = reader(cfile, dialect=dialect)
22
22
  for row in creader:
23
23
  res.append(list(row)[:max_column_read])
@@ -25,26 +25,28 @@ def read_csv_num(filename: str, dialect: type[Dialect],
25
25
 
26
26
 
27
27
  def read_csv_named_use_num(filename: str, dialect: type[Dialect],
28
+ encoding: str,
28
29
  max_column_read: int) -> NameData:
29
30
  """Read a csv file using numbered columns for named columns."""
30
- data = read_csv_num(filename=filename, dialect=dialect,
31
+ data = read_csv_num(filename=filename, dialect=dialect, encoding=encoding,
31
32
  max_column_read=max_column_read)
32
33
  return named_cols_from_num_cols(data=data, filename=filename)
33
34
 
34
35
 
35
- def read_csv_named(filename: str, dialect: type[Dialect],
36
+ def read_csv_named(filename: str, dialect: type[Dialect], encoding: str,
36
37
  max_column_read: int) -> NameData:
37
38
  """Read a csv file in specified dialect (named columns)."""
38
39
  res = []
39
40
  first_line: bool = True
40
41
  with open(file=filename, mode="r",
41
- encoding='utf_8_sig', newline='') as cfile:
42
+ encoding=encoding, newline='') as cfile:
42
43
  creader = DictReader(cfile, dialect=dialect)
43
44
  for row in creader:
44
45
  if first_line:
45
46
  if len(row) > max_column_read:
46
47
  return read_csv_named_use_num(filename=filename,
47
48
  dialect=dialect,
49
+ encoding=encoding,
48
50
  max_column_read= # noqa: E251, E501
49
51
  max_column_read)
50
52
  first_line = False
@@ -52,20 +54,21 @@ def read_csv_named(filename: str, dialect: type[Dialect],
52
54
  return handle_empty_column_in_dict_lst(res)
53
55
 
54
56
 
55
- def write_csv_num(data: NumData,
56
- filename: str, dialect: type[Dialect]) -> None:
57
+ def write_csv_num(data: NumData, filename: str, dialect: type[Dialect],
58
+ encoding: str) -> None:
57
59
  """Write a csv file in specified dialect."""
58
- with open(file=filename, mode="w", encoding='utf8', newline='') as cfile:
60
+ with open(file=filename, mode="w", encoding=encoding,
61
+ newline='') as cfile:
59
62
  cwriter = writer(cfile, dialect=dialect)
60
63
  for row in data:
61
64
  cwriter.writerow(row)
62
65
 
63
66
 
64
- def write_csv_named(data: NameData,
65
- filename: str, dialect: type[Dialect],
66
- column_order: list[str]) -> None:
67
+ def write_csv_named(data: NameData, filename: str, dialect: type[Dialect],
68
+ encoding: str, column_order: list[str]) -> None:
67
69
  """Write a csv file in specified dialect."""
68
- with open(file=filename, mode="w", encoding='utf8', newline='') as cfile:
70
+ with open(file=filename, mode="w", encoding=encoding,
71
+ newline='') as cfile:
69
72
  cwriter = DictWriter(f=cfile, dialect=dialect, fieldnames=column_order,
70
73
  extrasaction='ignore')
71
74
  cwriter.writeheader()
@@ -0,0 +1,2 @@
1
+ # Copyright (c) 2024 Tom Björkholm
2
+ # MIT License
@@ -119,6 +119,7 @@ def transform_named_files_name(infilename: str, outfilename: str,
119
119
  indata = None
120
120
  if cfgn.in_type == FileType.CSV:
121
121
  indata = read_csv_named(infilename, cfgn.get_in_csv_dialect(),
122
+ encoding=cfgn.in_csv_encoding,
122
123
  max_column_read=cfgn.max_column_read)
123
124
  else:
124
125
  indata = read_excel_named(infilename,
@@ -128,6 +129,7 @@ def transform_named_files_name(infilename: str, outfilename: str,
128
129
  if cfgn.out_type == FileType.CSV:
129
130
  write_csv_named(data=outdata, filename=outfilename,
130
131
  dialect=cfgn.get_out_csv_dialect(),
132
+ encoding=cfgn.out_csv_encoding,
131
133
  column_order=cfgn.s8_column_order)
132
134
  else:
133
135
  write_excel_named(data=outdata, filename=outfilename,
@@ -142,6 +142,7 @@ def transform_named_files_num(infilename: str, outfilename: str,
142
142
  indata = None
143
143
  if cfgn.in_type == FileType.CSV:
144
144
  indata = read_csv_num(infilename, cfgn.get_in_csv_dialect(),
145
+ encoding=cfgn.in_csv_encoding,
145
146
  max_column_read=cfgn.max_column_read)
146
147
  else:
147
148
  indata = read_excel_num(infilename,
@@ -150,7 +151,8 @@ def transform_named_files_num(infilename: str, outfilename: str,
150
151
  outdata = transform_data_num(indata=indata, cfg=cfgn)
151
152
  if cfgn.out_type == FileType.CSV:
152
153
  write_csv_num(data=outdata, filename=outfilename,
153
- dialect=cfgn.get_out_csv_dialect())
154
+ dialect=cfgn.get_out_csv_dialect(),
155
+ encoding=cfgn.out_csv_encoding)
154
156
  else:
155
157
  write_excel_num(data=outdata, filename=outfilename,
156
158
  excel_lib=cfgn.out_excel_library)
@@ -1,9 +0,0 @@
1
- openpyxl>=3.1.5
2
- types-openpyxl>=3.1.5.20240822
3
- pylightxl>=1.61
4
- XlsxWriter>=3.2.0
5
- pip>=23.2
6
- Pillow>=10.0.1
7
- setuptools>=74.0.0
8
- build>=1.2.1
9
- wheel>=0.44.0