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.
Files changed (34) 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 +150 -128
  5. numbers_parser/constants.py +5 -6
  6. numbers_parser/containers.py +11 -8
  7. numbers_parser/document.py +147 -108
  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 +17 -17
  25. numbers_parser/iwork.py +33 -27
  26. numbers_parser/model.py +94 -52
  27. numbers_parser/numbers_uuid.py +6 -4
  28. {numbers_parser-4.10.4.dist-info → numbers_parser-4.10.6.dist-info}/METADATA +9 -9
  29. numbers_parser-4.10.6.dist-info/RECORD +59 -0
  30. numbers_parser-4.10.4.dist-info/RECORD +0 -59
  31. numbers_parser/{mapping.py → generated/mapping.py} +24 -24
  32. {numbers_parser-4.10.4.dist-info → numbers_parser-4.10.6.dist-info}/LICENSE.rst +0 -0
  33. {numbers_parser-4.10.4.dist-info → numbers_parser-4.10.6.dist-info}/WHEEL +0 -0
  34. {numbers_parser-4.10.4.dist-info → numbers_parser-4.10.6.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,20 @@ 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,
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
- """ # noqa: E501
245
+ """
243
246
  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")
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
- raise TypeError("bg_image must be a BackgroundImage object")
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
- raise IndexError(f"format '{kwargs['name']}' already exists")
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
- raise TypeError(f"unsuported cell format type '{format_type}'") from None
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, table_name, from_table_id, x, y, num_rows, num_cols
406
- ) -> object: # noqa: PLR0913
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
- raise IndexError(f"table '{table_name}' already exists")
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, table_name, from_table_id, x, y, num_rows, num_cols
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): # noqa: F811
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
- raise ValueError("Number of headers cannot be negative")
508
+ msg = "Number of headers cannot be negative"
509
+ raise ValueError(msg)
492
510
  elif num_headers > self.num_rows:
493
- raise ValueError("Number of headers cannot exceed the number of rows")
511
+ msg = "Number of headers cannot exceed the number of rows"
512
+ raise ValueError(msg)
494
513
  elif num_headers > MAX_HEADER_COUNT:
495
- raise ValueError(f"Number of headers cannot exceed {MAX_HEADER_COUNT} rows")
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
- raise ValueError("Number of headers cannot be negative")
540
+ msg = "Number of headers cannot be negative"
541
+ raise ValueError(msg)
523
542
  elif num_headers > self.num_cols:
524
- raise ValueError("Number of headers cannot exceed the number of columns")
543
+ msg = "Number of headers cannot exceed the number of columns"
544
+ raise ValueError(msg)
525
545
  elif num_headers > MAX_HEADER_COUNT:
526
- raise ValueError(f"Number of headers cannot exceed {MAX_HEADER_COUNT} columns")
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(list(merge_cells))
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
- """ # noqa: E501
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
- raise IndexError(f"row {row} out of range")
694
+ msg = f"row {row} out of range"
695
+ raise IndexError(msg)
677
696
  if col >= self.num_cols or col < 0:
678
- raise IndexError(f"column {col} out of range")
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
- raise IndexError(f"row {min_row} out of range")
751
+ msg = f"row {min_row} out of range"
752
+ raise IndexError(msg)
732
753
  if max_row > self.num_rows:
733
- raise IndexError(f"row {max_row} out of range")
754
+ msg = f"row {max_row} out of range"
755
+ raise IndexError(msg)
734
756
  if min_col < 0:
735
- raise IndexError(f"column {min_col} out of range")
757
+ msg = f"column {min_col} out of range"
758
+ raise IndexError(msg)
736
759
  if max_col > self.num_cols:
737
- raise IndexError(f"column {max_col} out of range")
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
- raise IndexError(f"row {min_row} out of range")
819
+ msg = f"row {min_row} out of range"
820
+ raise IndexError(msg)
796
821
  if max_row > self.num_rows:
797
- raise IndexError(f"row {max_row} out of range")
822
+ msg = f"row {max_row} out of range"
823
+ raise IndexError(msg)
798
824
  if min_col < 0:
799
- raise IndexError(f"column {min_col} out of range")
825
+ msg = f"column {min_col} out of range"
826
+ raise IndexError(msg)
800
827
  if max_col > self.num_cols:
801
- raise IndexError(f"column {max_col} out of range")
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
- raise IndexError(f"{row} exceeds maximum row {MAX_ROW_COUNT-1}")
849
+ msg = f"{row} exceeds maximum row {MAX_ROW_COUNT - 1}"
850
+ raise IndexError(msg)
822
851
  if col >= MAX_COL_COUNT:
823
- raise IndexError(f"{col} exceeds maximum column {MAX_COL_COUNT-1}")
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) + tuple(values)
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
- raise IndexError(f"style '{style}' does not exist")
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
- raise TypeError("style must be a Style object or style name")
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
- raise IndexError("Row number not in range for table")
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
- raise IndexError("Column number not in range for table")
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
- raise IndexError("Row number not in range for table")
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
- raise IndexError("Column number not in range for table")
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
- """ # noqa: E501
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
- raise TypeError("invalid number of arguments to border_value()")
1199
+ msg = "invalid number of arguments to border_value()"
1200
+ raise TypeError(msg)
1172
1201
 
1173
1202
  if not isinstance(border_value, Border):
1174
- raise TypeError("border value must be a Border object")
1203
+ msg = "border value must be a Border object"
1204
+ raise TypeError(msg)
1175
1205
 
1176
1206
  if not isinstance(length, int):
1177
- raise TypeError("border length must be an int")
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
- raise TypeError("side must be a valid border segment")
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
- raise TypeError("too many positional arguments to set_cell_formatting")
1416
+ msg = "too many positional arguments to set_cell_formatting"
1417
+ raise TypeError(msg)
1386
1418
  else:
1387
- raise TypeError("no type defined for cell format")
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
- raise TypeError("no format provided for custom format")
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
- raise IndexError(f"format '{custom_format}' does not exist")
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
- raise TypeError("format must be a CustomFormatting object or format name")
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
- f"cannot use {format_type_name} formatting for cells of type {type_name}"
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
- raise TypeError(f"unsuported cell format type '{format_type_name}'") from None
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
- f"cannot use {format_type_name} formatting for cells of type {type_name}"
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 = True if format_type == FormattingType.CURRENCY else False
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
- f"unsupported number format '{control_format}' for {format_type_name}"
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
- raise IndexError("none value not allowed for popup")
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
- f"current cell value '{cell.value}' does not match any popup values"
1501
+ msg,
1463
1502
  )
1464
1503
 
1465
1504
  popup_format_type = FormattingType.TEXT if isinstance(cell, TextCell) else True