tableio 0.8__tar.gz → 0.9__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.
- {tableio-0.8/tableio.egg-info → tableio-0.9}/PKG-INFO +3 -3
- {tableio-0.8 → tableio-0.9}/README.md +2 -2
- {tableio-0.8 → tableio-0.9}/README_pypi.md +2 -2
- {tableio-0.8 → tableio-0.9}/pyproject.toml +1 -1
- {tableio-0.8 → tableio-0.9}/setup.py +1 -1
- {tableio-0.8 → tableio-0.9}/src/tableio/access_capability.py +23 -10
- {tableio-0.8 → tableio-0.9}/src/tableio/config_data_apply.py +52 -12
- {tableio-0.8 → tableio-0.9/tableio.egg-info}/PKG-INFO +3 -3
- {tableio-0.8 → tableio-0.9}/LICENSE.txt +0 -0
- {tableio-0.8 → tableio-0.9}/setup.cfg +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/__init__.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/_archive_rewrite.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/border_helper.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/capability.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/color.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/config_data.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/config_data_describe.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/config_data_error.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/config_data_validate.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/factory.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/optional_args.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/py.typed +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/reg_pkg_formats.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/tableio.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/tableio_csv.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/tableio_excel_openpyxl.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/tableio_excel_pylightxl.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/tableio_excel_xlsxwriter.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/tableio_excelbased.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/tableio_mformat.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/tableio_mformatbased.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/tableio_ods_odfdo.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/tableio_spreadsheetbased.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/tableio_textbased.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/tableio_types.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/value_type.py +0 -0
- {tableio-0.8 → tableio-0.9}/src/tableio/valueconversion.py +0 -0
- {tableio-0.8 → tableio-0.9}/tableio.egg-info/SOURCES.txt +0 -0
- {tableio-0.8 → tableio-0.9}/tableio.egg-info/dependency_links.txt +0 -0
- {tableio-0.8 → tableio-0.9}/tableio.egg-info/requires.txt +0 -0
- {tableio-0.8 → tableio-0.9}/tableio.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tableio
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9
|
|
4
4
|
Summary: Uniform way to write table data to and read from different file formats
|
|
5
5
|
Author: Tom Björkholm
|
|
6
6
|
Author-email: Tom Björkholm <klausuler_linnet0q@icloud.com>
|
|
@@ -137,9 +137,9 @@ a better start by reading the examples.
|
|
|
137
137
|
|
|
138
138
|
## Test summary
|
|
139
139
|
|
|
140
|
-
- Test result:
|
|
140
|
+
- Test result: 1344 passed in 20s
|
|
141
141
|
- No flake8 warnings.
|
|
142
142
|
- No mypy errors found.
|
|
143
143
|
- No python layout warnings.
|
|
144
|
-
- Built version(s): 0.
|
|
144
|
+
- Built version(s): 0.9
|
|
145
145
|
- Build and test using Python 3.14.4
|
|
@@ -93,9 +93,9 @@ information about the build system. This README can also be viewed at
|
|
|
93
93
|
|
|
94
94
|
## Test summary
|
|
95
95
|
|
|
96
|
-
- Test result:
|
|
96
|
+
- Test result: 1344 passed in 20s
|
|
97
97
|
- No flake8 warnings.
|
|
98
98
|
- No mypy errors found.
|
|
99
99
|
- No python layout warnings.
|
|
100
|
-
- Built version(s): 0.
|
|
100
|
+
- Built version(s): 0.9
|
|
101
101
|
- Build and test using Python 3.14.4
|
|
@@ -109,9 +109,9 @@ a better start by reading the examples.
|
|
|
109
109
|
|
|
110
110
|
## Test summary
|
|
111
111
|
|
|
112
|
-
- Test result:
|
|
112
|
+
- Test result: 1344 passed in 20s
|
|
113
113
|
- No flake8 warnings.
|
|
114
114
|
- No mypy errors found.
|
|
115
115
|
- No python layout warnings.
|
|
116
|
-
- Built version(s): 0.
|
|
116
|
+
- Built version(s): 0.9
|
|
117
117
|
- Build and test using Python 3.14.4
|
|
@@ -4,16 +4,22 @@
|
|
|
4
4
|
# Copyright (c) 2026 Tom Björkholm
|
|
5
5
|
# MIT License
|
|
6
6
|
|
|
7
|
-
import
|
|
7
|
+
from enum import Enum, auto
|
|
8
8
|
from typing import NoReturn, TextIO
|
|
9
9
|
|
|
10
10
|
from tableio.capability import CAP_NEEDED, Capabilities
|
|
11
11
|
from tableio.tableio_types import FileAccess
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
class NoErrorOutput(Enum):
|
|
15
|
+
"""Text stream marker when helper errors should not be printed."""
|
|
16
|
+
|
|
17
|
+
NO_OUTPUT = auto()
|
|
18
|
+
"""Text stream marker when helper errors should not be printed."""
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
NO_ERROR_OUTPUT = NoErrorOutput.NO_OUTPUT
|
|
22
|
+
"""Text stream marker used when helper errors should not be printed."""
|
|
17
23
|
|
|
18
24
|
|
|
19
25
|
class InsufficientCapabilities(ValueError):
|
|
@@ -32,13 +38,17 @@ class InsufficientCapabilities(ValueError):
|
|
|
32
38
|
super().__init__(message)
|
|
33
39
|
|
|
34
40
|
|
|
35
|
-
def _raise_error(error_file: TextIO
|
|
41
|
+
def _raise_error(error_file: TextIO | NoErrorOutput,
|
|
42
|
+
error: Exception) -> NoReturn:
|
|
36
43
|
"""Write an error message and raise the error."""
|
|
44
|
+
if isinstance(error_file, NoErrorOutput):
|
|
45
|
+
raise error
|
|
37
46
|
error_file.write(str(error) + '\n')
|
|
38
47
|
raise error
|
|
39
48
|
|
|
40
49
|
|
|
41
|
-
def _check_access_value(file_access: FileAccess,
|
|
50
|
+
def _check_access_value(file_access: FileAccess,
|
|
51
|
+
error_file: TextIO | NoErrorOutput) -> None:
|
|
42
52
|
"""Raise if file access is not a supported FileAccess value."""
|
|
43
53
|
if not isinstance(file_access, FileAccess):
|
|
44
54
|
error = TypeError('file_access must be a FileAccess value.')
|
|
@@ -50,7 +60,7 @@ def _check_access_value(file_access: FileAccess, error_file: TextIO) -> None:
|
|
|
50
60
|
|
|
51
61
|
|
|
52
62
|
def _check_capabilities_value(capabilities: Capabilities,
|
|
53
|
-
error_file: TextIO) -> None:
|
|
63
|
+
error_file: TextIO | NoErrorOutput) -> None:
|
|
54
64
|
"""Raise if capabilities is not a Capabilities object."""
|
|
55
65
|
if not isinstance(capabilities, Capabilities):
|
|
56
66
|
error = TypeError('capabilities must be a Capabilities object.')
|
|
@@ -58,7 +68,8 @@ def _check_capabilities_value(capabilities: Capabilities,
|
|
|
58
68
|
|
|
59
69
|
|
|
60
70
|
def access_capabilities(file_access: FileAccess,
|
|
61
|
-
error_file: TextIO
|
|
71
|
+
error_file: TextIO | NoErrorOutput =
|
|
72
|
+
NO_ERROR_OUTPUT) -> Capabilities:
|
|
62
73
|
"""Return the capabilities implied by a file access mode.
|
|
63
74
|
|
|
64
75
|
Args:
|
|
@@ -80,7 +91,8 @@ def access_capabilities(file_access: FileAccess,
|
|
|
80
91
|
|
|
81
92
|
def add_access_capabilities(file_access: FileAccess,
|
|
82
93
|
capabilities: Capabilities,
|
|
83
|
-
error_file: TextIO
|
|
94
|
+
error_file: TextIO | NoErrorOutput =
|
|
95
|
+
NO_ERROR_OUTPUT) \
|
|
84
96
|
-> Capabilities:
|
|
85
97
|
"""Return capabilities with file access requirements added.
|
|
86
98
|
|
|
@@ -135,7 +147,8 @@ def _access_error_message(file_access: FileAccess) -> str:
|
|
|
135
147
|
|
|
136
148
|
def check_access_capabilities(file_access: FileAccess,
|
|
137
149
|
capabilities: Capabilities,
|
|
138
|
-
error_file: TextIO
|
|
150
|
+
error_file: TextIO | NoErrorOutput =
|
|
151
|
+
NO_ERROR_OUTPUT) -> None:
|
|
139
152
|
"""Raise if capabilities are not enough for requested access mode.
|
|
140
153
|
|
|
141
154
|
Args:
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# Copyright (c) 2026 Tom Björkholm
|
|
5
5
|
# MIT License
|
|
6
6
|
|
|
7
|
-
from typing import Callable, Optional, TypeVar, cast
|
|
7
|
+
from typing import Callable, NoReturn, Optional, TypeVar, cast
|
|
8
8
|
|
|
9
9
|
from mformat.mformat import PathLike
|
|
10
10
|
from tableio.access_capability import add_access_capabilities
|
|
@@ -24,15 +24,14 @@ _FORMAT_PRIORITY = ('excel', 'ods', 'csv')
|
|
|
24
24
|
_ValueT = TypeVar('_ValueT')
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
def _config_error(name: str, message: str) ->
|
|
27
|
+
def _config_error(name: str, message: str) -> NoReturn:
|
|
28
28
|
"""Raise one structured configuration error."""
|
|
29
29
|
raise ConfigError((ConfigIssue(name, message),))
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
def _check_default_input(capabilities: Capabilities, file_access: FileAccess,
|
|
33
33
|
format_name: Optional[str],
|
|
34
|
-
implementation: Optional[str]
|
|
35
|
-
include_all_options: bool) -> None:
|
|
34
|
+
implementation: Optional[str]) -> None:
|
|
36
35
|
"""Validate runtime values used for default selection."""
|
|
37
36
|
if not isinstance(capabilities, Capabilities):
|
|
38
37
|
_config_error('capabilities', 'must be a Capabilities object.')
|
|
@@ -42,8 +41,15 @@ def _check_default_input(capabilities: Capabilities, file_access: FileAccess,
|
|
|
42
41
|
_config_error('format_name', 'must be a string or None.')
|
|
43
42
|
if implementation is not None and not isinstance(implementation, str):
|
|
44
43
|
_config_error('implementation', 'must be a string or None.')
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _check_default_flags(include_all_options: bool,
|
|
47
|
+
impl_in_cfg: Optional[bool]) -> None:
|
|
48
|
+
"""Validate flags used for default selection."""
|
|
45
49
|
if not isinstance(include_all_options, bool):
|
|
46
50
|
_config_error('include_all_options', 'must be a bool.')
|
|
51
|
+
if impl_in_cfg is not None and not isinstance(impl_in_cfg, bool):
|
|
52
|
+
_config_error('impl_in_cfg', 'must be a bool or None.')
|
|
47
53
|
|
|
48
54
|
|
|
49
55
|
def _registered_formats_by_lower() -> dict[str, str]:
|
|
@@ -103,7 +109,6 @@ def _best_default_names(capabilities: Capabilities, format_name: Optional[str],
|
|
|
103
109
|
return selected_format, selected_impl
|
|
104
110
|
name = 'implementation' if implementation is not None else 'format_name'
|
|
105
111
|
_config_error(name, 'does not match registered TableIO backends.')
|
|
106
|
-
raise AssertionError('Unreachable default selection failure.')
|
|
107
112
|
|
|
108
113
|
|
|
109
114
|
def _base_arg_items(config: ConfigData) -> list[tuple[str, str, object]]:
|
|
@@ -184,7 +189,8 @@ def _filtered_args(config: ConfigData, capabilities: Optional[Capabilities],
|
|
|
184
189
|
return filtered
|
|
185
190
|
|
|
186
191
|
|
|
187
|
-
def _all_option_config(format_name: str,
|
|
192
|
+
def _all_option_config(format_name: str,
|
|
193
|
+
implementation: Optional[str]) -> ConfigData:
|
|
188
194
|
"""Return a configuration object with all options visible."""
|
|
189
195
|
csv = CsvConfigData(dialect=CsvDialect.UNIX, delimiter=',', quoting='all',
|
|
190
196
|
quotechar='"', lineterminator='\n', escapechar='\\')
|
|
@@ -198,10 +204,21 @@ def _all_option_config(format_name: str, implementation: str) -> ConfigData:
|
|
|
198
204
|
html=html, latex=latex)
|
|
199
205
|
|
|
200
206
|
|
|
201
|
-
def
|
|
207
|
+
def _include_default_impl(implementation: Optional[str],
|
|
208
|
+
include_all_options: bool,
|
|
209
|
+
impl_in_cfg: Optional[bool]) -> bool:
|
|
210
|
+
"""Return true if the default config should pin implementation."""
|
|
211
|
+
if impl_in_cfg is not None:
|
|
212
|
+
return impl_in_cfg
|
|
213
|
+
return implementation is not None or include_all_options
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
# pylint: disable-next=too-many-arguments
|
|
217
|
+
def tio_config_default(capabilities: Capabilities, file_access: FileAccess, *,
|
|
202
218
|
format_name: Optional[str] = None,
|
|
203
219
|
implementation: Optional[str] = None,
|
|
204
|
-
include_all_options: bool = False
|
|
220
|
+
include_all_options: bool = False,
|
|
221
|
+
impl_in_cfg: Optional[bool] = None) -> ConfigData:
|
|
205
222
|
"""Return recommended default configuration data.
|
|
206
223
|
|
|
207
224
|
Default format and implementation selection first prefers implementations
|
|
@@ -211,6 +228,17 @@ def tio_config_default(capabilities: Capabilities, file_access: FileAccess,
|
|
|
211
228
|
If several implementations of the selected format match equally well,
|
|
212
229
|
their TableIO implementation priority is used.
|
|
213
230
|
|
|
231
|
+
Usually it is better to not include the implementation name in the
|
|
232
|
+
configuration, as that allows the TableIO library to choose the best
|
|
233
|
+
implementation based on the capabilities and file access at runtime.
|
|
234
|
+
If you want to include the implementation name in the configuration,
|
|
235
|
+
you can set the impl_in_cfg parameter to True. If you set it to False,
|
|
236
|
+
the implementation name will always be omitted from the configuration.
|
|
237
|
+
If you set it to None, the implementation name will normally be omitted
|
|
238
|
+
from the configuration, but if include_all_options is True or if
|
|
239
|
+
implementation was explicitly provided, the implementation name will be
|
|
240
|
+
included.
|
|
241
|
+
|
|
214
242
|
Args:
|
|
215
243
|
capabilities: Runtime capabilities the application intends to use.
|
|
216
244
|
file_access: Runtime file access requested by the application.
|
|
@@ -218,12 +246,21 @@ def tio_config_default(capabilities: Capabilities, file_access: FileAccess,
|
|
|
218
246
|
implementation: Optional preferred implementation name.
|
|
219
247
|
include_all_options: Include visible non-None values for all
|
|
220
248
|
configuration options, for teaching and configuration templates.
|
|
249
|
+
impl_in_cfg: Optional flag to include the implementation name in the
|
|
250
|
+
configuration. If None, the implementation name will normally be
|
|
251
|
+
omitted from the configuration, but if include_all_options is True
|
|
252
|
+
or if implementation was explicitly provided, the implementation
|
|
253
|
+
name will be included. If True, the implementation name will be
|
|
254
|
+
included in the configuration. If False, the implementation name
|
|
255
|
+
will always be omitted from the configuration.
|
|
221
256
|
Returns:
|
|
222
257
|
A configuration object containing durable user choices only.
|
|
223
258
|
"""
|
|
224
259
|
_check_default_input(capabilities, file_access, format_name,
|
|
225
|
-
implementation
|
|
260
|
+
implementation)
|
|
261
|
+
_check_default_flags(include_all_options, impl_in_cfg)
|
|
226
262
|
match_caps = add_access_capabilities(file_access, capabilities)
|
|
263
|
+
selected_impl: Optional[str] = None
|
|
227
264
|
selected_format, selected_impl = _best_default_names(match_caps,
|
|
228
265
|
format_name,
|
|
229
266
|
implementation)
|
|
@@ -231,6 +268,9 @@ def tio_config_default(capabilities: Capabilities, file_access: FileAccess,
|
|
|
231
268
|
selected_format = format_name
|
|
232
269
|
if implementation is not None:
|
|
233
270
|
selected_impl = implementation
|
|
271
|
+
if not _include_default_impl(implementation, include_all_options,
|
|
272
|
+
impl_in_cfg):
|
|
273
|
+
selected_impl = None
|
|
234
274
|
if include_all_options:
|
|
235
275
|
config = _all_option_config(selected_format, selected_impl)
|
|
236
276
|
else:
|
|
@@ -341,9 +381,9 @@ def tio_config_trim(config: ConfigData,
|
|
|
341
381
|
filtered_names),
|
|
342
382
|
line_length=_kept(config.line_length, 'line_length',
|
|
343
383
|
filtered_names),
|
|
344
|
-
table_max_line_length=_kept(
|
|
345
|
-
|
|
346
|
-
|
|
384
|
+
table_max_line_length=_kept(config.table_max_line_length,
|
|
385
|
+
'table_max_line_length',
|
|
386
|
+
filtered_names),
|
|
347
387
|
table_alignment=_kept(config.table_alignment,
|
|
348
388
|
'table_alignment', filtered_names),
|
|
349
389
|
csv=csv, html=html, latex=latex)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tableio
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9
|
|
4
4
|
Summary: Uniform way to write table data to and read from different file formats
|
|
5
5
|
Author: Tom Björkholm
|
|
6
6
|
Author-email: Tom Björkholm <klausuler_linnet0q@icloud.com>
|
|
@@ -137,9 +137,9 @@ a better start by reading the examples.
|
|
|
137
137
|
|
|
138
138
|
## Test summary
|
|
139
139
|
|
|
140
|
-
- Test result:
|
|
140
|
+
- Test result: 1344 passed in 20s
|
|
141
141
|
- No flake8 warnings.
|
|
142
142
|
- No mypy errors found.
|
|
143
143
|
- No python layout warnings.
|
|
144
|
-
- Built version(s): 0.
|
|
144
|
+
- Built version(s): 0.9
|
|
145
145
|
- Build and test using Python 3.14.4
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|