numbers-parser 4.10.4__py3-none-any.whl → 4.10.6__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 +150 -128
- numbers_parser/constants.py +5 -6
- numbers_parser/containers.py +11 -8
- numbers_parser/document.py +147 -108
- 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 +17 -17
- numbers_parser/iwork.py +33 -27
- numbers_parser/model.py +94 -52
- numbers_parser/numbers_uuid.py +6 -4
- {numbers_parser-4.10.4.dist-info → numbers_parser-4.10.6.dist-info}/METADATA +9 -9
- numbers_parser-4.10.6.dist-info/RECORD +59 -0
- numbers_parser-4.10.4.dist-info/RECORD +0 -59
- numbers_parser/{mapping.py → generated/mapping.py} +24 -24
- {numbers_parser-4.10.4.dist-info → numbers_parser-4.10.6.dist-info}/LICENSE.rst +0 -0
- {numbers_parser-4.10.4.dist-info → numbers_parser-4.10.6.dist-info}/WHEEL +0 -0
- {numbers_parser-4.10.4.dist-info → numbers_parser-4.10.6.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,20 @@ class Document:
|
|
|
201
199
|
Table(
|
|
202
200
|
self._model,
|
|
203
201
|
self._model.add_table(
|
|
204
|
-
new_sheet_id,
|
|
202
|
+
new_sheet_id,
|
|
203
|
+
table_name,
|
|
204
|
+
prev_table_id,
|
|
205
|
+
0,
|
|
206
|
+
0,
|
|
207
|
+
num_rows,
|
|
208
|
+
num_cols,
|
|
205
209
|
),
|
|
206
|
-
)
|
|
210
|
+
),
|
|
207
211
|
)
|
|
208
212
|
self._sheets.append(new_sheet)
|
|
209
213
|
|
|
210
214
|
def add_style(self, **kwargs) -> Style:
|
|
211
|
-
r"""
|
|
212
|
-
Add a new style to the current document.
|
|
215
|
+
r"""Add a new style to the current document.
|
|
213
216
|
|
|
214
217
|
If no style name is provided, the next available numbered style
|
|
215
218
|
will be generated in the series ``Custom Style 1``, ``Custom Style 2``, etc.
|
|
@@ -239,13 +242,15 @@ class Document:
|
|
|
239
242
|
If ``font_size`` is not a ``float``, ``font_name`` is not a ``str``,
|
|
240
243
|
``bg_image`` is not a :py:class:`~numbers_parser.BackgroundImage`,
|
|
241
244
|
or if any of the ``bool`` parameters are invalid.
|
|
242
|
-
"""
|
|
245
|
+
"""
|
|
243
246
|
if "name" in kwargs and kwargs["name"] is not None and kwargs["name"] in self._model.styles:
|
|
244
|
-
|
|
247
|
+
msg = f"style '{kwargs['name']}' already exists"
|
|
248
|
+
raise IndexError(msg)
|
|
245
249
|
|
|
246
250
|
if "bg_image" in kwargs and kwargs["bg_image"] is not None:
|
|
247
251
|
if not isinstance(kwargs["bg_image"], BackgroundImage):
|
|
248
|
-
|
|
252
|
+
msg = "bg_image must be a BackgroundImage object"
|
|
253
|
+
raise TypeError(msg)
|
|
249
254
|
self._model.store_image((kwargs["bg_image"].data), kwargs["bg_image"].filename)
|
|
250
255
|
|
|
251
256
|
style = Style(**kwargs)
|
|
@@ -256,8 +261,7 @@ class Document:
|
|
|
256
261
|
return style
|
|
257
262
|
|
|
258
263
|
def add_custom_format(self, **kwargs) -> CustomFormatting:
|
|
259
|
-
r"""
|
|
260
|
-
Add a new custom format to the current document.
|
|
264
|
+
r"""Add a new custom format to the current document.
|
|
261
265
|
|
|
262
266
|
.. code-block:: python
|
|
263
267
|
|
|
@@ -308,14 +312,16 @@ class Document:
|
|
|
308
312
|
and kwargs["name"] is not None
|
|
309
313
|
and kwargs["name"] in self._model.custom_formats
|
|
310
314
|
):
|
|
311
|
-
|
|
315
|
+
msg = f"format '{kwargs['name']}' already exists"
|
|
316
|
+
raise IndexError(msg)
|
|
312
317
|
|
|
313
318
|
if "type" in kwargs:
|
|
314
319
|
format_type = kwargs["type"].upper()
|
|
315
320
|
try:
|
|
316
321
|
kwargs["type"] = CustomFormattingType[format_type]
|
|
317
322
|
except (KeyError, AttributeError):
|
|
318
|
-
|
|
323
|
+
msg = f"unsuported cell format type '{format_type}'"
|
|
324
|
+
raise TypeError(msg) from None
|
|
319
325
|
|
|
320
326
|
custom_format = CustomFormatting(**kwargs)
|
|
321
327
|
if custom_format.name is None:
|
|
@@ -330,7 +336,7 @@ class Document:
|
|
|
330
336
|
|
|
331
337
|
|
|
332
338
|
class Sheet:
|
|
333
|
-
def __init__(self, model, sheet_id):
|
|
339
|
+
def __init__(self, model, sheet_id) -> None:
|
|
334
340
|
self._sheet_id = sheet_id
|
|
335
341
|
self._model = model
|
|
336
342
|
refs = self._model.table_ids(self._sheet_id)
|
|
@@ -402,11 +408,18 @@ class Sheet:
|
|
|
402
408
|
return self._add_table(table_name, from_table_id, x, y, num_rows, num_cols)
|
|
403
409
|
|
|
404
410
|
def _add_table( # noqa: PLR0913
|
|
405
|
-
self,
|
|
406
|
-
|
|
411
|
+
self,
|
|
412
|
+
table_name,
|
|
413
|
+
from_table_id,
|
|
414
|
+
x,
|
|
415
|
+
y,
|
|
416
|
+
num_rows,
|
|
417
|
+
num_cols,
|
|
418
|
+
) -> object:
|
|
407
419
|
if table_name is not None:
|
|
408
420
|
if table_name in self._tables:
|
|
409
|
-
|
|
421
|
+
msg = f"table '{table_name}' already exists"
|
|
422
|
+
raise IndexError(msg)
|
|
410
423
|
else:
|
|
411
424
|
table_num = 1
|
|
412
425
|
while f"table {table_num}" in self._tables:
|
|
@@ -414,14 +427,20 @@ class Sheet:
|
|
|
414
427
|
table_name = f"Table {table_num}"
|
|
415
428
|
|
|
416
429
|
new_table_id = self._model.add_table(
|
|
417
|
-
self._sheet_id,
|
|
430
|
+
self._sheet_id,
|
|
431
|
+
table_name,
|
|
432
|
+
from_table_id,
|
|
433
|
+
x,
|
|
434
|
+
y,
|
|
435
|
+
num_rows,
|
|
436
|
+
num_cols,
|
|
418
437
|
)
|
|
419
438
|
self._tables.append(Table(self._model, new_table_id))
|
|
420
439
|
return self._tables[-1]
|
|
421
440
|
|
|
422
441
|
|
|
423
|
-
class Table(Cacheable):
|
|
424
|
-
def __init__(self, model, table_id):
|
|
442
|
+
class Table(Cacheable):
|
|
443
|
+
def __init__(self, model, table_id) -> None:
|
|
425
444
|
super().__init__()
|
|
426
445
|
self._model = model
|
|
427
446
|
self._table_id = table_id
|
|
@@ -466,12 +485,10 @@ class Table(Cacheable): # noqa: F811
|
|
|
466
485
|
|
|
467
486
|
@property
|
|
468
487
|
def num_header_rows(self) -> int:
|
|
469
|
-
"""
|
|
470
|
-
int: The number of header rows.
|
|
488
|
+
"""int: The number of header rows.
|
|
471
489
|
|
|
472
490
|
Example
|
|
473
491
|
-------
|
|
474
|
-
|
|
475
492
|
.. code-block:: python
|
|
476
493
|
|
|
477
494
|
# Add an extra header row
|
|
@@ -488,21 +505,22 @@ class Table(Cacheable): # noqa: F811
|
|
|
488
505
|
@num_header_rows.setter
|
|
489
506
|
def num_header_rows(self, num_headers: int):
|
|
490
507
|
if num_headers < 0:
|
|
491
|
-
|
|
508
|
+
msg = "Number of headers cannot be negative"
|
|
509
|
+
raise ValueError(msg)
|
|
492
510
|
elif num_headers > self.num_rows:
|
|
493
|
-
|
|
511
|
+
msg = "Number of headers cannot exceed the number of rows"
|
|
512
|
+
raise ValueError(msg)
|
|
494
513
|
elif num_headers > MAX_HEADER_COUNT:
|
|
495
|
-
|
|
514
|
+
msg = f"Number of headers cannot exceed {MAX_HEADER_COUNT} rows"
|
|
515
|
+
raise ValueError(msg)
|
|
496
516
|
return self._model.num_header_rows(self._table_id, num_headers)
|
|
497
517
|
|
|
498
518
|
@property
|
|
499
519
|
def num_header_cols(self) -> int:
|
|
500
|
-
"""
|
|
501
|
-
int: The number of header columns.
|
|
520
|
+
"""int: The number of header columns.
|
|
502
521
|
|
|
503
522
|
Example
|
|
504
523
|
-------
|
|
505
|
-
|
|
506
524
|
.. code-block:: python
|
|
507
525
|
|
|
508
526
|
# Add an extra header column
|
|
@@ -519,11 +537,14 @@ class Table(Cacheable): # noqa: F811
|
|
|
519
537
|
@num_header_cols.setter
|
|
520
538
|
def num_header_cols(self, num_headers: int):
|
|
521
539
|
if num_headers < 0:
|
|
522
|
-
|
|
540
|
+
msg = "Number of headers cannot be negative"
|
|
541
|
+
raise ValueError(msg)
|
|
523
542
|
elif num_headers > self.num_cols:
|
|
524
|
-
|
|
543
|
+
msg = "Number of headers cannot exceed the number of columns"
|
|
544
|
+
raise ValueError(msg)
|
|
525
545
|
elif num_headers > MAX_HEADER_COUNT:
|
|
526
|
-
|
|
546
|
+
msg = f"Number of headers cannot exceed {MAX_HEADER_COUNT} columns"
|
|
547
|
+
raise ValueError(msg)
|
|
527
548
|
return self._model.num_header_cols(self._table_id, num_headers)
|
|
528
549
|
|
|
529
550
|
@property
|
|
@@ -536,9 +557,8 @@ class Table(Cacheable): # noqa: F811
|
|
|
536
557
|
"""int: The table's width in points."""
|
|
537
558
|
return self._model.table_width(self._table_id)
|
|
538
559
|
|
|
539
|
-
def row_height(self, row: int, height: int = None) -> int:
|
|
540
|
-
"""
|
|
541
|
-
The height of a table row in points.
|
|
560
|
+
def row_height(self, row: int, height: Optional[int] = None) -> int:
|
|
561
|
+
"""The height of a table row in points.
|
|
542
562
|
|
|
543
563
|
.. code-block:: python
|
|
544
564
|
|
|
@@ -559,7 +579,7 @@ class Table(Cacheable): # noqa: F811
|
|
|
559
579
|
"""
|
|
560
580
|
return self._model.row_height(self._table_id, row, height)
|
|
561
581
|
|
|
562
|
-
def col_width(self, col: int, width: int = None) -> int:
|
|
582
|
+
def col_width(self, col: int, width: Optional[int] = None) -> int:
|
|
563
583
|
"""The width of a table column in points.
|
|
564
584
|
|
|
565
585
|
Parameters
|
|
@@ -605,7 +625,6 @@ class Table(Cacheable): # noqa: F811
|
|
|
605
625
|
|
|
606
626
|
Example
|
|
607
627
|
-------
|
|
608
|
-
|
|
609
628
|
.. code-block:: python
|
|
610
629
|
|
|
611
630
|
>>> table.merge_ranges
|
|
@@ -621,11 +640,10 @@ class Table(Cacheable): # noqa: F811
|
|
|
621
640
|
if cell.is_merged:
|
|
622
641
|
size = cell.size
|
|
623
642
|
merge_cells.add(xl_range(row, col, row + size[0] - 1, col + size[1] - 1))
|
|
624
|
-
return sorted(
|
|
643
|
+
return sorted(merge_cells)
|
|
625
644
|
|
|
626
645
|
def cell(self, *args) -> Union[Cell, MergedCell]:
|
|
627
|
-
"""
|
|
628
|
-
Return a single cell in the table.
|
|
646
|
+
"""Return a single cell in the table.
|
|
629
647
|
|
|
630
648
|
The ``cell()`` method supports two forms of notation to designate the position
|
|
631
649
|
of cells: **Row-column** notation and **A1** notation:
|
|
@@ -664,7 +682,7 @@ class Table(Cacheable): # noqa: F811
|
|
|
664
682
|
<numbers_parser.cell.TextCell object at 0x105a80b90>
|
|
665
683
|
>>> table.cell("B2").value
|
|
666
684
|
1234.50
|
|
667
|
-
"""
|
|
685
|
+
"""
|
|
668
686
|
if isinstance(args[0], str):
|
|
669
687
|
(row, col) = xl_cell_to_rowcol(args[0])
|
|
670
688
|
elif len(args) != 2:
|
|
@@ -673,9 +691,11 @@ class Table(Cacheable): # noqa: F811
|
|
|
673
691
|
(row, col) = args
|
|
674
692
|
|
|
675
693
|
if row >= self.num_rows or row < 0:
|
|
676
|
-
|
|
694
|
+
msg = f"row {row} out of range"
|
|
695
|
+
raise IndexError(msg)
|
|
677
696
|
if col >= self.num_cols or col < 0:
|
|
678
|
-
|
|
697
|
+
msg = f"column {col} out of range"
|
|
698
|
+
raise IndexError(msg)
|
|
679
699
|
|
|
680
700
|
return self._data[row][col]
|
|
681
701
|
|
|
@@ -728,13 +748,17 @@ class Table(Cacheable): # noqa: F811
|
|
|
728
748
|
max_col = max_col or self.num_cols - 1
|
|
729
749
|
|
|
730
750
|
if min_row < 0:
|
|
731
|
-
|
|
751
|
+
msg = f"row {min_row} out of range"
|
|
752
|
+
raise IndexError(msg)
|
|
732
753
|
if max_row > self.num_rows:
|
|
733
|
-
|
|
754
|
+
msg = f"row {max_row} out of range"
|
|
755
|
+
raise IndexError(msg)
|
|
734
756
|
if min_col < 0:
|
|
735
|
-
|
|
757
|
+
msg = f"column {min_col} out of range"
|
|
758
|
+
raise IndexError(msg)
|
|
736
759
|
if max_col > self.num_cols:
|
|
737
|
-
|
|
760
|
+
msg = f"column {max_col} out of range"
|
|
761
|
+
raise IndexError(msg)
|
|
738
762
|
|
|
739
763
|
rows = self.rows()
|
|
740
764
|
for row in range(min_row, max_row + 1):
|
|
@@ -792,13 +816,17 @@ class Table(Cacheable): # noqa: F811
|
|
|
792
816
|
max_col = max_col or self.num_cols - 1
|
|
793
817
|
|
|
794
818
|
if min_row < 0:
|
|
795
|
-
|
|
819
|
+
msg = f"row {min_row} out of range"
|
|
820
|
+
raise IndexError(msg)
|
|
796
821
|
if max_row > self.num_rows:
|
|
797
|
-
|
|
822
|
+
msg = f"row {max_row} out of range"
|
|
823
|
+
raise IndexError(msg)
|
|
798
824
|
if min_col < 0:
|
|
799
|
-
|
|
825
|
+
msg = f"column {min_col} out of range"
|
|
826
|
+
raise IndexError(msg)
|
|
800
827
|
if max_col > self.num_cols:
|
|
801
|
-
|
|
828
|
+
msg = f"column {max_col} out of range"
|
|
829
|
+
raise IndexError(msg)
|
|
802
830
|
|
|
803
831
|
rows = self.rows()
|
|
804
832
|
for col in range(min_col, max_col + 1):
|
|
@@ -818,9 +846,11 @@ class Table(Cacheable): # noqa: F811
|
|
|
818
846
|
values = args[2:]
|
|
819
847
|
|
|
820
848
|
if row >= MAX_ROW_COUNT:
|
|
821
|
-
|
|
849
|
+
msg = f"{row} exceeds maximum row {MAX_ROW_COUNT - 1}"
|
|
850
|
+
raise IndexError(msg)
|
|
822
851
|
if col >= MAX_COL_COUNT:
|
|
823
|
-
|
|
852
|
+
msg = f"{col} exceeds maximum column {MAX_COL_COUNT - 1}"
|
|
853
|
+
raise IndexError(msg)
|
|
824
854
|
|
|
825
855
|
for _ in range(self.num_rows, row + 1):
|
|
826
856
|
self.add_row()
|
|
@@ -828,11 +858,10 @@ class Table(Cacheable): # noqa: F811
|
|
|
828
858
|
for _ in range(self.num_cols, col + 1):
|
|
829
859
|
self.add_column()
|
|
830
860
|
|
|
831
|
-
return (row, col
|
|
861
|
+
return (row, col, *tuple(values))
|
|
832
862
|
|
|
833
863
|
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.
|
|
864
|
+
"""Write a value to a cell and update the style/cell type.
|
|
836
865
|
|
|
837
866
|
The ``write()`` method supports two forms of notation to designate the position
|
|
838
867
|
of cells: **Row-column** notation and **A1** notation:
|
|
@@ -849,7 +878,6 @@ class Table(Cacheable): # noqa: F811
|
|
|
849
878
|
|
|
850
879
|
Parameters
|
|
851
880
|
----------
|
|
852
|
-
|
|
853
881
|
row: int
|
|
854
882
|
The row number (zero indexed)
|
|
855
883
|
col: int
|
|
@@ -894,10 +922,12 @@ class Table(Cacheable): # noqa: F811
|
|
|
894
922
|
self._data[row][col]._style = style
|
|
895
923
|
elif isinstance(style, str):
|
|
896
924
|
if style not in self._model.styles:
|
|
897
|
-
|
|
925
|
+
msg = f"style '{style}' does not exist"
|
|
926
|
+
raise IndexError(msg)
|
|
898
927
|
self._data[row][col]._style = self._model.styles[style]
|
|
899
928
|
else:
|
|
900
|
-
|
|
929
|
+
msg = "style must be a Style object or style name"
|
|
930
|
+
raise TypeError(msg)
|
|
901
931
|
|
|
902
932
|
def add_row(
|
|
903
933
|
self,
|
|
@@ -905,8 +935,7 @@ class Table(Cacheable): # noqa: F811
|
|
|
905
935
|
start_row: Optional[Union[int, None]] = None,
|
|
906
936
|
default: Optional[Union[str, int, float, bool, DateTime, Duration]] = None,
|
|
907
937
|
) -> None:
|
|
908
|
-
"""
|
|
909
|
-
Add or insert rows to the table.
|
|
938
|
+
"""Add or insert rows to the table.
|
|
910
939
|
|
|
911
940
|
Parameters
|
|
912
941
|
----------
|
|
@@ -934,7 +963,8 @@ class Table(Cacheable): # noqa: F811
|
|
|
934
963
|
If the default value is unsupported by :py:meth:`numbers_parser.Table.write`.
|
|
935
964
|
"""
|
|
936
965
|
if start_row is not None and (start_row < 0 or start_row >= self.num_rows):
|
|
937
|
-
|
|
966
|
+
msg = "Row number not in range for table"
|
|
967
|
+
raise IndexError(msg)
|
|
938
968
|
|
|
939
969
|
if start_row is None:
|
|
940
970
|
start_row = self.num_rows
|
|
@@ -959,8 +989,7 @@ class Table(Cacheable): # noqa: F811
|
|
|
959
989
|
start_col: Optional[Union[int, None]] = None,
|
|
960
990
|
default: Optional[Union[str, int, float, bool, DateTime, Duration]] = None,
|
|
961
991
|
) -> None:
|
|
962
|
-
"""
|
|
963
|
-
Add or insert columns to the table.
|
|
992
|
+
"""Add or insert columns to the table.
|
|
964
993
|
|
|
965
994
|
Parameters
|
|
966
995
|
----------
|
|
@@ -988,7 +1017,8 @@ class Table(Cacheable): # noqa: F811
|
|
|
988
1017
|
If the default value is unsupported by :py:meth:`numbers_parser.Table.write`.
|
|
989
1018
|
"""
|
|
990
1019
|
if start_col is not None and (start_col < 0 or start_col >= self.num_cols):
|
|
991
|
-
|
|
1020
|
+
msg = "Column number not in range for table"
|
|
1021
|
+
raise IndexError(msg)
|
|
992
1022
|
|
|
993
1023
|
if start_col is None:
|
|
994
1024
|
start_col = self.num_cols
|
|
@@ -1010,8 +1040,7 @@ class Table(Cacheable): # noqa: F811
|
|
|
1010
1040
|
num_rows: Optional[int] = 1,
|
|
1011
1041
|
start_row: Optional[Union[int, None]] = None,
|
|
1012
1042
|
) -> None:
|
|
1013
|
-
"""
|
|
1014
|
-
Delete rows from the table.
|
|
1043
|
+
"""Delete rows from the table.
|
|
1015
1044
|
|
|
1016
1045
|
Parameters
|
|
1017
1046
|
----------
|
|
@@ -1033,7 +1062,8 @@ class Table(Cacheable): # noqa: F811
|
|
|
1033
1062
|
If the start_row is out of range for the table.
|
|
1034
1063
|
"""
|
|
1035
1064
|
if start_row is not None and (start_row < 0 or start_row >= self.num_rows):
|
|
1036
|
-
|
|
1065
|
+
msg = "Row number not in range for table"
|
|
1066
|
+
raise IndexError(msg)
|
|
1037
1067
|
|
|
1038
1068
|
if start_row is not None:
|
|
1039
1069
|
del self._data[start_row : start_row + num_rows]
|
|
@@ -1048,8 +1078,7 @@ class Table(Cacheable): # noqa: F811
|
|
|
1048
1078
|
num_cols: Optional[int] = 1,
|
|
1049
1079
|
start_col: Optional[Union[int, None]] = None,
|
|
1050
1080
|
) -> None:
|
|
1051
|
-
"""
|
|
1052
|
-
Add or delete columns columns from the table.
|
|
1081
|
+
"""Add or delete columns columns from the table.
|
|
1053
1082
|
|
|
1054
1083
|
Parameters
|
|
1055
1084
|
----------
|
|
@@ -1065,7 +1094,8 @@ class Table(Cacheable): # noqa: F811
|
|
|
1065
1094
|
If the start_col is out of range for the table.
|
|
1066
1095
|
"""
|
|
1067
1096
|
if start_col is not None and (start_col < 0 or start_col >= self.num_cols):
|
|
1068
|
-
|
|
1097
|
+
msg = "Column number not in range for table"
|
|
1098
|
+
raise IndexError(msg)
|
|
1069
1099
|
|
|
1070
1100
|
for row in range(self.num_rows):
|
|
1071
1101
|
if start_col is not None:
|
|
@@ -1077,8 +1107,7 @@ class Table(Cacheable): # noqa: F811
|
|
|
1077
1107
|
self._model.number_of_columns(self._table_id, self.num_cols)
|
|
1078
1108
|
|
|
1079
1109
|
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.
|
|
1110
|
+
"""Convert a cell range or list of cell ranges into merged cells.
|
|
1082
1111
|
|
|
1083
1112
|
Parameters
|
|
1084
1113
|
----------
|
|
@@ -1119,8 +1148,7 @@ class Table(Cacheable): # noqa: F811
|
|
|
1119
1148
|
cell._set_merge(merge_cells.get((row, col)))
|
|
1120
1149
|
|
|
1121
1150
|
def set_cell_border(self, *args):
|
|
1122
|
-
"""
|
|
1123
|
-
Set the borders for a cell.
|
|
1151
|
+
"""Set the borders for a cell.
|
|
1124
1152
|
|
|
1125
1153
|
Cell references can be row-column offsers or Excel/Numbers-style A1 notation. Borders
|
|
1126
1154
|
can be applied to multiple sides of a cell by passing a list of sides. The name(s)
|
|
@@ -1160,7 +1188,7 @@ class Table(Cacheable): # noqa: F811
|
|
|
1160
1188
|
-----
|
|
1161
1189
|
RuntimeWarning:
|
|
1162
1190
|
If any of the sides to which the border is applied have been merged.
|
|
1163
|
-
"""
|
|
1191
|
+
"""
|
|
1164
1192
|
(row, col, *args) = self._validate_cell_coords(*args)
|
|
1165
1193
|
if len(args) == 2:
|
|
1166
1194
|
(side, border_value) = args
|
|
@@ -1168,13 +1196,16 @@ class Table(Cacheable): # noqa: F811
|
|
|
1168
1196
|
elif len(args) == 3:
|
|
1169
1197
|
(side, border_value, length) = args
|
|
1170
1198
|
else:
|
|
1171
|
-
|
|
1199
|
+
msg = "invalid number of arguments to border_value()"
|
|
1200
|
+
raise TypeError(msg)
|
|
1172
1201
|
|
|
1173
1202
|
if not isinstance(border_value, Border):
|
|
1174
|
-
|
|
1203
|
+
msg = "border value must be a Border object"
|
|
1204
|
+
raise TypeError(msg)
|
|
1175
1205
|
|
|
1176
1206
|
if not isinstance(length, int):
|
|
1177
|
-
|
|
1207
|
+
msg = "border length must be an int"
|
|
1208
|
+
raise TypeError(msg)
|
|
1178
1209
|
|
|
1179
1210
|
if isinstance(side, list):
|
|
1180
1211
|
for s in side:
|
|
@@ -1213,13 +1244,13 @@ class Table(Cacheable): # noqa: F811
|
|
|
1213
1244
|
for border_row_num in range(row, row + length):
|
|
1214
1245
|
self._model.set_cell_border(self._table_id, border_row_num, col, side, border_value)
|
|
1215
1246
|
else:
|
|
1216
|
-
|
|
1247
|
+
msg = "side must be a valid border segment"
|
|
1248
|
+
raise TypeError(msg)
|
|
1217
1249
|
|
|
1218
1250
|
self._model.add_stroke(self._table_id, row, col, side, border_value, length)
|
|
1219
1251
|
|
|
1220
1252
|
def set_cell_formatting(self, *args: str, **kwargs) -> None:
|
|
1221
|
-
r"""
|
|
1222
|
-
Set the data format for a cell.
|
|
1253
|
+
r"""Set the data format for a cell.
|
|
1223
1254
|
|
|
1224
1255
|
Cell references can be **row-column** offsers or Excel/Numbers-style **A1** notation.
|
|
1225
1256
|
|
|
@@ -1382,9 +1413,11 @@ class Table(Cacheable): # noqa: F811
|
|
|
1382
1413
|
if len(args) == 1:
|
|
1383
1414
|
format_type = args[0]
|
|
1384
1415
|
elif len(args) > 1:
|
|
1385
|
-
|
|
1416
|
+
msg = "too many positional arguments to set_cell_formatting"
|
|
1417
|
+
raise TypeError(msg)
|
|
1386
1418
|
else:
|
|
1387
|
-
|
|
1419
|
+
msg = "no type defined for cell format"
|
|
1420
|
+
raise TypeError(msg)
|
|
1388
1421
|
|
|
1389
1422
|
if format_type == "custom":
|
|
1390
1423
|
self._set_cell_custom_format(row, col, **kwargs)
|
|
@@ -1393,24 +1426,28 @@ class Table(Cacheable): # noqa: F811
|
|
|
1393
1426
|
|
|
1394
1427
|
def _set_cell_custom_format(self, row: int, col: int, **kwargs) -> None:
|
|
1395
1428
|
if "format" not in kwargs:
|
|
1396
|
-
|
|
1429
|
+
msg = "no format provided for custom format"
|
|
1430
|
+
raise TypeError(msg)
|
|
1397
1431
|
|
|
1398
1432
|
custom_format = kwargs["format"]
|
|
1399
1433
|
if isinstance(custom_format, CustomFormatting):
|
|
1400
1434
|
custom_format = kwargs["format"]
|
|
1401
1435
|
elif isinstance(custom_format, str):
|
|
1402
1436
|
if custom_format not in self._model.custom_formats:
|
|
1403
|
-
|
|
1437
|
+
msg = f"format '{custom_format}' does not exist"
|
|
1438
|
+
raise IndexError(msg)
|
|
1404
1439
|
custom_format = self._model.custom_formats[custom_format]
|
|
1405
1440
|
else:
|
|
1406
|
-
|
|
1441
|
+
msg = "format must be a CustomFormatting object or format name"
|
|
1442
|
+
raise TypeError(msg)
|
|
1407
1443
|
|
|
1408
1444
|
cell = self._data[row][col]
|
|
1409
1445
|
type_name = type(cell).__name__
|
|
1410
1446
|
format_type_name = custom_format.type.name.lower()
|
|
1411
1447
|
if type_name not in CUSTOM_FORMATTING_ALLOWED_CELLS[format_type_name]:
|
|
1448
|
+
msg = f"cannot use {format_type_name} formatting for cells of type {type_name}"
|
|
1412
1449
|
raise TypeError(
|
|
1413
|
-
|
|
1450
|
+
msg,
|
|
1414
1451
|
)
|
|
1415
1452
|
|
|
1416
1453
|
format_id = self._model.custom_format_id(self._table_id, custom_format)
|
|
@@ -1419,14 +1456,17 @@ class Table(Cacheable): # noqa: F811
|
|
|
1419
1456
|
def _set_cell_data_format(self, row: int, col: int, format_type_name: str, **kwargs) -> None:
|
|
1420
1457
|
try:
|
|
1421
1458
|
format_type = FormattingType[format_type_name.upper()]
|
|
1459
|
+
_ = FORMATTING_ALLOWED_CELLS[format_type_name]
|
|
1422
1460
|
except (KeyError, AttributeError):
|
|
1423
|
-
|
|
1461
|
+
msg = f"unsuported cell format type '{format_type_name}'"
|
|
1462
|
+
raise TypeError(msg) from None
|
|
1424
1463
|
|
|
1425
1464
|
cell = self._data[row][col]
|
|
1426
1465
|
type_name = type(cell).__name__
|
|
1427
1466
|
if type_name not in FORMATTING_ALLOWED_CELLS[format_type_name]:
|
|
1467
|
+
msg = f"cannot use {format_type_name} formatting for cells of type {type_name}"
|
|
1428
1468
|
raise TypeError(
|
|
1429
|
-
|
|
1469
|
+
msg,
|
|
1430
1470
|
)
|
|
1431
1471
|
|
|
1432
1472
|
format = Formatting(type=format_type, **kwargs)
|
|
@@ -1435,31 +1475,30 @@ class Table(Cacheable): # noqa: F811
|
|
|
1435
1475
|
else:
|
|
1436
1476
|
control_id = None
|
|
1437
1477
|
|
|
1438
|
-
is_currency =
|
|
1478
|
+
is_currency = format_type == FormattingType.CURRENCY
|
|
1439
1479
|
if format_type_name in ["slider", "stepper"]:
|
|
1440
1480
|
if "control_format" in kwargs:
|
|
1441
1481
|
try:
|
|
1442
1482
|
control_format = kwargs["control_format"].name
|
|
1443
1483
|
number_format_type = FormattingType[control_format]
|
|
1444
|
-
is_currency =
|
|
1445
|
-
True
|
|
1446
|
-
if kwargs["control_format"] == ControlFormattingType.CURRENCY
|
|
1447
|
-
else False
|
|
1448
|
-
)
|
|
1484
|
+
is_currency = kwargs["control_format"] == ControlFormattingType.CURRENCY
|
|
1449
1485
|
except (KeyError, AttributeError):
|
|
1450
1486
|
control_format = kwargs["control_format"]
|
|
1487
|
+
msg = f"unsupported number format '{control_format}' for {format_type_name}"
|
|
1451
1488
|
raise TypeError(
|
|
1452
|
-
|
|
1489
|
+
msg,
|
|
1453
1490
|
) from None
|
|
1454
1491
|
else:
|
|
1455
1492
|
number_format_type = FormattingType.NUMBER
|
|
1456
1493
|
format_id = self._model.format_archive(self._table_id, number_format_type, format)
|
|
1457
1494
|
elif format_type_name == "popup":
|
|
1458
1495
|
if cell.value == "" and not format.allow_none:
|
|
1459
|
-
|
|
1496
|
+
msg = "none value not allowed for popup"
|
|
1497
|
+
raise IndexError(msg)
|
|
1460
1498
|
elif cell.value != "" and cell.value not in format.popup_values:
|
|
1499
|
+
msg = f"current cell value '{cell.value}' does not match any popup values"
|
|
1461
1500
|
raise IndexError(
|
|
1462
|
-
|
|
1501
|
+
msg,
|
|
1463
1502
|
)
|
|
1464
1503
|
|
|
1465
1504
|
popup_format_type = FormattingType.TEXT if isinstance(cell, TextCell) else True
|