tableio 0.1__tar.gz → 0.3__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 (37) hide show
  1. {tableio-0.1/tableio.egg-info → tableio-0.3}/PKG-INFO +62 -20
  2. {tableio-0.1 → tableio-0.3}/README.md +14 -19
  3. tableio-0.3/README_pypi.md +123 -0
  4. {tableio-0.1 → tableio-0.3}/pyproject.toml +2 -3
  5. {tableio-0.1 → tableio-0.3}/setup.py +6 -3
  6. tableio-0.3/src/tableio/__init__.py +47 -0
  7. {tableio-0.1 → tableio-0.3}/src/tableio/capability.py +94 -1
  8. {tableio-0.1 → tableio-0.3}/src/tableio/factory.py +46 -3
  9. {tableio-0.1 → tableio-0.3}/src/tableio/reg_pkg_formats.py +7 -1
  10. {tableio-0.1 → tableio-0.3}/src/tableio/tableio.py +354 -168
  11. {tableio-0.1 → tableio-0.3}/src/tableio/tableio_csv.py +26 -37
  12. tableio-0.3/src/tableio/tableio_excel_openpyxl.py +286 -0
  13. tableio-0.3/src/tableio/tableio_excel_pylightxl.py +709 -0
  14. tableio-0.3/src/tableio/tableio_excel_xlsxwriter.py +407 -0
  15. {tableio-0.1 → tableio-0.3}/src/tableio/tableio_excelbased.py +49 -2
  16. {tableio-0.1 → tableio-0.3}/src/tableio/tableio_mformat.py +1 -1
  17. {tableio-0.1 → tableio-0.3}/src/tableio/tableio_mformatbased.py +32 -37
  18. tableio-0.3/src/tableio/tableio_ods_odfdo.py +482 -0
  19. tableio-0.3/src/tableio/tableio_spreadsheetbased.py +783 -0
  20. tableio-0.3/src/tableio/tableio_types.py +61 -0
  21. {tableio-0.1 → tableio-0.3}/src/tableio/value_type.py +2 -0
  22. tableio-0.3/src/tableio/valueconversion.py +397 -0
  23. {tableio-0.1 → tableio-0.3/tableio.egg-info}/PKG-INFO +62 -20
  24. {tableio-0.1 → tableio-0.3}/tableio.egg-info/SOURCES.txt +5 -0
  25. {tableio-0.1 → tableio-0.3}/tableio.egg-info/requires.txt +4 -1
  26. tableio-0.1/README_pypi.md +0 -83
  27. tableio-0.1/src/tableio/__init__.py +0 -6
  28. tableio-0.1/src/tableio/tableio_excel_openpyxl.py +0 -630
  29. tableio-0.1/src/tableio/tableio_spreadsheetbased.py +0 -46
  30. {tableio-0.1 → tableio-0.3}/LICENSE.txt +0 -0
  31. {tableio-0.1 → tableio-0.3}/setup.cfg +0 -0
  32. {tableio-0.1 → tableio-0.3}/src/tableio/color.py +0 -0
  33. {tableio-0.1 → tableio-0.3}/src/tableio/optional_args.py +0 -0
  34. {tableio-0.1 → tableio-0.3}/src/tableio/py.typed +0 -0
  35. {tableio-0.1 → tableio-0.3}/src/tableio/tableio_textbased.py +0 -0
  36. {tableio-0.1 → tableio-0.3}/tableio.egg-info/dependency_links.txt +0 -0
  37. {tableio-0.1 → tableio-0.3}/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.1
3
+ Version: 0.3
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>
@@ -8,17 +8,19 @@ License-Expression: MIT
8
8
  Project-URL: Source code, https://bitbucket.org/tom-bjorkholm/table-io
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: Operating System :: OS Independent
11
- Classifier: Development Status :: 2 - Pre-Alpha
12
11
  Requires-Python: >=3.12
13
12
  Description-Content-Type: text/markdown
14
13
  License-File: LICENSE.txt
15
14
  Requires-Dist: pip>=26.0.1
16
15
  Requires-Dist: setuptools>=82.0.1
17
- Requires-Dist: build>=1.4.0
16
+ Requires-Dist: build>=1.4.2
18
17
  Requires-Dist: wheel>=0.46.3
19
18
  Requires-Dist: mformat-ext>=0.6
20
19
  Requires-Dist: openpyxl>=3.1.5
21
20
  Requires-Dist: types-openpyxl>=3.1.5.20260322
21
+ Requires-Dist: odfdo>=3.22.3
22
+ Requires-Dist: xlsxwriter>=3.2.9
23
+ Requires-Dist: pylightxl>=1.61
22
24
  Dynamic: author
23
25
  Dynamic: license-file
24
26
  Dynamic: requires-dist
@@ -30,9 +32,15 @@ The tableio package contains a number of classes providing a uniform way for
30
32
  a python program to write table data (rows of columns) to and read table data
31
33
  from a number of different common file formats.
32
34
 
33
- The primary intended use is for text output from a python program, where the
34
- programmer would like the user to be able to select the input and output file
35
- formats.
35
+ An increasing number of users want output from programs to be in a format
36
+ like a spreadsheet, and not the old fashoned raw text files. Similarly,
37
+ many users want the data they feed into programs to be in a particular format
38
+ (like a spreadsheet). The tableio package tries to make it easier for the
39
+ programmer to fullfil requests like that.
40
+
41
+ The primary intended use is for data table output from a python program
42
+ and data table input to a python program, where the programmer would like
43
+ the user to be able to select the input and output file formats.
36
44
 
37
45
  The support for spreadsheets is for reading and writing data. There is no
38
46
  intention to support reading or writing formulas. There is no support for
@@ -40,10 +48,6 @@ running calculations in the spreadsheets (although nothing will stop a
40
48
  receiver of a spreadsheet created by tableio package to manually add
41
49
  formulas in the received spreadsheet).
42
50
 
43
- ## Early design phase
44
-
45
- This project is in an early design phase. This means that major changes to the APIs are still expected.
46
-
47
51
  ## Installing tableio
48
52
 
49
53
  ### Installing tableio on mac and Linux
@@ -66,24 +70,60 @@ The currently supported formats are:
66
70
  |-------------|----------------|-----------|----------|
67
71
  | CSV | csv | yes | yes |
68
72
  | Excel | OpenPyXL | yes | yes |
73
+ | Excel | XlsxWriter | yes | - |
74
+ | Excel | pylightxl | yes | yes |
75
+ | ODS | odfdo | yes | yes |
69
76
  | HTML | mformat | yes | - |
70
77
  | LaTeX | mformat | yes | - |
71
78
  | docx | mformat | yes | - |
72
79
  | md | mformat | yes | - |
73
80
  | odt | mformat | yes | - |
74
81
  | pdf | mformat | yes | - |
75
- | rst | mformat | yes | - |
82
+ | reST | mformat | yes | - |
76
83
  | rtf | mformat | yes | - |
77
84
  | txt | mformat | yes | - |
78
85
 
86
+ ## Features
87
+
88
+ All features are not available for all file formats. Often the file
89
+ format restricts what features are reasonable in that format. Using
90
+ a selection mechanism called Capabilities it is possible to select
91
+ file format at runtime based on what features are essential. It is
92
+ also possible to ignore some features when using a file format that
93
+ cannot support that feature (like ignoring bold fomatting in CSV).
94
+
95
+ The main features are:
96
+
97
+ - File open modes: Create, Read or Update
98
+ - Writing tables from list of lists or list of dicts
99
+ - Writing headings before and between tables
100
+ - Reading tables to list of lists or list of dicts, including the headings
101
+ before the table.
102
+ - formatting per cell or per row:
103
+ - bold format
104
+ - italics format
105
+ - highlight colour
106
+ - reading and writing cells with data types:
107
+ - str
108
+ - bool
109
+ - int
110
+ - float
111
+ - datetime
112
+ - writing a table as a filtered data range
113
+ - writing a table to a specific location in a spreadsheet (specified by a box)
114
+ - reading table data from a specific location in a spreadsheet (specified by a box)
115
+ - using multiple sheets in spreadsheets
116
+ - finding location where some data is present in spreadsheet and doing modifications
117
+ at that position or at positions relative to that position.
118
+
79
119
  ## Example programs
80
120
 
81
- Some example programs are available at: [https://bitbucket.org/tom-bjorkholm/table-io/src/master/example/src/example/](https://bitbucket.org/tom-bjorkholm/table-io/src/master/example/src/example/).
121
+ The best way to learn to use this package is to use the provided
122
+ example programs:
123
+ [https://bitbucket.org/tom-bjorkholm/table-io/src/master/example/src/example/README.md](https://bitbucket.org/tom-bjorkholm/table-io/src/master/example/src/example/README.md).
82
124
 
83
125
  ## API documentation
84
126
 
85
- Be aware that this is still in early development. The APIs may change between versions.
86
-
87
127
  You can find the public API documentation at [https://bitbucket.org/tom-bjorkholm/table-io/src/master/doc/api.md](https://bitbucket.org/tom-bjorkholm/table-io/src/master/doc/api.md)
88
128
 
89
129
  You can find the protected API documentation at [https://bitbucket.org/tom-bjorkholm/table-io/src/master/doc/protected_api.md](https://bitbucket.org/tom-bjorkholm/table-io/src/master/doc/protected_api.md)
@@ -96,14 +136,16 @@ a better start by reading the examples.
96
136
 
97
137
  ## Version history
98
138
 
99
- | Version | Date | Python version | Comment |
100
- |---------|-------------|----------------|------------------------|
101
- | 0.1 | 2026 Mar 23 | 3.12 or newer | First released version |
139
+ | Version | Date | Python version | Comment |
140
+ |---------|-------------|----------------|-----------------------------|
141
+ | 0.3 | 2023 Apr 01 | 3.12 or newer | Improved API, more backends |
142
+ | 0.2 | 2026 Mar 28 | 3.12 or newer | More features, API changes |
143
+ | 0.1 | 2026 Mar 23 | 3.12 or newer | First released version |
102
144
 
103
145
  ## Test summary
104
146
 
105
- - Test result: 634 passed in 17s
106
- - No Flake8 warnings.
147
+ - Test result: 1010 passed in 14s
148
+ - No flake8 warnings.
107
149
  - No mypy errors found.
108
- - Built version(s): 0.1
150
+ - Built version(s): 0.3
109
151
  - Build and test using Python 3.14.3
@@ -1,13 +1,10 @@
1
1
  # tableio
2
2
 
3
- ## Early protoype
4
-
5
- This package is still an early prototype. This means that major changes to the APIs are expected.
6
-
7
- ## Use
8
-
9
3
  > **👤 Looking to use this in your program**
10
- > This repository is for developers of the package. If you want to install and use `tableio` including writing programs that use them, please visit the **PyPI project page [https://pypi.org/project/tableio](https://pypi.org/project/tableio) for installation instructions and user documentation.
4
+ > This repository is for developers of the package. If you want to install
5
+ > and use `tableio` including writing programs that use them, please visit
6
+ > the **PyPI project page [https://pypi.org/project/tableio](https://pypi.org/project/tableio)
7
+ > for installation instructions and user documentation.
11
8
 
12
9
  ## What is it
13
10
 
@@ -52,22 +49,20 @@ git submodule update --remote --merge
52
49
 
53
50
  #### OS
54
51
 
55
- For running the script and running the test suite you need a mac or a Linux computer. Even if the resulting package can be installed and used on Windows, the scripts for building and testing are only implemented for mac and Linux.
52
+ For running the script and running the test suite you need a mac or a Linux computer.
53
+ Even if the resulting package can be installed and used on Windows, the scripts for
54
+ building and testing are only implemented for mac and Linux.
56
55
 
57
56
  #### Python version
58
57
 
59
- Please see README_pypi.md for information on needed python version. Main development is on newest Python version.
60
-
61
- #### Zsh
62
-
63
- Most scripts are Python.
64
- Some scripts are zsh. zsh is available by default on modern macs. zsh can easily be installed on Linux (on Ubuntu: `sudo apt install zsh`).
58
+ Please see README_pypi.md for information on needed python version.
59
+ Main development is on newest Python version.
65
60
 
66
61
  ### Quick start
67
62
 
68
63
  1. Clone this repository
69
- 2. Run `./setup_build_environment.zsh` to set up the build environment
70
- 3. Run `./doBuild.zsh` to build and test the package
64
+ 2. Run `./run_setup_build_environment.py` to set up the build environment
65
+ 3. Run `./run_build.py` to build and test the package
71
66
 
72
67
  ### Building application
73
68
 
@@ -98,8 +93,8 @@ information about the build system. This README can also be viewed at
98
93
 
99
94
  ## Test summary
100
95
 
101
- - Test result: 634 passed in 17s
102
- - No Flake8 warnings.
96
+ - Test result: 1010 passed in 14s
97
+ - No flake8 warnings.
103
98
  - No mypy errors found.
104
- - Built version(s): 0.1
99
+ - Built version(s): 0.3
105
100
  - Build and test using Python 3.14.3
@@ -0,0 +1,123 @@
1
+ # tableio
2
+
3
+ The tableio package contains a number of classes providing a uniform way for
4
+ a python program to write table data (rows of columns) to and read table data
5
+ from a number of different common file formats.
6
+
7
+ An increasing number of users want output from programs to be in a format
8
+ like a spreadsheet, and not the old fashoned raw text files. Similarly,
9
+ many users want the data they feed into programs to be in a particular format
10
+ (like a spreadsheet). The tableio package tries to make it easier for the
11
+ programmer to fullfil requests like that.
12
+
13
+ The primary intended use is for data table output from a python program
14
+ and data table input to a python program, where the programmer would like
15
+ the user to be able to select the input and output file formats.
16
+
17
+ The support for spreadsheets is for reading and writing data. There is no
18
+ intention to support reading or writing formulas. There is no support for
19
+ running calculations in the spreadsheets (although nothing will stop a
20
+ receiver of a spreadsheet created by tableio package to manually add
21
+ formulas in the received spreadsheet).
22
+
23
+ ## Installing tableio
24
+
25
+ ### Installing tableio on mac and Linux
26
+
27
+ ````sh
28
+ pip3 install --upgrade tableio
29
+ ````
30
+
31
+ ### Installing tableio on Microsoft Windows
32
+
33
+ ````sh
34
+ pip install --upgrade tableio
35
+ ````
36
+
37
+ ## Supported formats
38
+
39
+ The currently supported formats are:
40
+
41
+ | File format | Implementation | Can write | Can read |
42
+ |-------------|----------------|-----------|----------|
43
+ | CSV | csv | yes | yes |
44
+ | Excel | OpenPyXL | yes | yes |
45
+ | Excel | XlsxWriter | yes | - |
46
+ | Excel | pylightxl | yes | yes |
47
+ | ODS | odfdo | yes | yes |
48
+ | HTML | mformat | yes | - |
49
+ | LaTeX | mformat | yes | - |
50
+ | docx | mformat | yes | - |
51
+ | md | mformat | yes | - |
52
+ | odt | mformat | yes | - |
53
+ | pdf | mformat | yes | - |
54
+ | reST | mformat | yes | - |
55
+ | rtf | mformat | yes | - |
56
+ | txt | mformat | yes | - |
57
+
58
+ ## Features
59
+
60
+ All features are not available for all file formats. Often the file
61
+ format restricts what features are reasonable in that format. Using
62
+ a selection mechanism called Capabilities it is possible to select
63
+ file format at runtime based on what features are essential. It is
64
+ also possible to ignore some features when using a file format that
65
+ cannot support that feature (like ignoring bold fomatting in CSV).
66
+
67
+ The main features are:
68
+
69
+ - File open modes: Create, Read or Update
70
+ - Writing tables from list of lists or list of dicts
71
+ - Writing headings before and between tables
72
+ - Reading tables to list of lists or list of dicts, including the headings
73
+ before the table.
74
+ - formatting per cell or per row:
75
+ - bold format
76
+ - italics format
77
+ - highlight colour
78
+ - reading and writing cells with data types:
79
+ - str
80
+ - bool
81
+ - int
82
+ - float
83
+ - datetime
84
+ - writing a table as a filtered data range
85
+ - writing a table to a specific location in a spreadsheet (specified by a box)
86
+ - reading table data from a specific location in a spreadsheet (specified by a box)
87
+ - using multiple sheets in spreadsheets
88
+ - finding location where some data is present in spreadsheet and doing modifications
89
+ at that position or at positions relative to that position.
90
+
91
+ ## Example programs
92
+
93
+ The best way to learn to use this package is to use the provided
94
+ example programs:
95
+ [https://bitbucket.org/tom-bjorkholm/table-io/src/master/example/src/example/README.md](https://bitbucket.org/tom-bjorkholm/table-io/src/master/example/src/example/README.md).
96
+
97
+ ## API documentation
98
+
99
+ You can find the public API documentation at [https://bitbucket.org/tom-bjorkholm/table-io/src/master/doc/api.md](https://bitbucket.org/tom-bjorkholm/table-io/src/master/doc/api.md)
100
+
101
+ You can find the protected API documentation at [https://bitbucket.org/tom-bjorkholm/table-io/src/master/doc/protected_api.md](https://bitbucket.org/tom-bjorkholm/table-io/src/master/doc/protected_api.md)
102
+ The protected API documentation is only for developers that want to
103
+ extend the framework with by adding their own classes as registered
104
+ readers/writers to the factory.
105
+
106
+ Even though the API documentation exists, most users and programmers probably get
107
+ a better start by reading the examples.
108
+
109
+ ## Version history
110
+
111
+ | Version | Date | Python version | Comment |
112
+ |---------|-------------|----------------|-----------------------------|
113
+ | 0.3 | 2023 Apr 01 | 3.12 or newer | Improved API, more backends |
114
+ | 0.2 | 2026 Mar 28 | 3.12 or newer | More features, API changes |
115
+ | 0.1 | 2026 Mar 23 | 3.12 or newer | First released version |
116
+
117
+ ## Test summary
118
+
119
+ - Test result: 1010 passed in 14s
120
+ - No flake8 warnings.
121
+ - No mypy errors found.
122
+ - Built version(s): 0.3
123
+ - Build and test using Python 3.14.3
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tableio"
7
- version = "0.1"
7
+ version = "0.3"
8
8
  authors = [
9
9
  { name="Tom Björkholm", email="klausuler_linnet0q@icloud.com" },
10
10
  ]
@@ -15,8 +15,7 @@ license = "MIT"
15
15
  license-files = ["LICENSE.txt"]
16
16
  classifiers = [
17
17
  "Programming Language :: Python :: 3",
18
- "Operating System :: OS Independent",
19
- "Development Status :: 2 - Pre-Alpha"
18
+ "Operating System :: OS Independent"
20
19
  ]
21
20
  dynamic = ["dependencies"]
22
21
 
@@ -5,7 +5,7 @@ from setuptools import setup
5
5
 
6
6
  setup(
7
7
  name='tableio',
8
- version='0.1',
8
+ version='0.3',
9
9
  description='Uniform way to write table data to and read from different ' \
10
10
  'file formats',
11
11
  author='Tom Björkholm',
@@ -17,10 +17,13 @@ setup(
17
17
  install_requires=[ # pylint: disable=duplicate-code
18
18
  'pip >= 26.0.1',
19
19
  'setuptools >= 82.0.1',
20
- 'build >= 1.4.0',
20
+ 'build >= 1.4.2',
21
21
  'wheel >= 0.46.3',
22
22
  'mformat-ext >= 0.6',
23
23
  'openpyxl >= 3.1.5',
24
- 'types-openpyxl >= 3.1.5.20260322'
24
+ 'types-openpyxl >= 3.1.5.20260322',
25
+ 'odfdo >= 3.22.3',
26
+ 'xlsxwriter >= 3.2.9',
27
+ 'pylightxl >= 1.61'
25
28
  ]
26
29
  )
@@ -0,0 +1,47 @@
1
+ #! /usr/local/bin/python3
2
+ """Curated top-level public API for the tableio package."""
3
+
4
+ # Copyright (c) 2026 Tom Björkholm
5
+ # MIT License
6
+ #
7
+
8
+ from tableio.capability import CAP_IGNORABLE, CAP_NEEDED, CAP_NOT_USED, \
9
+ Capabilities
10
+ from tableio.color import Color
11
+ from tableio.factory import create_tableio, filter_args_tableio, \
12
+ list_implementations_tableio, list_registered_tableio
13
+ from tableio.optional_args import CsvDialect, OptionalArgs, OptionalArgsDict
14
+ from tableio.tableio import Box, FileAccess, Position, TableIO
15
+ from tableio.value_type import CellT, DictData, DictDataMap, Fmt, \
16
+ FmtDictData, FmtDictRow, FmtListData, FmtListRow, ListData, \
17
+ ListDataSeq, ReadResult, Value, ValueFmt
18
+
19
+ __all__ = ['create_tableio',
20
+ 'TableIO',
21
+ 'FileAccess',
22
+ 'Box',
23
+ 'Position',
24
+ 'OptionalArgs',
25
+ 'OptionalArgsDict',
26
+ 'Value',
27
+ 'ListData',
28
+ 'ListDataSeq',
29
+ 'DictData',
30
+ 'DictDataMap',
31
+ 'ReadResult',
32
+ 'Fmt',
33
+ 'ValueFmt',
34
+ 'FmtListRow',
35
+ 'FmtDictRow',
36
+ 'FmtListData',
37
+ 'FmtDictData',
38
+ 'CellT',
39
+ 'Color',
40
+ 'Capabilities',
41
+ 'CAP_NEEDED',
42
+ 'CAP_NOT_USED',
43
+ 'CAP_IGNORABLE',
44
+ 'filter_args_tableio',
45
+ 'list_registered_tableio',
46
+ 'list_implementations_tableio',
47
+ 'CsvDialect']
@@ -84,6 +84,12 @@ class Capabilities(NamedTuple):
84
84
  can_write_highlight: SingleCapability = SingleCapability()
85
85
  """The writer class can write highlight according to format."""
86
86
 
87
+ multi_sheet: SingleCapability = SingleCapability()
88
+ """The reader/writer class can read from or write to multiple sheets."""
89
+
90
+ can_find_value_position: SingleCapability = SingleCapability()
91
+ """The reader/writer class can find the position of a value."""
92
+
87
93
 
88
94
  def single_capability_match(offered: SingleCapability,
89
95
  will_use: SingleCapability,
@@ -98,7 +104,7 @@ def single_capability_match(offered: SingleCapability,
98
104
  ignore_allowed: If False: when the offered single capability would
99
105
  ignore the will use single capability it is
100
106
  considered a mismatch, and will return False.
101
- If False: when the offered single capability would
107
+ If True: when the offered single capability would
102
108
  ignore the will use single capability it is
103
109
  considered a match, and will return True.
104
110
  Returns:
@@ -154,3 +160,90 @@ class CapabilityNotSupported(ValueError):
154
160
  """
155
161
  self.action = action
156
162
  super().__init__(f'The class does not support {action}.')
163
+
164
+
165
+ def capability_to_str(capability: SingleCapability) -> str:
166
+ """Convert a single capability to a string.
167
+
168
+ Args:
169
+ capability: The single capability to convert.
170
+ Returns:
171
+ A string representation of the single capability.
172
+ """
173
+ result = ''
174
+ if capability.supported:
175
+ result += 'supported'
176
+ else:
177
+ result += 'not supported'
178
+ if capability.strictness == Strictness.STRICT:
179
+ result += ' (strict)'
180
+ else:
181
+ result += ' (ignore)'
182
+ return result
183
+
184
+
185
+ # ----------------------------------------------------------------------------
186
+ # Capability constants from the point of view of the requester
187
+ # ----------------------------------------------------------------------------
188
+
189
+ CAP_NOT_USED = SingleCapability(supported=False, strictness=Strictness.IGNORE)
190
+ """A capability that is not used.
191
+
192
+ The requester promises to not use this capability, so it does not
193
+ matter if the implementation supports it or not.
194
+ """
195
+
196
+ CAP_NEEDED = SingleCapability(supported=True, strictness=Strictness.STRICT)
197
+ """A capability that is used and must be supported.
198
+
199
+ In the selection of reader/writer class it is a must that the selected
200
+ class supports this capability. If no matching reader/writer class is
201
+ found to fulfill the request, an exception is raised.
202
+ """
203
+
204
+ CAP_IGNORABLE = SingleCapability(supported=True, strictness=Strictness.IGNORE)
205
+ """A capability that can be ignored if not supported.
206
+
207
+ An example might be that prefer to be able to write a value in bold,
208
+ but the request can accept that the implementation ignores the bold
209
+ formatting.
210
+ """
211
+
212
+ # ----------------------------------------------------------------------------
213
+ # Capability constants from the point of view of the reader/writer class
214
+ # ----------------------------------------------------------------------------
215
+
216
+ CAP_IMPLEMENTED = SingleCapability(supported=True,
217
+ strictness=Strictness.STRICT)
218
+ """A capability that is fully implemented and supported."""
219
+
220
+ CAP_IGNORED = SingleCapability(supported=False, strictness=Strictness.IGNORE)
221
+ """A capability that is not supported and will be ignored if requested.
222
+
223
+ The implementation cannot fulfill the request, but it makes sense to
224
+ ignore this feature and continue anyway. A typical example would be
225
+ a request to format a written value in bold. Here ignoring the bold
226
+ formatting makes sense as there is still a value written to the file.
227
+ """
228
+
229
+ CAP_UNSUPPORTED = SingleCapability(supported=False,
230
+ strictness=Strictness.STRICT)
231
+ """A capability that is not supported and will raise an exception if requested.
232
+
233
+ This is a for a feature that cannot be supported but it would not make
234
+ sense to ignore. A typical example would be a request to write
235
+ a value in a specific location in the file. Writing the value to a
236
+ different location would not make sense. Thus the only sensible thing
237
+ to do is to raise an exception.
238
+ """
239
+
240
+ CAP_ALL_IMPLEMENTED = Capabilities(can_read=CAP_IMPLEMENTED,
241
+ can_write=CAP_IMPLEMENTED,
242
+ can_fmt_row=CAP_IMPLEMENTED,
243
+ can_fmt_value=CAP_IMPLEMENTED,
244
+ filtered_data_range=CAP_IMPLEMENTED,
245
+ can_write_box=CAP_IMPLEMENTED,
246
+ can_read_box=CAP_IMPLEMENTED,
247
+ can_write_highlight=CAP_IMPLEMENTED,
248
+ multi_sheet=CAP_IMPLEMENTED,
249
+ can_find_value_position=CAP_IMPLEMENTED)
@@ -51,6 +51,37 @@ class TableIOFactoryNoCapabilityMatch(ValueError):
51
51
  """
52
52
 
53
53
 
54
+ class InsufficientCapabilities(ValueError):
55
+ """Raised when requested capabilities contradict requested file access.
56
+
57
+ Error raised when the caller supplies both file access and an explicit
58
+ Capabilities object, but the requested capabilities do not include the
59
+ capability implied by that access mode. For example, READ requires
60
+ can_read, CREATE requires can_write, and UPDATE requires both.
61
+ """
62
+
63
+
64
+ def _check_capabilities_for_file_access(
65
+ file_access: FileAccess,
66
+ capabilities: Optional[Capabilities]) -> None:
67
+ """Raise if explicit capabilities not enough for requested access mode."""
68
+ if capabilities is None:
69
+ return
70
+ if file_access == FileAccess.READ and not capabilities.can_read.supported:
71
+ msg = 'FileAccess.READ requires can_read capability.'
72
+ raise InsufficientCapabilities(msg)
73
+ if file_access == FileAccess.CREATE and \
74
+ not capabilities.can_write.supported:
75
+ msg = 'FileAccess.CREATE requires can_write capability.'
76
+ raise InsufficientCapabilities(msg)
77
+ if file_access == FileAccess.UPDATE and (
78
+ not capabilities.can_write.supported or
79
+ not capabilities.can_read.supported):
80
+ msg = 'FileAccess.UPDATE requires both can_read and '
81
+ msg += 'can_write capabilities.'
82
+ raise InsufficientCapabilities(msg)
83
+
84
+
54
85
  @total_ordering
55
86
  class ImplPrio(NamedTuple):
56
87
  """Priority of an implementation."""
@@ -339,6 +370,7 @@ class TableIOFactory:
339
370
  An instance of the requested TableIO subclass.
340
371
  Intended to be used as context manager, using a with statement.
341
372
  Raises:
373
+ InsufficientCapabilities: If capabilities contradict file_access.
342
374
  TableIOFactoryNoSuchError: If the format_name is not registered
343
375
  or the implementation name is not
344
376
  registered.
@@ -357,7 +389,17 @@ class TableIOFactory:
357
389
  file_access: FileAccess, args: OptionalArgs = None,
358
390
  implementation: Optional[str] = None,
359
391
  capabilities: Optional[Capabilities] = None) -> TableIO:
360
- """Internally create an instance of a registered subclass."""
392
+ """Internally create an instance of a registered subclass.
393
+
394
+ Raises:
395
+ InsufficientCapabilities: If capabilities contradict file_access.
396
+ TableIOFactoryNoSuchError: If the format_name is not registered
397
+ or the implementation name is not
398
+ registered.
399
+ TableIOFactoryNoCapabilityMatch: If the capabilities cannot be
400
+ matched to any implementation.
401
+ """
402
+ _check_capabilities_for_file_access(file_access, capabilities)
361
403
  correct_name: Optional[str] = None
362
404
  if format_name in self._formats:
363
405
  correct_name = format_name
@@ -371,8 +413,8 @@ class TableIOFactory:
371
413
  )
372
414
  assert correct_name is not None
373
415
  format_info: FactoryFormatInfo = self._formats[correct_name]
374
- best_matches = format_info.best_match_names(capabilities=capabilities,
375
- empty_is_ok=False)
416
+ best_matches = format_info.best_match_names(
417
+ capabilities=capabilities, empty_is_ok=False)
376
418
  if implementation is not None:
377
419
  fikeys = list(format_info._registry.keys()) # pylint: disable=protected-access # noqa: E501
378
420
  if implementation not in fikeys:
@@ -666,6 +708,7 @@ def create_tableio(format_name: str, # pylint: disable=too-many-arguments, too-
666
708
  Returns:
667
709
  An instance of the requested TableIO subclass.
668
710
  Raises:
711
+ InsufficientCapabilities: If capabilities contradict file_access.
669
712
  TableIOFactoryNoSuchError: If the format_name or implementation
670
713
  name is not registered.
671
714
  TableIOFactoryNoCapabilityMatch: If the capabilities cannot be
@@ -16,6 +16,9 @@ from tableio.tableio_mformat import TableIOMformatHtml, TableIOMformatMd, \
16
16
  TableIOMformatRtf
17
17
  from tableio.tableio_csv import TableIOCsv
18
18
  from tableio.tableio_excel_openpyxl import TableIOExcelOpenPyXL
19
+ from tableio.tableio_excel_pylightxl import TableIOExcelPylightxl
20
+ from tableio.tableio_excel_xlsxwriter import TableIOExcelXlsxWriter
21
+ from tableio.tableio_ods_odfdo import TableIOOdsOdfdo
19
22
  from tableio.tableio import TableIO
20
23
 
21
24
 
@@ -26,5 +29,8 @@ def register_formats_in_pkg() -> list[type[TableIO]]:
26
29
  TableIOMformatLatex, TableIOMformatDocx,
27
30
  TableIOMformatOdt, TableIOMformatPdf,
28
31
  TableIOMformatRtf, TableIOCsv,
29
- TableIOExcelOpenPyXL]
32
+ TableIOExcelOpenPyXL,
33
+ TableIOExcelPylightxl,
34
+ TableIOExcelXlsxWriter,
35
+ TableIOOdsOdfdo]
30
36
  return ret