numbers-parser 4.10.3__py3-none-any.whl → 4.10.5__py3-none-any.whl
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.
- numbers_parser/__init__.py +1 -1
- numbers_parser/_cat_numbers.py +4 -4
- numbers_parser/_unpack_numbers.py +5 -5
- numbers_parser/cell.py +119 -119
- numbers_parser/constants.py +5 -6
- numbers_parser/containers.py +13 -7
- numbers_parser/document.py +135 -113
- numbers_parser/exceptions.py +0 -7
- numbers_parser/formula.py +3 -4
- numbers_parser/generated/TNArchives_pb2.py +24 -26
- numbers_parser/generated/TSAArchives_pb2.py +26 -28
- numbers_parser/generated/TSCEArchives_pb2.py +8 -10
- numbers_parser/generated/TSCHArchives_GEN_pb2.py +28 -34
- numbers_parser/generated/TSCHArchives_pb2.py +61 -65
- numbers_parser/generated/TSDArchives_pb2.py +100 -110
- numbers_parser/generated/TSKArchives_pb2.py +168 -170
- numbers_parser/generated/TSPArchiveMessages_pb2.py +32 -34
- numbers_parser/generated/TSPMessages_pb2.py +40 -40
- numbers_parser/generated/TSSArchives_pb2.py +36 -36
- numbers_parser/generated/TSTArchives_pb2.py +321 -325
- numbers_parser/generated/TSTStylePropertyArchiving_pb2.py +8 -10
- numbers_parser/generated/TSWPArchives_pb2.py +250 -286
- numbers_parser/generated/TSWPCommandArchives_pb2.py +95 -95
- numbers_parser/iwafile.py +16 -16
- numbers_parser/iwork.py +35 -29
- numbers_parser/model.py +77 -55
- numbers_parser/numbers_uuid.py +6 -4
- {numbers_parser-4.10.3.dist-info → numbers_parser-4.10.5.dist-info}/METADATA +7 -7
- {numbers_parser-4.10.3.dist-info → numbers_parser-4.10.5.dist-info}/RECORD +32 -32
- {numbers_parser-4.10.3.dist-info → numbers_parser-4.10.5.dist-info}/LICENSE.rst +0 -0
- {numbers_parser-4.10.3.dist-info → numbers_parser-4.10.5.dist-info}/WHEEL +0 -0
- {numbers_parser-4.10.3.dist-info → numbers_parser-4.10.5.dist-info}/entry_points.txt +0 -0
numbers_parser/document.py
CHANGED
|
@@ -46,8 +46,7 @@ class Table:
|
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
class Document:
|
|
49
|
-
"""
|
|
50
|
-
Create an instance of a new Numbers document.
|
|
49
|
+
"""Create an instance of a new Numbers document.
|
|
51
50
|
|
|
52
51
|
If ``filename`` is ``None``, an empty document is created using the defaults
|
|
53
52
|
defined by the class constructor. You can optionionally override these
|
|
@@ -87,7 +86,7 @@ class Document:
|
|
|
87
86
|
num_header_cols: Optional[int] = 1,
|
|
88
87
|
num_rows: Optional[int] = DEFAULT_ROW_COUNT,
|
|
89
88
|
num_cols: Optional[int] = DEFAULT_COLUMN_COUNT,
|
|
90
|
-
):
|
|
89
|
+
) -> None:
|
|
91
90
|
self._model = _NumbersModel(None if filename is None else Path(filename))
|
|
92
91
|
refs = self._model.sheet_ids()
|
|
93
92
|
self._sheets = ItemsList(self._model, refs, Sheet)
|
|
@@ -120,15 +119,13 @@ class Document:
|
|
|
120
119
|
|
|
121
120
|
@property
|
|
122
121
|
def custom_formats(self) -> Dict[str, CustomFormatting]:
|
|
123
|
-
"""
|
|
124
|
-
Dict[str, :class:`CustomFormatting`]: A dict mapping custom format names
|
|
122
|
+
"""Dict[str, :class:`CustomFormatting`]: A dict mapping custom format names
|
|
125
123
|
to the corresponding custom format.
|
|
126
124
|
"""
|
|
127
125
|
return self._model.custom_formats
|
|
128
126
|
|
|
129
127
|
def save(self, filename: Union[str, Path], package: bool = False) -> None:
|
|
130
|
-
"""
|
|
131
|
-
Save the document in the specified filename.
|
|
128
|
+
"""Save the document in the specified filename.
|
|
132
129
|
|
|
133
130
|
Parameters
|
|
134
131
|
----------
|
|
@@ -165,8 +162,7 @@ class Document:
|
|
|
165
162
|
num_rows: Optional[int] = DEFAULT_ROW_COUNT,
|
|
166
163
|
num_cols: Optional[int] = DEFAULT_COLUMN_COUNT,
|
|
167
164
|
) -> None:
|
|
168
|
-
"""
|
|
169
|
-
Add a new sheet to the current document.
|
|
165
|
+
"""Add a new sheet to the current document.
|
|
170
166
|
|
|
171
167
|
If no sheet name is provided, the next available numbered sheet
|
|
172
168
|
will be generated in the series ``Sheet 1``, ``Sheet 2``, etc.
|
|
@@ -182,12 +178,14 @@ class Document:
|
|
|
182
178
|
num_cols: int, optional, default: 8
|
|
183
179
|
The number of columns in the newly created table
|
|
184
180
|
|
|
185
|
-
Raises
|
|
181
|
+
Raises
|
|
182
|
+
------
|
|
186
183
|
IndexError: If the sheet name already exists in the document.
|
|
187
184
|
"""
|
|
188
185
|
if sheet_name is not None:
|
|
189
186
|
if sheet_name in self._sheets:
|
|
190
|
-
|
|
187
|
+
msg = f"sheet '{sheet_name}' already exists"
|
|
188
|
+
raise IndexError(msg)
|
|
191
189
|
else:
|
|
192
190
|
sheet_num = 1
|
|
193
191
|
while f"sheet {sheet_num}" in self._sheets:
|
|
@@ -201,15 +199,14 @@ class Document:
|
|
|
201
199
|
Table(
|
|
202
200
|
self._model,
|
|
203
201
|
self._model.add_table(
|
|
204
|
-
new_sheet_id, table_name, prev_table_id, 0, 0, num_rows, num_cols
|
|
202
|
+
new_sheet_id, table_name, prev_table_id, 0, 0, num_rows, num_cols,
|
|
205
203
|
),
|
|
206
|
-
)
|
|
204
|
+
),
|
|
207
205
|
)
|
|
208
206
|
self._sheets.append(new_sheet)
|
|
209
207
|
|
|
210
208
|
def add_style(self, **kwargs) -> Style:
|
|
211
|
-
r"""
|
|
212
|
-
Add a new style to the current document.
|
|
209
|
+
r"""Add a new style to the current document.
|
|
213
210
|
|
|
214
211
|
If no style name is provided, the next available numbered style
|
|
215
212
|
will be generated in the series ``Custom Style 1``, ``Custom Style 2``, etc.
|
|
@@ -239,13 +236,15 @@ class Document:
|
|
|
239
236
|
If ``font_size`` is not a ``float``, ``font_name`` is not a ``str``,
|
|
240
237
|
``bg_image`` is not a :py:class:`~numbers_parser.BackgroundImage`,
|
|
241
238
|
or if any of the ``bool`` parameters are invalid.
|
|
242
|
-
"""
|
|
239
|
+
"""
|
|
243
240
|
if "name" in kwargs and kwargs["name"] is not None and kwargs["name"] in self._model.styles:
|
|
244
|
-
|
|
241
|
+
msg = f"style '{kwargs['name']}' already exists"
|
|
242
|
+
raise IndexError(msg)
|
|
245
243
|
|
|
246
244
|
if "bg_image" in kwargs and kwargs["bg_image"] is not None:
|
|
247
245
|
if not isinstance(kwargs["bg_image"], BackgroundImage):
|
|
248
|
-
|
|
246
|
+
msg = "bg_image must be a BackgroundImage object"
|
|
247
|
+
raise TypeError(msg)
|
|
249
248
|
self._model.store_image((kwargs["bg_image"].data), kwargs["bg_image"].filename)
|
|
250
249
|
|
|
251
250
|
style = Style(**kwargs)
|
|
@@ -256,8 +255,7 @@ class Document:
|
|
|
256
255
|
return style
|
|
257
256
|
|
|
258
257
|
def add_custom_format(self, **kwargs) -> CustomFormatting:
|
|
259
|
-
r"""
|
|
260
|
-
Add a new custom format to the current document.
|
|
258
|
+
r"""Add a new custom format to the current document.
|
|
261
259
|
|
|
262
260
|
.. code-block:: python
|
|
263
261
|
|
|
@@ -308,14 +306,16 @@ class Document:
|
|
|
308
306
|
and kwargs["name"] is not None
|
|
309
307
|
and kwargs["name"] in self._model.custom_formats
|
|
310
308
|
):
|
|
311
|
-
|
|
309
|
+
msg = f"format '{kwargs['name']}' already exists"
|
|
310
|
+
raise IndexError(msg)
|
|
312
311
|
|
|
313
312
|
if "type" in kwargs:
|
|
314
313
|
format_type = kwargs["type"].upper()
|
|
315
314
|
try:
|
|
316
315
|
kwargs["type"] = CustomFormattingType[format_type]
|
|
317
316
|
except (KeyError, AttributeError):
|
|
318
|
-
|
|
317
|
+
msg = f"unsuported cell format type '{format_type}'"
|
|
318
|
+
raise TypeError(msg) from None
|
|
319
319
|
|
|
320
320
|
custom_format = CustomFormatting(**kwargs)
|
|
321
321
|
if custom_format.name is None:
|
|
@@ -330,7 +330,7 @@ class Document:
|
|
|
330
330
|
|
|
331
331
|
|
|
332
332
|
class Sheet:
|
|
333
|
-
def __init__(self, model, sheet_id):
|
|
333
|
+
def __init__(self, model, sheet_id) -> None:
|
|
334
334
|
self._sheet_id = sheet_id
|
|
335
335
|
self._model = model
|
|
336
336
|
refs = self._model.table_ids(self._sheet_id)
|
|
@@ -402,11 +402,12 @@ class Sheet:
|
|
|
402
402
|
return self._add_table(table_name, from_table_id, x, y, num_rows, num_cols)
|
|
403
403
|
|
|
404
404
|
def _add_table( # noqa: PLR0913
|
|
405
|
-
self, table_name, from_table_id, x, y, num_rows, num_cols
|
|
406
|
-
) -> object:
|
|
405
|
+
self, table_name, from_table_id, x, y, num_rows, num_cols,
|
|
406
|
+
) -> object:
|
|
407
407
|
if table_name is not None:
|
|
408
408
|
if table_name in self._tables:
|
|
409
|
-
|
|
409
|
+
msg = f"table '{table_name}' already exists"
|
|
410
|
+
raise IndexError(msg)
|
|
410
411
|
else:
|
|
411
412
|
table_num = 1
|
|
412
413
|
while f"table {table_num}" in self._tables:
|
|
@@ -414,14 +415,14 @@ class Sheet:
|
|
|
414
415
|
table_name = f"Table {table_num}"
|
|
415
416
|
|
|
416
417
|
new_table_id = self._model.add_table(
|
|
417
|
-
self._sheet_id, table_name, from_table_id, x, y, num_rows, num_cols
|
|
418
|
+
self._sheet_id, table_name, from_table_id, x, y, num_rows, num_cols,
|
|
418
419
|
)
|
|
419
420
|
self._tables.append(Table(self._model, new_table_id))
|
|
420
421
|
return self._tables[-1]
|
|
421
422
|
|
|
422
423
|
|
|
423
|
-
class Table(Cacheable):
|
|
424
|
-
def __init__(self, model, table_id):
|
|
424
|
+
class Table(Cacheable):
|
|
425
|
+
def __init__(self, model, table_id) -> None:
|
|
425
426
|
super().__init__()
|
|
426
427
|
self._model = model
|
|
427
428
|
self._table_id = table_id
|
|
@@ -466,18 +467,16 @@ class Table(Cacheable): # noqa: F811
|
|
|
466
467
|
|
|
467
468
|
@property
|
|
468
469
|
def num_header_rows(self) -> int:
|
|
469
|
-
"""
|
|
470
|
-
int: The number of header rows.
|
|
470
|
+
"""int: The number of header rows.
|
|
471
471
|
|
|
472
|
-
Example
|
|
472
|
+
Example:
|
|
473
473
|
-------
|
|
474
|
-
|
|
475
474
|
.. code-block:: python
|
|
476
475
|
|
|
477
476
|
# Add an extra header row
|
|
478
477
|
table.num_header_rows += 1
|
|
479
478
|
|
|
480
|
-
Raises
|
|
479
|
+
Raises:
|
|
481
480
|
------
|
|
482
481
|
ValueError:
|
|
483
482
|
If the number of headers is negative, exceeds the number of rows in the
|
|
@@ -488,27 +487,28 @@ class Table(Cacheable): # noqa: F811
|
|
|
488
487
|
@num_header_rows.setter
|
|
489
488
|
def num_header_rows(self, num_headers: int):
|
|
490
489
|
if num_headers < 0:
|
|
491
|
-
|
|
490
|
+
msg = "Number of headers cannot be negative"
|
|
491
|
+
raise ValueError(msg)
|
|
492
492
|
elif num_headers > self.num_rows:
|
|
493
|
-
|
|
493
|
+
msg = "Number of headers cannot exceed the number of rows"
|
|
494
|
+
raise ValueError(msg)
|
|
494
495
|
elif num_headers > MAX_HEADER_COUNT:
|
|
495
|
-
|
|
496
|
+
msg = f"Number of headers cannot exceed {MAX_HEADER_COUNT} rows"
|
|
497
|
+
raise ValueError(msg)
|
|
496
498
|
return self._model.num_header_rows(self._table_id, num_headers)
|
|
497
499
|
|
|
498
500
|
@property
|
|
499
501
|
def num_header_cols(self) -> int:
|
|
500
|
-
"""
|
|
501
|
-
int: The number of header columns.
|
|
502
|
+
"""int: The number of header columns.
|
|
502
503
|
|
|
503
|
-
Example
|
|
504
|
+
Example:
|
|
504
505
|
-------
|
|
505
|
-
|
|
506
506
|
.. code-block:: python
|
|
507
507
|
|
|
508
508
|
# Add an extra header column
|
|
509
509
|
table.num_header_cols += 1
|
|
510
510
|
|
|
511
|
-
Raises
|
|
511
|
+
Raises:
|
|
512
512
|
------
|
|
513
513
|
ValueError:
|
|
514
514
|
If the number of headers is negative, exceeds the number of rows in the
|
|
@@ -519,11 +519,14 @@ class Table(Cacheable): # noqa: F811
|
|
|
519
519
|
@num_header_cols.setter
|
|
520
520
|
def num_header_cols(self, num_headers: int):
|
|
521
521
|
if num_headers < 0:
|
|
522
|
-
|
|
522
|
+
msg = "Number of headers cannot be negative"
|
|
523
|
+
raise ValueError(msg)
|
|
523
524
|
elif num_headers > self.num_cols:
|
|
524
|
-
|
|
525
|
+
msg = "Number of headers cannot exceed the number of columns"
|
|
526
|
+
raise ValueError(msg)
|
|
525
527
|
elif num_headers > MAX_HEADER_COUNT:
|
|
526
|
-
|
|
528
|
+
msg = f"Number of headers cannot exceed {MAX_HEADER_COUNT} columns"
|
|
529
|
+
raise ValueError(msg)
|
|
527
530
|
return self._model.num_header_cols(self._table_id, num_headers)
|
|
528
531
|
|
|
529
532
|
@property
|
|
@@ -536,9 +539,8 @@ class Table(Cacheable): # noqa: F811
|
|
|
536
539
|
"""int: The table's width in points."""
|
|
537
540
|
return self._model.table_width(self._table_id)
|
|
538
541
|
|
|
539
|
-
def row_height(self, row: int, height: int = None) -> int:
|
|
540
|
-
"""
|
|
541
|
-
The height of a table row in points.
|
|
542
|
+
def row_height(self, row: int, height: Optional[int] = None) -> int:
|
|
543
|
+
"""The height of a table row in points.
|
|
542
544
|
|
|
543
545
|
.. code-block:: python
|
|
544
546
|
|
|
@@ -559,7 +561,7 @@ class Table(Cacheable): # noqa: F811
|
|
|
559
561
|
"""
|
|
560
562
|
return self._model.row_height(self._table_id, row, height)
|
|
561
563
|
|
|
562
|
-
def col_width(self, col: int, width: int = None) -> int:
|
|
564
|
+
def col_width(self, col: int, width: Optional[int] = None) -> int:
|
|
563
565
|
"""The width of a table column in points.
|
|
564
566
|
|
|
565
567
|
Parameters
|
|
@@ -603,9 +605,8 @@ class Table(Cacheable): # noqa: F811
|
|
|
603
605
|
def merge_ranges(self) -> List[str]:
|
|
604
606
|
"""List[str]: The merge ranges of cells in A1 notation.
|
|
605
607
|
|
|
606
|
-
Example
|
|
608
|
+
Example:
|
|
607
609
|
-------
|
|
608
|
-
|
|
609
610
|
.. code-block:: python
|
|
610
611
|
|
|
611
612
|
>>> table.merge_ranges
|
|
@@ -621,11 +622,10 @@ class Table(Cacheable): # noqa: F811
|
|
|
621
622
|
if cell.is_merged:
|
|
622
623
|
size = cell.size
|
|
623
624
|
merge_cells.add(xl_range(row, col, row + size[0] - 1, col + size[1] - 1))
|
|
624
|
-
return sorted(
|
|
625
|
+
return sorted(merge_cells)
|
|
625
626
|
|
|
626
627
|
def cell(self, *args) -> Union[Cell, MergedCell]:
|
|
627
|
-
"""
|
|
628
|
-
Return a single cell in the table.
|
|
628
|
+
"""Return a single cell in the table.
|
|
629
629
|
|
|
630
630
|
The ``cell()`` method supports two forms of notation to designate the position
|
|
631
631
|
of cells: **Row-column** notation and **A1** notation:
|
|
@@ -664,7 +664,7 @@ class Table(Cacheable): # noqa: F811
|
|
|
664
664
|
<numbers_parser.cell.TextCell object at 0x105a80b90>
|
|
665
665
|
>>> table.cell("B2").value
|
|
666
666
|
1234.50
|
|
667
|
-
"""
|
|
667
|
+
"""
|
|
668
668
|
if isinstance(args[0], str):
|
|
669
669
|
(row, col) = xl_cell_to_rowcol(args[0])
|
|
670
670
|
elif len(args) != 2:
|
|
@@ -673,9 +673,11 @@ class Table(Cacheable): # noqa: F811
|
|
|
673
673
|
(row, col) = args
|
|
674
674
|
|
|
675
675
|
if row >= self.num_rows or row < 0:
|
|
676
|
-
|
|
676
|
+
msg = f"row {row} out of range"
|
|
677
|
+
raise IndexError(msg)
|
|
677
678
|
if col >= self.num_cols or col < 0:
|
|
678
|
-
|
|
679
|
+
msg = f"column {col} out of range"
|
|
680
|
+
raise IndexError(msg)
|
|
679
681
|
|
|
680
682
|
return self._data[row][col]
|
|
681
683
|
|
|
@@ -728,13 +730,17 @@ class Table(Cacheable): # noqa: F811
|
|
|
728
730
|
max_col = max_col or self.num_cols - 1
|
|
729
731
|
|
|
730
732
|
if min_row < 0:
|
|
731
|
-
|
|
733
|
+
msg = f"row {min_row} out of range"
|
|
734
|
+
raise IndexError(msg)
|
|
732
735
|
if max_row > self.num_rows:
|
|
733
|
-
|
|
736
|
+
msg = f"row {max_row} out of range"
|
|
737
|
+
raise IndexError(msg)
|
|
734
738
|
if min_col < 0:
|
|
735
|
-
|
|
739
|
+
msg = f"column {min_col} out of range"
|
|
740
|
+
raise IndexError(msg)
|
|
736
741
|
if max_col > self.num_cols:
|
|
737
|
-
|
|
742
|
+
msg = f"column {max_col} out of range"
|
|
743
|
+
raise IndexError(msg)
|
|
738
744
|
|
|
739
745
|
rows = self.rows()
|
|
740
746
|
for row in range(min_row, max_row + 1):
|
|
@@ -792,13 +798,17 @@ class Table(Cacheable): # noqa: F811
|
|
|
792
798
|
max_col = max_col or self.num_cols - 1
|
|
793
799
|
|
|
794
800
|
if min_row < 0:
|
|
795
|
-
|
|
801
|
+
msg = f"row {min_row} out of range"
|
|
802
|
+
raise IndexError(msg)
|
|
796
803
|
if max_row > self.num_rows:
|
|
797
|
-
|
|
804
|
+
msg = f"row {max_row} out of range"
|
|
805
|
+
raise IndexError(msg)
|
|
798
806
|
if min_col < 0:
|
|
799
|
-
|
|
807
|
+
msg = f"column {min_col} out of range"
|
|
808
|
+
raise IndexError(msg)
|
|
800
809
|
if max_col > self.num_cols:
|
|
801
|
-
|
|
810
|
+
msg = f"column {max_col} out of range"
|
|
811
|
+
raise IndexError(msg)
|
|
802
812
|
|
|
803
813
|
rows = self.rows()
|
|
804
814
|
for col in range(min_col, max_col + 1):
|
|
@@ -818,9 +828,11 @@ class Table(Cacheable): # noqa: F811
|
|
|
818
828
|
values = args[2:]
|
|
819
829
|
|
|
820
830
|
if row >= MAX_ROW_COUNT:
|
|
821
|
-
|
|
831
|
+
msg = f"{row} exceeds maximum row {MAX_ROW_COUNT - 1}"
|
|
832
|
+
raise IndexError(msg)
|
|
822
833
|
if col >= MAX_COL_COUNT:
|
|
823
|
-
|
|
834
|
+
msg = f"{col} exceeds maximum column {MAX_COL_COUNT - 1}"
|
|
835
|
+
raise IndexError(msg)
|
|
824
836
|
|
|
825
837
|
for _ in range(self.num_rows, row + 1):
|
|
826
838
|
self.add_row()
|
|
@@ -828,11 +840,10 @@ class Table(Cacheable): # noqa: F811
|
|
|
828
840
|
for _ in range(self.num_cols, col + 1):
|
|
829
841
|
self.add_column()
|
|
830
842
|
|
|
831
|
-
return (row, col
|
|
843
|
+
return (row, col, *tuple(values))
|
|
832
844
|
|
|
833
845
|
def write(self, *args, style: Optional[Union[Style, str, None]] = None) -> None:
|
|
834
|
-
"""
|
|
835
|
-
Write a value to a cell and update the style/cell type.
|
|
846
|
+
"""Write a value to a cell and update the style/cell type.
|
|
836
847
|
|
|
837
848
|
The ``write()`` method supports two forms of notation to designate the position
|
|
838
849
|
of cells: **Row-column** notation and **A1** notation:
|
|
@@ -849,7 +860,6 @@ class Table(Cacheable): # noqa: F811
|
|
|
849
860
|
|
|
850
861
|
Parameters
|
|
851
862
|
----------
|
|
852
|
-
|
|
853
863
|
row: int
|
|
854
864
|
The row number (zero indexed)
|
|
855
865
|
col: int
|
|
@@ -894,10 +904,12 @@ class Table(Cacheable): # noqa: F811
|
|
|
894
904
|
self._data[row][col]._style = style
|
|
895
905
|
elif isinstance(style, str):
|
|
896
906
|
if style not in self._model.styles:
|
|
897
|
-
|
|
907
|
+
msg = f"style '{style}' does not exist"
|
|
908
|
+
raise IndexError(msg)
|
|
898
909
|
self._data[row][col]._style = self._model.styles[style]
|
|
899
910
|
else:
|
|
900
|
-
|
|
911
|
+
msg = "style must be a Style object or style name"
|
|
912
|
+
raise TypeError(msg)
|
|
901
913
|
|
|
902
914
|
def add_row(
|
|
903
915
|
self,
|
|
@@ -905,8 +917,7 @@ class Table(Cacheable): # noqa: F811
|
|
|
905
917
|
start_row: Optional[Union[int, None]] = None,
|
|
906
918
|
default: Optional[Union[str, int, float, bool, DateTime, Duration]] = None,
|
|
907
919
|
) -> None:
|
|
908
|
-
"""
|
|
909
|
-
Add or insert rows to the table.
|
|
920
|
+
"""Add or insert rows to the table.
|
|
910
921
|
|
|
911
922
|
Parameters
|
|
912
923
|
----------
|
|
@@ -934,7 +945,8 @@ class Table(Cacheable): # noqa: F811
|
|
|
934
945
|
If the default value is unsupported by :py:meth:`numbers_parser.Table.write`.
|
|
935
946
|
"""
|
|
936
947
|
if start_row is not None and (start_row < 0 or start_row >= self.num_rows):
|
|
937
|
-
|
|
948
|
+
msg = "Row number not in range for table"
|
|
949
|
+
raise IndexError(msg)
|
|
938
950
|
|
|
939
951
|
if start_row is None:
|
|
940
952
|
start_row = self.num_rows
|
|
@@ -959,8 +971,7 @@ class Table(Cacheable): # noqa: F811
|
|
|
959
971
|
start_col: Optional[Union[int, None]] = None,
|
|
960
972
|
default: Optional[Union[str, int, float, bool, DateTime, Duration]] = None,
|
|
961
973
|
) -> None:
|
|
962
|
-
"""
|
|
963
|
-
Add or insert columns to the table.
|
|
974
|
+
"""Add or insert columns to the table.
|
|
964
975
|
|
|
965
976
|
Parameters
|
|
966
977
|
----------
|
|
@@ -988,7 +999,8 @@ class Table(Cacheable): # noqa: F811
|
|
|
988
999
|
If the default value is unsupported by :py:meth:`numbers_parser.Table.write`.
|
|
989
1000
|
"""
|
|
990
1001
|
if start_col is not None and (start_col < 0 or start_col >= self.num_cols):
|
|
991
|
-
|
|
1002
|
+
msg = "Column number not in range for table"
|
|
1003
|
+
raise IndexError(msg)
|
|
992
1004
|
|
|
993
1005
|
if start_col is None:
|
|
994
1006
|
start_col = self.num_cols
|
|
@@ -1010,8 +1022,7 @@ class Table(Cacheable): # noqa: F811
|
|
|
1010
1022
|
num_rows: Optional[int] = 1,
|
|
1011
1023
|
start_row: Optional[Union[int, None]] = None,
|
|
1012
1024
|
) -> None:
|
|
1013
|
-
"""
|
|
1014
|
-
Delete rows from the table.
|
|
1025
|
+
"""Delete rows from the table.
|
|
1015
1026
|
|
|
1016
1027
|
Parameters
|
|
1017
1028
|
----------
|
|
@@ -1033,7 +1044,8 @@ class Table(Cacheable): # noqa: F811
|
|
|
1033
1044
|
If the start_row is out of range for the table.
|
|
1034
1045
|
"""
|
|
1035
1046
|
if start_row is not None and (start_row < 0 or start_row >= self.num_rows):
|
|
1036
|
-
|
|
1047
|
+
msg = "Row number not in range for table"
|
|
1048
|
+
raise IndexError(msg)
|
|
1037
1049
|
|
|
1038
1050
|
if start_row is not None:
|
|
1039
1051
|
del self._data[start_row : start_row + num_rows]
|
|
@@ -1048,8 +1060,7 @@ class Table(Cacheable): # noqa: F811
|
|
|
1048
1060
|
num_cols: Optional[int] = 1,
|
|
1049
1061
|
start_col: Optional[Union[int, None]] = None,
|
|
1050
1062
|
) -> None:
|
|
1051
|
-
"""
|
|
1052
|
-
Add or delete columns columns from the table.
|
|
1063
|
+
"""Add or delete columns columns from the table.
|
|
1053
1064
|
|
|
1054
1065
|
Parameters
|
|
1055
1066
|
----------
|
|
@@ -1065,7 +1076,8 @@ class Table(Cacheable): # noqa: F811
|
|
|
1065
1076
|
If the start_col is out of range for the table.
|
|
1066
1077
|
"""
|
|
1067
1078
|
if start_col is not None and (start_col < 0 or start_col >= self.num_cols):
|
|
1068
|
-
|
|
1079
|
+
msg = "Column number not in range for table"
|
|
1080
|
+
raise IndexError(msg)
|
|
1069
1081
|
|
|
1070
1082
|
for row in range(self.num_rows):
|
|
1071
1083
|
if start_col is not None:
|
|
@@ -1077,8 +1089,7 @@ class Table(Cacheable): # noqa: F811
|
|
|
1077
1089
|
self._model.number_of_columns(self._table_id, self.num_cols)
|
|
1078
1090
|
|
|
1079
1091
|
def merge_cells(self, cell_range: Union[str, List[str]]) -> None:
|
|
1080
|
-
"""
|
|
1081
|
-
Convert a cell range or list of cell ranges into merged cells.
|
|
1092
|
+
"""Convert a cell range or list of cell ranges into merged cells.
|
|
1082
1093
|
|
|
1083
1094
|
Parameters
|
|
1084
1095
|
----------
|
|
@@ -1119,8 +1130,7 @@ class Table(Cacheable): # noqa: F811
|
|
|
1119
1130
|
cell._set_merge(merge_cells.get((row, col)))
|
|
1120
1131
|
|
|
1121
1132
|
def set_cell_border(self, *args):
|
|
1122
|
-
"""
|
|
1123
|
-
Set the borders for a cell.
|
|
1133
|
+
"""Set the borders for a cell.
|
|
1124
1134
|
|
|
1125
1135
|
Cell references can be row-column offsers or Excel/Numbers-style A1 notation. Borders
|
|
1126
1136
|
can be applied to multiple sides of a cell by passing a list of sides. The name(s)
|
|
@@ -1150,17 +1160,17 @@ class Table(Cacheable): # noqa: F811
|
|
|
1150
1160
|
* **param3** (:py:class:`Border`): The border to add.
|
|
1151
1161
|
* **param4** (*int*, *optional*, default: 1): The length of the stroke to add.
|
|
1152
1162
|
|
|
1153
|
-
Raises
|
|
1163
|
+
Raises:
|
|
1154
1164
|
------
|
|
1155
1165
|
TypeError:
|
|
1156
1166
|
If an invalid number of arguments is passed or if the types of the arguments
|
|
1157
1167
|
are invalid.
|
|
1158
1168
|
|
|
1159
|
-
Warns
|
|
1169
|
+
Warns:
|
|
1160
1170
|
-----
|
|
1161
1171
|
RuntimeWarning:
|
|
1162
1172
|
If any of the sides to which the border is applied have been merged.
|
|
1163
|
-
"""
|
|
1173
|
+
"""
|
|
1164
1174
|
(row, col, *args) = self._validate_cell_coords(*args)
|
|
1165
1175
|
if len(args) == 2:
|
|
1166
1176
|
(side, border_value) = args
|
|
@@ -1168,13 +1178,16 @@ class Table(Cacheable): # noqa: F811
|
|
|
1168
1178
|
elif len(args) == 3:
|
|
1169
1179
|
(side, border_value, length) = args
|
|
1170
1180
|
else:
|
|
1171
|
-
|
|
1181
|
+
msg = "invalid number of arguments to border_value()"
|
|
1182
|
+
raise TypeError(msg)
|
|
1172
1183
|
|
|
1173
1184
|
if not isinstance(border_value, Border):
|
|
1174
|
-
|
|
1185
|
+
msg = "border value must be a Border object"
|
|
1186
|
+
raise TypeError(msg)
|
|
1175
1187
|
|
|
1176
1188
|
if not isinstance(length, int):
|
|
1177
|
-
|
|
1189
|
+
msg = "border length must be an int"
|
|
1190
|
+
raise TypeError(msg)
|
|
1178
1191
|
|
|
1179
1192
|
if isinstance(side, list):
|
|
1180
1193
|
for s in side:
|
|
@@ -1213,13 +1226,13 @@ class Table(Cacheable): # noqa: F811
|
|
|
1213
1226
|
for border_row_num in range(row, row + length):
|
|
1214
1227
|
self._model.set_cell_border(self._table_id, border_row_num, col, side, border_value)
|
|
1215
1228
|
else:
|
|
1216
|
-
|
|
1229
|
+
msg = "side must be a valid border segment"
|
|
1230
|
+
raise TypeError(msg)
|
|
1217
1231
|
|
|
1218
1232
|
self._model.add_stroke(self._table_id, row, col, side, border_value, length)
|
|
1219
1233
|
|
|
1220
1234
|
def set_cell_formatting(self, *args: str, **kwargs) -> None:
|
|
1221
|
-
r"""
|
|
1222
|
-
Set the data format for a cell.
|
|
1235
|
+
r"""Set the data format for a cell.
|
|
1223
1236
|
|
|
1224
1237
|
Cell references can be **row-column** offsers or Excel/Numbers-style **A1** notation.
|
|
1225
1238
|
|
|
@@ -1382,9 +1395,11 @@ class Table(Cacheable): # noqa: F811
|
|
|
1382
1395
|
if len(args) == 1:
|
|
1383
1396
|
format_type = args[0]
|
|
1384
1397
|
elif len(args) > 1:
|
|
1385
|
-
|
|
1398
|
+
msg = "too many positional arguments to set_cell_formatting"
|
|
1399
|
+
raise TypeError(msg)
|
|
1386
1400
|
else:
|
|
1387
|
-
|
|
1401
|
+
msg = "no type defined for cell format"
|
|
1402
|
+
raise TypeError(msg)
|
|
1388
1403
|
|
|
1389
1404
|
if format_type == "custom":
|
|
1390
1405
|
self._set_cell_custom_format(row, col, **kwargs)
|
|
@@ -1393,24 +1408,28 @@ class Table(Cacheable): # noqa: F811
|
|
|
1393
1408
|
|
|
1394
1409
|
def _set_cell_custom_format(self, row: int, col: int, **kwargs) -> None:
|
|
1395
1410
|
if "format" not in kwargs:
|
|
1396
|
-
|
|
1411
|
+
msg = "no format provided for custom format"
|
|
1412
|
+
raise TypeError(msg)
|
|
1397
1413
|
|
|
1398
1414
|
custom_format = kwargs["format"]
|
|
1399
1415
|
if isinstance(custom_format, CustomFormatting):
|
|
1400
1416
|
custom_format = kwargs["format"]
|
|
1401
1417
|
elif isinstance(custom_format, str):
|
|
1402
1418
|
if custom_format not in self._model.custom_formats:
|
|
1403
|
-
|
|
1419
|
+
msg = f"format '{custom_format}' does not exist"
|
|
1420
|
+
raise IndexError(msg)
|
|
1404
1421
|
custom_format = self._model.custom_formats[custom_format]
|
|
1405
1422
|
else:
|
|
1406
|
-
|
|
1423
|
+
msg = "format must be a CustomFormatting object or format name"
|
|
1424
|
+
raise TypeError(msg)
|
|
1407
1425
|
|
|
1408
1426
|
cell = self._data[row][col]
|
|
1409
1427
|
type_name = type(cell).__name__
|
|
1410
1428
|
format_type_name = custom_format.type.name.lower()
|
|
1411
1429
|
if type_name not in CUSTOM_FORMATTING_ALLOWED_CELLS[format_type_name]:
|
|
1430
|
+
msg = f"cannot use {format_type_name} formatting for cells of type {type_name}"
|
|
1412
1431
|
raise TypeError(
|
|
1413
|
-
|
|
1432
|
+
msg,
|
|
1414
1433
|
)
|
|
1415
1434
|
|
|
1416
1435
|
format_id = self._model.custom_format_id(self._table_id, custom_format)
|
|
@@ -1420,13 +1439,15 @@ class Table(Cacheable): # noqa: F811
|
|
|
1420
1439
|
try:
|
|
1421
1440
|
format_type = FormattingType[format_type_name.upper()]
|
|
1422
1441
|
except (KeyError, AttributeError):
|
|
1423
|
-
|
|
1442
|
+
msg = f"unsuported cell format type '{format_type_name}'"
|
|
1443
|
+
raise TypeError(msg) from None
|
|
1424
1444
|
|
|
1425
1445
|
cell = self._data[row][col]
|
|
1426
1446
|
type_name = type(cell).__name__
|
|
1427
1447
|
if type_name not in FORMATTING_ALLOWED_CELLS[format_type_name]:
|
|
1448
|
+
msg = f"cannot use {format_type_name} formatting for cells of type {type_name}"
|
|
1428
1449
|
raise TypeError(
|
|
1429
|
-
|
|
1450
|
+
msg,
|
|
1430
1451
|
)
|
|
1431
1452
|
|
|
1432
1453
|
format = Formatting(type=format_type, **kwargs)
|
|
@@ -1435,31 +1456,32 @@ class Table(Cacheable): # noqa: F811
|
|
|
1435
1456
|
else:
|
|
1436
1457
|
control_id = None
|
|
1437
1458
|
|
|
1438
|
-
is_currency =
|
|
1459
|
+
is_currency = format_type == FormattingType.CURRENCY
|
|
1439
1460
|
if format_type_name in ["slider", "stepper"]:
|
|
1440
1461
|
if "control_format" in kwargs:
|
|
1441
1462
|
try:
|
|
1442
1463
|
control_format = kwargs["control_format"].name
|
|
1443
1464
|
number_format_type = FormattingType[control_format]
|
|
1444
1465
|
is_currency = (
|
|
1445
|
-
|
|
1446
|
-
if kwargs["control_format"] == ControlFormattingType.CURRENCY
|
|
1447
|
-
else False
|
|
1466
|
+
kwargs["control_format"] == ControlFormattingType.CURRENCY
|
|
1448
1467
|
)
|
|
1449
1468
|
except (KeyError, AttributeError):
|
|
1450
1469
|
control_format = kwargs["control_format"]
|
|
1470
|
+
msg = f"unsupported number format '{control_format}' for {format_type_name}"
|
|
1451
1471
|
raise TypeError(
|
|
1452
|
-
|
|
1472
|
+
msg,
|
|
1453
1473
|
) from None
|
|
1454
1474
|
else:
|
|
1455
1475
|
number_format_type = FormattingType.NUMBER
|
|
1456
1476
|
format_id = self._model.format_archive(self._table_id, number_format_type, format)
|
|
1457
1477
|
elif format_type_name == "popup":
|
|
1458
1478
|
if cell.value == "" and not format.allow_none:
|
|
1459
|
-
|
|
1479
|
+
msg = "none value not allowed for popup"
|
|
1480
|
+
raise IndexError(msg)
|
|
1460
1481
|
elif cell.value != "" and cell.value not in format.popup_values:
|
|
1482
|
+
msg = f"current cell value '{cell.value}' does not match any popup values"
|
|
1461
1483
|
raise IndexError(
|
|
1462
|
-
|
|
1484
|
+
msg,
|
|
1463
1485
|
)
|
|
1464
1486
|
|
|
1465
1487
|
popup_format_type = FormattingType.TEXT if isinstance(cell, TextCell) else True
|