numbers-parser 4.10.4__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.
Files changed (32) hide show
  1. numbers_parser/__init__.py +1 -1
  2. numbers_parser/_cat_numbers.py +4 -4
  3. numbers_parser/_unpack_numbers.py +5 -5
  4. numbers_parser/cell.py +119 -119
  5. numbers_parser/constants.py +5 -6
  6. numbers_parser/containers.py +11 -8
  7. numbers_parser/document.py +135 -113
  8. numbers_parser/exceptions.py +0 -7
  9. numbers_parser/formula.py +3 -4
  10. numbers_parser/generated/TNArchives_pb2.py +24 -26
  11. numbers_parser/generated/TSAArchives_pb2.py +26 -28
  12. numbers_parser/generated/TSCEArchives_pb2.py +8 -10
  13. numbers_parser/generated/TSCHArchives_GEN_pb2.py +28 -34
  14. numbers_parser/generated/TSCHArchives_pb2.py +61 -65
  15. numbers_parser/generated/TSDArchives_pb2.py +100 -110
  16. numbers_parser/generated/TSKArchives_pb2.py +168 -170
  17. numbers_parser/generated/TSPArchiveMessages_pb2.py +32 -34
  18. numbers_parser/generated/TSPMessages_pb2.py +40 -40
  19. numbers_parser/generated/TSSArchives_pb2.py +36 -36
  20. numbers_parser/generated/TSTArchives_pb2.py +321 -325
  21. numbers_parser/generated/TSTStylePropertyArchiving_pb2.py +8 -10
  22. numbers_parser/generated/TSWPArchives_pb2.py +250 -286
  23. numbers_parser/generated/TSWPCommandArchives_pb2.py +95 -95
  24. numbers_parser/iwafile.py +16 -16
  25. numbers_parser/iwork.py +35 -29
  26. numbers_parser/model.py +64 -52
  27. numbers_parser/numbers_uuid.py +6 -4
  28. {numbers_parser-4.10.4.dist-info → numbers_parser-4.10.5.dist-info}/METADATA +7 -7
  29. {numbers_parser-4.10.4.dist-info → numbers_parser-4.10.5.dist-info}/RECORD +32 -32
  30. {numbers_parser-4.10.4.dist-info → numbers_parser-4.10.5.dist-info}/LICENSE.rst +0 -0
  31. {numbers_parser-4.10.4.dist-info → numbers_parser-4.10.5.dist-info}/WHEEL +0 -0
  32. {numbers_parser-4.10.4.dist-info → numbers_parser-4.10.5.dist-info}/entry_points.txt +0 -0
@@ -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
- raise IndexError(f"sheet '{sheet_name}' already exists")
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
- """ # noqa: E501
239
+ """
243
240
  if "name" in kwargs and kwargs["name"] is not None and kwargs["name"] in self._model.styles:
244
- raise IndexError(f"style '{kwargs['name']}' already exists")
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
- raise TypeError("bg_image must be a BackgroundImage object")
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
- raise IndexError(f"format '{kwargs['name']}' already exists")
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
- raise TypeError(f"unsuported cell format type '{format_type}'") from None
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: # noqa: PLR0913
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
- raise IndexError(f"table '{table_name}' already exists")
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): # noqa: F811
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
- raise ValueError("Number of headers cannot be negative")
490
+ msg = "Number of headers cannot be negative"
491
+ raise ValueError(msg)
492
492
  elif num_headers > self.num_rows:
493
- raise ValueError("Number of headers cannot exceed the number of rows")
493
+ msg = "Number of headers cannot exceed the number of rows"
494
+ raise ValueError(msg)
494
495
  elif num_headers > MAX_HEADER_COUNT:
495
- raise ValueError(f"Number of headers cannot exceed {MAX_HEADER_COUNT} rows")
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
- raise ValueError("Number of headers cannot be negative")
522
+ msg = "Number of headers cannot be negative"
523
+ raise ValueError(msg)
523
524
  elif num_headers > self.num_cols:
524
- raise ValueError("Number of headers cannot exceed the number of columns")
525
+ msg = "Number of headers cannot exceed the number of columns"
526
+ raise ValueError(msg)
525
527
  elif num_headers > MAX_HEADER_COUNT:
526
- raise ValueError(f"Number of headers cannot exceed {MAX_HEADER_COUNT} columns")
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(list(merge_cells))
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
- """ # noqa: E501
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
- raise IndexError(f"row {row} out of range")
676
+ msg = f"row {row} out of range"
677
+ raise IndexError(msg)
677
678
  if col >= self.num_cols or col < 0:
678
- raise IndexError(f"column {col} out of range")
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
- raise IndexError(f"row {min_row} out of range")
733
+ msg = f"row {min_row} out of range"
734
+ raise IndexError(msg)
732
735
  if max_row > self.num_rows:
733
- raise IndexError(f"row {max_row} out of range")
736
+ msg = f"row {max_row} out of range"
737
+ raise IndexError(msg)
734
738
  if min_col < 0:
735
- raise IndexError(f"column {min_col} out of range")
739
+ msg = f"column {min_col} out of range"
740
+ raise IndexError(msg)
736
741
  if max_col > self.num_cols:
737
- raise IndexError(f"column {max_col} out of range")
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
- raise IndexError(f"row {min_row} out of range")
801
+ msg = f"row {min_row} out of range"
802
+ raise IndexError(msg)
796
803
  if max_row > self.num_rows:
797
- raise IndexError(f"row {max_row} out of range")
804
+ msg = f"row {max_row} out of range"
805
+ raise IndexError(msg)
798
806
  if min_col < 0:
799
- raise IndexError(f"column {min_col} out of range")
807
+ msg = f"column {min_col} out of range"
808
+ raise IndexError(msg)
800
809
  if max_col > self.num_cols:
801
- raise IndexError(f"column {max_col} out of range")
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
- raise IndexError(f"{row} exceeds maximum row {MAX_ROW_COUNT-1}")
831
+ msg = f"{row} exceeds maximum row {MAX_ROW_COUNT - 1}"
832
+ raise IndexError(msg)
822
833
  if col >= MAX_COL_COUNT:
823
- raise IndexError(f"{col} exceeds maximum column {MAX_COL_COUNT-1}")
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) + tuple(values)
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
- raise IndexError(f"style '{style}' does not exist")
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
- raise TypeError("style must be a Style object or style name")
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
- raise IndexError("Row number not in range for table")
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
- raise IndexError("Column number not in range for table")
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
- raise IndexError("Row number not in range for table")
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
- raise IndexError("Column number not in range for table")
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
- """ # noqa: E501
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
- raise TypeError("invalid number of arguments to border_value()")
1181
+ msg = "invalid number of arguments to border_value()"
1182
+ raise TypeError(msg)
1172
1183
 
1173
1184
  if not isinstance(border_value, Border):
1174
- raise TypeError("border value must be a Border object")
1185
+ msg = "border value must be a Border object"
1186
+ raise TypeError(msg)
1175
1187
 
1176
1188
  if not isinstance(length, int):
1177
- raise TypeError("border length must be an int")
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
- raise TypeError("side must be a valid border segment")
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
- raise TypeError("too many positional arguments to set_cell_formatting")
1398
+ msg = "too many positional arguments to set_cell_formatting"
1399
+ raise TypeError(msg)
1386
1400
  else:
1387
- raise TypeError("no type defined for cell format")
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
- raise TypeError("no format provided for custom format")
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
- raise IndexError(f"format '{custom_format}' does not exist")
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
- raise TypeError("format must be a CustomFormatting object or format name")
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
- f"cannot use {format_type_name} formatting for cells of type {type_name}"
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
- raise TypeError(f"unsuported cell format type '{format_type_name}'") from None
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
- f"cannot use {format_type_name} formatting for cells of type {type_name}"
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 = True if format_type == FormattingType.CURRENCY else False
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
- True
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
- f"unsupported number format '{control_format}' for {format_type_name}"
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
- raise IndexError("none value not allowed for popup")
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
- f"current cell value '{cell.value}' does not match any popup values"
1484
+ msg,
1463
1485
  )
1464
1486
 
1465
1487
  popup_format_type = FormattingType.TEXT if isinstance(cell, TextCell) else True