numbers-parser 4.14.1__py3-none-any.whl → 4.14.3__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/model.py CHANGED
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import re
2
4
  from array import array
3
5
  from collections import defaultdict
@@ -5,7 +7,6 @@ from hashlib import sha1
5
7
  from math import floor
6
8
  from pathlib import Path
7
9
  from struct import pack
8
- from typing import Dict, List, Optional, Tuple, Union
9
10
 
10
11
  from numbers_parser.bullets import (
11
12
  BULLET_CONVERSION,
@@ -91,27 +92,27 @@ class MergeCells:
91
92
  def __init__(self) -> None:
92
93
  self._references = defaultdict(lambda: False)
93
94
 
94
- def add_reference(self, row: int, col: int, rect: Tuple):
95
+ def add_reference(self, row: int, col: int, rect: tuple) -> None:
95
96
  self._references[(row, col)] = MergeReference(*rect)
96
97
 
97
- def add_anchor(self, row: int, col: int, size: Tuple):
98
+ def add_anchor(self, row: int, col: int, size: tuple) -> None:
98
99
  self._references[(row, col)] = MergeAnchor(size)
99
100
 
100
- def is_merge_reference(self, row_col: Tuple) -> bool:
101
+ def is_merge_reference(self, row_col: tuple) -> bool:
101
102
  # defaultdict will default this to False for missing entries
102
103
  return isinstance(self._references[row_col], MergeReference)
103
104
 
104
- def is_merge_anchor(self, row_col: Tuple) -> bool:
105
+ def is_merge_anchor(self, row_col: tuple) -> bool:
105
106
  # defaultdict will default this to False for missing entries
106
107
  return isinstance(self._references[row_col], MergeAnchor)
107
108
 
108
- def get(self, row_col: Tuple) -> Union[MergeAnchor, MergeReference]:
109
+ def get(self, row_col: tuple) -> MergeAnchor | MergeReference:
109
110
  return self._references[row_col]
110
111
 
111
- def size(self, row_col: Tuple) -> Tuple:
112
+ def size(self, row_col: tuple) -> tuple:
112
113
  return self._references[row_col].size
113
114
 
114
- def rect(self, row_col: Tuple) -> Tuple:
115
+ def rect(self, row_col: tuple) -> tuple:
115
116
  return self._references[row_col].rect
116
117
 
117
118
  def merge_cells(self):
@@ -121,14 +122,14 @@ class MergeCells:
121
122
  class DataLists(Cacheable):
122
123
  """Model for TST.DataList with caching and key generation for new values."""
123
124
 
124
- def __init__(self, model: object, datalist_name: str, value_attr: Optional[str] = None) -> None:
125
+ def __init__(self, model: object, datalist_name: str, value_attr: str | None = None) -> None:
125
126
  self._model = model
126
127
  self._datalists = {}
127
128
  self._value_attr = value_attr
128
129
  self._datalist_name = datalist_name
129
130
 
130
131
  @cache()
131
- def add_table(self, table_id: int):
132
+ def add_table(self, table_id: int) -> None:
132
133
  """Cache a new datalist for a table if not already seen."""
133
134
  base_data_store = self._model.objects[table_id].base_data_store
134
135
  datalist_id = getattr(base_data_store, self._datalist_name).identifier
@@ -162,10 +163,9 @@ class DataLists(Cacheable):
162
163
  def value_key(self, value):
163
164
  if hasattr(value, "DESCRIPTOR"):
164
165
  return repr(value)
165
- else:
166
- return value
166
+ return value
167
167
 
168
- def init(self, table_id: int):
168
+ def init(self, table_id: int) -> None:
169
169
  """Remove all entries from a datalist."""
170
170
  self.add_table(table_id)
171
171
  self._datalists[table_id]["by_key"] = {}
@@ -176,7 +176,8 @@ class DataLists(Cacheable):
176
176
  clear_field_container(self._datalists[table_id]["datalist"].entries)
177
177
 
178
178
  def lookup_key(self, table_id: int, value) -> int:
179
- """Return the key associated with a value for a particular table entry.
179
+ """
180
+ Return the key associated with a value for a particular table entry.
180
181
  If the value is not in the datalist, allocate a new entry with the
181
182
  next available key.
182
183
  """
@@ -204,7 +205,8 @@ class DataLists(Cacheable):
204
205
 
205
206
 
206
207
  class _NumbersModel(Cacheable):
207
- """Loads all objects from Numbers document and provides decoding
208
+ """
209
+ Loads all objects from Numbers document and provides decoding
208
210
  methods for other classes in the module to abstract away the
209
211
  internal structures of Numbers document data structures.
210
212
 
@@ -248,13 +250,11 @@ class _NumbersModel(Cacheable):
248
250
  if value is None:
249
251
  if sheet_id not in self.objects:
250
252
  return None
251
- else:
252
- return self.objects[sheet_id].name
253
- else:
254
- self.objects[sheet_id].name = value
255
- return None
253
+ return self.objects[sheet_id].name
254
+ self.objects[sheet_id].name = value
255
+ return None
256
256
 
257
- def set_table_data(self, table_id: int, data: List):
257
+ def set_table_data(self, table_id: int, data: list) -> None:
258
258
  self._table_data[table_id] = data
259
259
 
260
260
  # Don't cache: new tables can be added at runtime
@@ -313,27 +313,25 @@ class _NumbersModel(Cacheable):
313
313
  def table_name(self, table_id, value=None):
314
314
  if value is None:
315
315
  return self.objects[table_id].table_name
316
- else:
317
- self.objects[table_id].table_name = value
318
- return None
316
+ self.objects[table_id].table_name = value
317
+ return None
319
318
 
320
- def table_name_enabled(self, table_id: int, enabled: Optional[bool] = None):
319
+ def table_name_enabled(self, table_id: int, enabled: bool | None = None):
321
320
  if enabled is not None:
322
321
  self.objects[table_id].table_name_enabled = enabled
323
322
  return None
324
- else:
325
- return self.objects[table_id].table_name_enabled
323
+ return self.objects[table_id].table_name_enabled
326
324
 
327
- def caption_enabled(self, table_id: int, enabled: Optional[bool] = None) -> bool:
325
+ def caption_enabled(self, table_id: int, enabled: bool | None = None) -> bool:
328
326
  table_info = self.objects[self.table_info_id(table_id)]
329
327
  if enabled is not None:
330
328
  table_info.super.caption_hidden = not enabled
331
- else:
332
- caption_info_id = table_info.super.caption.identifier
333
- caption_archive = self.objects[caption_info_id]
334
- if caption_archive.DESCRIPTOR.name == "StandinCaptionArchive":
335
- return False
336
- return not table_info.super.caption_hidden
329
+ return None
330
+ caption_info_id = table_info.super.caption.identifier
331
+ caption_archive = self.objects[caption_info_id]
332
+ if caption_archive.DESCRIPTOR.name == "StandinCaptionArchive":
333
+ return False
334
+ return not table_info.super.caption_hidden
337
335
 
338
336
  def find_style_id(self, style_substr: str):
339
337
  stylesheet = self.objects[self.stylesheet_id()]
@@ -344,18 +342,18 @@ class _NumbersModel(Cacheable):
344
342
 
345
343
  def caption_paragraph_style_id(self):
346
344
  style_map = {
347
- id: self.objects[id]
348
- for id in self.find_refs("ParagraphStyleArchive")
349
- if "Caption" in self.objects[id].super.name
345
+ x: self.objects[x]
346
+ for x in self.find_refs("ParagraphStyleArchive")
347
+ if "Caption" in self.objects[x].super.name
350
348
  }
351
- return list(style_map.keys())[0]
349
+ return next(iter(style_map.keys()))
352
350
 
353
351
  @cache(num_args=0)
354
352
  def stylesheet_id(self):
355
353
  return self.find_refs("StylesheetArchive")[0]
356
354
 
357
- def set_reference(self, obj: object, id: int):
358
- obj.MergeFrom(TSPMessages.Reference(identifier=id))
355
+ def set_reference(self, obj: object, ref_id: int) -> None:
356
+ obj.MergeFrom(TSPMessages.Reference(identifier=ref_id))
359
357
 
360
358
  def create_path_source_archive(self, table_id):
361
359
  box_size = 100.0
@@ -389,12 +387,12 @@ class _NumbersModel(Cacheable):
389
387
  type=TSPMessages.Path.ElementType.moveTo,
390
388
  points=[TSPMessages.Point(x=0.0, y=0.0)],
391
389
  ),
392
- ]
390
+ ],
393
391
  ),
394
392
  ),
395
393
  )
396
394
 
397
- def create_caption_archive(self, table_id):
395
+ def create_caption_archive(self, table_id) -> None:
398
396
  table_info_id = self.table_info_id(table_id)
399
397
  table_info = self.objects[table_info_id]
400
398
  caption_placement_id, _ = self.objects.create_object_from_dict(
@@ -421,16 +419,16 @@ class _NumbersModel(Cacheable):
421
419
  {
422
420
  "character_index": 0,
423
421
  "object": {"identifier": self.caption_paragraph_style_id()},
424
- }
425
- ]
422
+ },
423
+ ],
426
424
  },
427
425
  "table_list_style": {
428
426
  "entries": [
429
427
  {
430
428
  "character_index": 0,
431
429
  "object": {"identifier": self.find_style_id("liststyle")},
432
- }
433
- ]
430
+ },
431
+ ],
434
432
  },
435
433
  "table_para_starts": {"entries": [{"character_index": 0, "first": 0, "second": 0}]},
436
434
  "table_para_bidi": {"entries": [{"character_index": 0, "first": 0, "second": 0}]},
@@ -445,7 +443,9 @@ class _NumbersModel(Cacheable):
445
443
  self.caption_paragraph_style_id(),
446
444
  ]:
447
445
  self.add_component_reference(
448
- object_id, location="CalculationEngine", component_id=self.stylesheet_id()
446
+ object_id,
447
+ location="CalculationEngine",
448
+ component_id=self.stylesheet_id(),
449
449
  )
450
450
  caption_info.super.MergeFrom(
451
451
  TSWPArchives.ShapeInfoArchive(
@@ -458,18 +458,19 @@ class _NumbersModel(Cacheable):
458
458
  strokePatternOffsetDistance=0.0,
459
459
  pathsource=self.create_path_source_archive(table_id),
460
460
  ),
461
- )
461
+ ),
462
462
  )
463
463
 
464
464
  self.set_reference(table_info.super.caption, caption_info_id)
465
465
  component = self.metadata_component(self.calc_engine_id())
466
466
  component.object_uuid_map_entries.append(
467
467
  TSPArchiveMessages.ObjectUUIDMapEntry(
468
- identifier=caption_info_id, uuid=NumbersUUID().protobuf2
469
- )
468
+ identifier=caption_info_id,
469
+ uuid=NumbersUUID().protobuf2,
470
+ ),
470
471
  )
471
472
 
472
- def caption_text(self, table_id: int, caption: str = None) -> str:
473
+ def caption_text(self, table_id: int, caption: str | None = None) -> str:
473
474
  table_info = self.objects[self.table_info_id(table_id)]
474
475
  caption_info_id = table_info.super.caption.identifier
475
476
  caption_archive = self.objects[caption_info_id]
@@ -477,19 +478,18 @@ class _NumbersModel(Cacheable):
477
478
  if caption_archive.DESCRIPTOR.name == "StandinCaptionArchive":
478
479
  if caption is None:
479
480
  return "Caption"
480
- else:
481
- self.create_caption_archive(table_id)
482
- caption_info_id = table_info.super.caption.identifier
483
- caption_archive = self.objects[caption_info_id]
481
+ self.create_caption_archive(table_id)
482
+ caption_info_id = table_info.super.caption.identifier
483
+ caption_archive = self.objects[caption_info_id]
484
484
 
485
485
  caption_storage_id = caption_archive.super.owned_storage.identifier
486
486
  if caption is not None:
487
487
  clear_field_container(self.objects[caption_storage_id].text)
488
488
  self.objects[caption_storage_id].text.append(caption)
489
- elif len(self.objects[caption_storage_id].text) == 0:
489
+ return None
490
+ if len(self.objects[caption_storage_id].text) == 0:
490
491
  return "Caption"
491
- else:
492
- return self.objects[caption_storage_id].text[0]
492
+ return self.objects[caption_storage_id].text[0]
493
493
 
494
494
  @cache()
495
495
  def table_tiles(self, table_id):
@@ -511,17 +511,17 @@ class _NumbersModel(Cacheable):
511
511
  return self._table_formats.lookup_value(table_id, key).format
512
512
 
513
513
  @cache(num_args=3)
514
- def format_archive(self, table_id: int, format_type: FormattingType, format: Formatting):
514
+ def format_archive(self, table_id: int, format_type: FormattingType, formatting: Formatting):
515
515
  """Create a table format from a Formatting spec and return the table format ID."""
516
- attrs = {x: getattr(format, x) for x in ALLOWED_FORMATTING_PARAMETERS[format_type]}
516
+ attrs = {x: getattr(formatting, x) for x in ALLOWED_FORMATTING_PARAMETERS[format_type]}
517
517
  attrs["format_type"] = FORMAT_TYPE_MAP[format_type]
518
518
 
519
- format = TSKArchives.FormatStructArchive(**attrs)
520
- return self._table_formats.lookup_key(table_id, format)
519
+ format_archive = TSKArchives.FormatStructArchive(**attrs)
520
+ return self._table_formats.lookup_key(table_id, format_archive)
521
521
 
522
- def cell_popup_model(self, parent_id: int, format: Formatting):
522
+ def cell_popup_model(self, parent_id: int, formatting: Formatting):
523
523
  tsce_items = [{"cell_value_type": "NIL_TYPE"}]
524
- for item in format.popup_values:
524
+ for item in formatting.popup_values:
525
525
  if isinstance(item, str):
526
526
  tsce_items.append(
527
527
  {
@@ -550,7 +550,12 @@ class _NumbersModel(Cacheable):
550
550
  )
551
551
  return popup_menu_id
552
552
 
553
- def control_cell_archive(self, table_id: int, format_type: FormattingType, format: Formatting):
553
+ def control_cell_archive(
554
+ self,
555
+ table_id: int,
556
+ format_type: FormattingType,
557
+ formatting: Formatting,
558
+ ):
554
559
  """Create control cell archive from a Formatting spec and return the table format ID."""
555
560
  if format_type == FormattingType.TICKBOX:
556
561
  cell_spec = TSTArchives.CellSpecArchive(interaction_type=CellInteractionType.TOGGLE)
@@ -564,26 +569,26 @@ class _NumbersModel(Cacheable):
564
569
  elif format_type == FormattingType.SLIDER:
565
570
  cell_spec = TSTArchives.CellSpecArchive(
566
571
  interaction_type=CellInteractionType.SLIDER,
567
- range_control_min=format.minimum,
568
- range_control_max=format.maximum,
569
- range_control_inc=format.increment,
572
+ range_control_min=formatting.minimum,
573
+ range_control_max=formatting.maximum,
574
+ range_control_inc=formatting.increment,
570
575
  )
571
576
  else: # POPUP
572
- popup_id = self.cell_popup_model(self._control_specs.id(table_id), format)
577
+ popup_id = self.cell_popup_model(self._control_specs.id(table_id), formatting)
573
578
  cell_spec = TSTArchives.CellSpecArchive(
574
579
  interaction_type=CellInteractionType.POPUP,
575
580
  chooser_control_popup_model=TSPMessages.Reference(identifier=popup_id),
576
- chooser_control_start_w_first=not (format.allow_none),
581
+ chooser_control_start_w_first=not (formatting.allow_none),
577
582
  )
578
583
  return self._control_specs.lookup_key(table_id, cell_spec)
579
584
 
580
- def add_custom_decimal_format_archive(self, format: CustomFormatting) -> None:
585
+ def add_custom_decimal_format_archive(self, formatting: CustomFormatting) -> None:
581
586
  """Create a custom format from the format spec."""
582
- integer_format = format.integer_format
583
- decimal_format = format.decimal_format
584
- num_integers = format.num_integers
585
- num_decimals = format.num_decimals
586
- show_thousands_separator = format.show_thousands_separator
587
+ integer_format = formatting.integer_format
588
+ decimal_format = formatting.decimal_format
589
+ num_integers = formatting.num_integers
590
+ num_decimals = formatting.num_decimals
591
+ show_thousands_separator = formatting.show_thousands_separator
587
592
 
588
593
  if num_integers == 0:
589
594
  format_string = ""
@@ -618,7 +623,7 @@ class _NumbersModel(Cacheable):
618
623
  )
619
624
 
620
625
  format_archive = TSKArchives.CustomFormatArchive(
621
- name=format.name,
626
+ name=formatting.name,
622
627
  format_type_pre_bnc=FormatType.CUSTOM_NUMBER,
623
628
  format_type=FormatType.CUSTOM_NUMBER,
624
629
  default_format=TSKArchives.FormatStructArchive(
@@ -640,45 +645,49 @@ class _NumbersModel(Cacheable):
640
645
  use_accounting_style=False,
641
646
  ),
642
647
  )
643
- self.add_custom_format_archive(format, format_archive)
648
+ self.add_custom_format_archive(formatting, format_archive)
644
649
 
645
- def add_custom_datetime_format_archive(self, format: CustomFormatting) -> None:
650
+ def add_custom_datetime_format_archive(self, formatting: CustomFormatting) -> None:
646
651
  format_archive = TSKArchives.CustomFormatArchive(
647
- name=format.name,
652
+ name=formatting.name,
648
653
  format_type_pre_bnc=FormatType.CUSTOM_DATE,
649
654
  format_type=FormatType.CUSTOM_DATE,
650
655
  default_format=TSKArchives.FormatStructArchive(
651
- custom_format_string=format.format,
656
+ custom_format_string=formatting.format,
652
657
  format_type=FormatType.CUSTOM_DATE,
653
658
  ),
654
659
  )
655
- self.add_custom_format_archive(format, format_archive)
660
+ self.add_custom_format_archive(formatting, format_archive)
656
661
 
657
- def add_custom_format_archive(self, format: CustomFormatting, format_archive: object) -> None:
662
+ def add_custom_format_archive(
663
+ self,
664
+ formatting: CustomFormatting,
665
+ format_archive: object,
666
+ ) -> None:
658
667
  format_uuid = NumbersUUID().protobuf2
659
- self._custom_formats[format.name] = format
660
- self._custom_format_archives[format.name] = format_archive
661
- self._custom_format_uuids[format.name] = format_uuid
668
+ self._custom_formats[formatting.name] = formatting
669
+ self._custom_format_archives[formatting.name] = format_archive
670
+ self._custom_format_uuids[formatting.name] = format_uuid
662
671
 
663
672
  custom_format_list_id = self.objects[DOCUMENT_ID].super.custom_format_list.identifier
664
673
  custom_format_list = self.objects[custom_format_list_id]
665
674
  custom_format_list.custom_formats.append(format_archive)
666
675
  custom_format_list.uuids.append(format_uuid)
667
676
 
668
- def custom_format_id(self, table_id: int, format: CustomFormatting) -> int:
677
+ def custom_format_id(self, table_id: int, formatting: CustomFormatting) -> int:
669
678
  """Look up the custom format and return the format ID for the table."""
670
- format_type = CUSTOM_FORMAT_TYPE_MAP[format.type]
671
- format_uuid = self._custom_format_uuids[format.name]
679
+ format_type = CUSTOM_FORMAT_TYPE_MAP[formatting.type]
680
+ format_uuid = self._custom_format_uuids[formatting.name]
672
681
  custom_format = TSKArchives.FormatStructArchive(
673
682
  format_type=format_type,
674
683
  custom_uid=TSPMessages.UUID(lower=format_uuid.lower, upper=format_uuid.upper),
675
684
  )
676
685
  return self._table_formats.lookup_key(table_id, custom_format)
677
686
 
678
- def add_custom_text_format_archive(self, format: CustomFormatting) -> None:
679
- format_string = format.format.replace("%s", CUSTOM_TEXT_PLACEHOLDER)
687
+ def add_custom_text_format_archive(self, formatting: CustomFormatting) -> None:
688
+ format_string = formatting.format.replace("%s", CUSTOM_TEXT_PLACEHOLDER)
680
689
  format_archive = TSKArchives.CustomFormatArchive(
681
- name=format.name,
690
+ name=formatting.name,
682
691
  format_type_pre_bnc=FormatType.CUSTOM_TEXT,
683
692
  format_type=FormatType.CUSTOM_TEXT,
684
693
  default_format=TSKArchives.FormatStructArchive(
@@ -686,7 +695,7 @@ class _NumbersModel(Cacheable):
686
695
  format_type=FormatType.CUSTOM_TEXT,
687
696
  ),
688
697
  )
689
- self.add_custom_format_archive(format, format_archive)
698
+ self.add_custom_format_archive(formatting, format_archive)
690
699
 
691
700
  @cache(num_args=2)
692
701
  def table_style(self, table_id: int, key: int) -> str:
@@ -699,12 +708,13 @@ class _NumbersModel(Cacheable):
699
708
  """Return the string associated with a string ID for a particular table."""
700
709
  return self._table_strings.lookup_value(table_id, key).string
701
710
 
702
- def init_table_strings(self, table_id: int):
711
+ def init_table_strings(self, table_id: int) -> None:
703
712
  """Cache table strings reference and delete all existing keys/values."""
704
713
  self._table_strings.init(table_id)
705
714
 
706
715
  def table_string_key(self, table_id: int, value: str) -> int:
707
- """Return the key associated with a string for a particular table. If
716
+ """
717
+ Return the key associated with a string for a particular table. If
708
718
  the string is not in the strings table, allocate a new entry with the
709
719
  next available key.
710
720
  """
@@ -712,7 +722,8 @@ class _NumbersModel(Cacheable):
712
722
 
713
723
  @cache(num_args=0)
714
724
  def owner_id_map(self):
715
- """ "
725
+ """
726
+ "
716
727
  Extracts the mapping table from Owner IDs to UUIDs. Returns a
717
728
  dictionary mapping the owner ID int to a 128-bit UUID.
718
729
  """
@@ -789,8 +800,7 @@ class _NumbersModel(Cacheable):
789
800
  ce_id = self.find_refs("CalculationEngineArchive")
790
801
  if len(ce_id) == 0:
791
802
  return 0
792
- else:
793
- return ce_id[0]
803
+ return ce_id[0]
794
804
 
795
805
  @cache(num_args=0)
796
806
  def calc_engine(self):
@@ -798,11 +808,10 @@ class _NumbersModel(Cacheable):
798
808
  ce_id = self.calc_engine_id()
799
809
  if ce_id == 0:
800
810
  return None
801
- else:
802
- return self.objects[ce_id]
811
+ return self.objects[ce_id]
803
812
 
804
813
  @cache()
805
- def calculate_merge_cell_ranges(self, table_id):
814
+ def calculate_merge_cell_ranges(self, table_id) -> None:
806
815
  """Exract all the merge cell ranges for the Table."""
807
816
  # https://github.com/masaccio/numbers-parser/blob/main/doc/Numbers.md#merge-ranges
808
817
  owner_id_map = self.owner_id_map()
@@ -865,10 +874,11 @@ class _NumbersModel(Cacheable):
865
874
  for sheet_id in self.sheet_ids(): # pragma: no branch
866
875
  if table_id in self.table_ids(sheet_id):
867
876
  return sheet_id
877
+ return None
868
878
 
869
879
  @cache()
870
- def table_uuids_to_id(self, table_uuid) -> int:
871
- for sheet_id in self.sheet_ids(): # pragma: no branch
880
+ def table_uuids_to_id(self, table_uuid) -> int | None:
881
+ for sheet_id in self.sheet_ids(): # pragma: no branch # noqa: RET503
872
882
  for table_id in self.table_ids(sheet_id):
873
883
  if table_uuid == self.table_base_id(table_id):
874
884
  return table_id
@@ -891,12 +901,11 @@ class _NumbersModel(Cacheable):
891
901
 
892
902
  if node.HasField("AST_colon_tract"):
893
903
  return self.tract_to_row_col_ref(node, other_table_name, row, col)
894
- elif node.HasField("AST_row") and not node.HasField("AST_column"):
904
+ if node.HasField("AST_row") and not node.HasField("AST_column"):
895
905
  return node_to_row_ref(node, other_table_name, row)
896
- elif node.HasField("AST_column") and not node.HasField("AST_row"):
906
+ if node.HasField("AST_column") and not node.HasField("AST_row"):
897
907
  return node_to_col_ref(node, other_table_name, col)
898
- else:
899
- return node_to_row_col_ref(node, other_table_name, row, col)
908
+ return node_to_row_col_ref(node, other_table_name, row, col)
900
909
 
901
910
  def tract_to_row_col_ref(self, node: object, table_name: str, row: int, col: int) -> str:
902
911
  if node.AST_sticky_bits.begin_row_is_absolute:
@@ -933,8 +942,7 @@ class _NumbersModel(Cacheable):
933
942
  )
934
943
  if table_name is not None:
935
944
  return f"{table_name}::{begin_ref}:{end_ref}"
936
- else:
937
- return f"{begin_ref}:{end_ref}"
945
+ return f"{begin_ref}:{end_ref}"
938
946
 
939
947
  @cache()
940
948
  def formula_ast(self, table_id: int):
@@ -947,7 +955,7 @@ class _NumbersModel(Cacheable):
947
955
  return formulas
948
956
 
949
957
  @cache()
950
- def storage_buffers(self, table_id: int) -> List:
958
+ def storage_buffers(self, table_id: int) -> list:
951
959
  buffers = []
952
960
  for tile in self.table_tiles(table_id):
953
961
  if not tile.last_saved_in_BNC:
@@ -975,7 +983,7 @@ class _NumbersModel(Cacheable):
975
983
  return None
976
984
  return storage_buffers[row_offset][col]
977
985
 
978
- def recalculate_row_headers(self, table_id: int, data: List):
986
+ def recalculate_row_headers(self, table_id: int, data: list) -> None:
979
987
  base_data_store = self.objects[table_id].base_data_store
980
988
  buckets = self.objects[base_data_store.rowHeaders.buckets[0].identifier]
981
989
  clear_field_container(buckets.headers)
@@ -992,7 +1000,7 @@ class _NumbersModel(Cacheable):
992
1000
  )
993
1001
  buckets.headers.append(header)
994
1002
 
995
- def recalculate_column_headers(self, table_id: int, data: List):
1003
+ def recalculate_column_headers(self, table_id: int, data: list) -> None:
996
1004
  current_column_widths = {}
997
1005
  for col in range(self.number_of_columns(table_id)):
998
1006
  current_column_widths[col] = self.col_width(table_id, col)
@@ -1014,7 +1022,7 @@ class _NumbersModel(Cacheable):
1014
1022
  )
1015
1023
  buckets.headers.append(header)
1016
1024
 
1017
- def recalculate_merged_cells(self, table_id: int):
1025
+ def recalculate_merged_cells(self, table_id: int) -> None:
1018
1026
  merge_cells = self.merge_cells(table_id)
1019
1027
 
1020
1028
  merge_map_id, merge_map = self.objects.create_object_from_dict(
@@ -1037,7 +1045,7 @@ class _NumbersModel(Cacheable):
1037
1045
  def recalculate_row_info(
1038
1046
  self,
1039
1047
  table_id: int,
1040
- data: List,
1048
+ data: list,
1041
1049
  tile_row_offset: int,
1042
1050
  row: int,
1043
1051
  ) -> TSTArchives.TileRowInfo:
@@ -1068,18 +1076,18 @@ class _NumbersModel(Cacheable):
1068
1076
  return row_info
1069
1077
 
1070
1078
  @cache()
1071
- def metadata_component(self, reference: Optional[Union[str, int]] = None) -> int:
1079
+ def metadata_component(self, reference: str | int | None = None) -> int:
1072
1080
  """Return the ID of an object in the document metadata given it's name or ID."""
1073
1081
  component_map = {c.identifier: c for c in self.objects[PACKAGE_ID].components}
1074
1082
  if isinstance(reference, str):
1075
1083
  component_ids = [
1076
- id for id, c in component_map.items() if c.preferred_locator == reference
1084
+ x for x, c in component_map.items() if c.preferred_locator == reference
1077
1085
  ]
1078
1086
  else:
1079
- component_ids = [id for id, c in component_map.items() if c.identifier == reference]
1087
+ component_ids = [x for x, c in component_map.items() if c.identifier == reference]
1080
1088
  return component_map[component_ids[0]]
1081
1089
 
1082
- def add_component_metadata(self, object_id: int, parent: str, locator: str):
1090
+ def add_component_metadata(self, object_id: int, parent: str, locator: str) -> None:
1083
1091
  """Add a new ComponentInfo record to the parent object in the document metadata."""
1084
1092
  locator = locator.format(object_id)
1085
1093
  preferred_locator = re.sub(r"\-\d+.*", "", locator)
@@ -1098,10 +1106,10 @@ class _NumbersModel(Cacheable):
1098
1106
  def add_component_reference(
1099
1107
  self,
1100
1108
  object_id: int,
1101
- location: Optional[str] = None,
1102
- component_id: Optional[int] = None,
1109
+ location: str | None = None,
1110
+ component_id: int | None = None,
1103
1111
  is_weak: bool = False,
1104
- ):
1112
+ ) -> None:
1105
1113
  """Add an external reference to an object in a metadata component."""
1106
1114
  component = self.metadata_component(location or component_id)
1107
1115
  if component_id is not None:
@@ -1114,7 +1122,7 @@ class _NumbersModel(Cacheable):
1114
1122
  TSPArchiveMessages.ComponentExternalReference(**params),
1115
1123
  )
1116
1124
 
1117
- def recalculate_table_data(self, table_id: int, data: List):
1125
+ def recalculate_table_data(self, table_id: int, data: list) -> None:
1118
1126
  table_model = self.objects[table_id]
1119
1127
  table_model.number_of_rows = len(data)
1120
1128
  table_model.number_of_columns = len(data[0])
@@ -1191,7 +1199,7 @@ class _NumbersModel(Cacheable):
1191
1199
  height += self.row_height(table_id, row)
1192
1200
  return floor(height)
1193
1201
 
1194
- def row_height(self, table_id: int, row: int, height: Optional[int] = None) -> int:
1202
+ def row_height(self, table_id: int, row: int, height: int | None = None) -> int:
1195
1203
  if height is not None:
1196
1204
  if table_id not in self._row_heights:
1197
1205
  self._row_heights[table_id] = {}
@@ -1218,7 +1226,7 @@ class _NumbersModel(Cacheable):
1218
1226
  data[row][col].border.top.width
1219
1227
  for col in range(len(data[row]))
1220
1228
  if data[row][col].border.top is not None
1221
- ]
1229
+ ],
1222
1230
  )
1223
1231
  max_bottom_border = max(
1224
1232
  [0.0]
@@ -1226,7 +1234,7 @@ class _NumbersModel(Cacheable):
1226
1234
  data[row][col].border.bottom.width
1227
1235
  for col in range(len(data[row]))
1228
1236
  if data[row][col].border.bottom is not None
1229
- ]
1237
+ ],
1230
1238
  )
1231
1239
  height += max_top_border / 2
1232
1240
  height += max_bottom_border / 2
@@ -1243,7 +1251,7 @@ class _NumbersModel(Cacheable):
1243
1251
  width += self.col_width(table_id, row)
1244
1252
  return round(width)
1245
1253
 
1246
- def col_width(self, table_id: int, col: int, width: Optional[int] = None) -> int:
1254
+ def col_width(self, table_id: int, col: int, width: int | None = None) -> int:
1247
1255
  if width is not None:
1248
1256
  if table_id not in self._col_widths:
1249
1257
  self._col_widths[table_id] = {}
@@ -1270,7 +1278,7 @@ class _NumbersModel(Cacheable):
1270
1278
  data[row][col].border.left.width
1271
1279
  for row in range(len(data))
1272
1280
  if data[row][col].border.left is not None
1273
- ]
1281
+ ],
1274
1282
  )
1275
1283
  max_right_border = max(
1276
1284
  [0.0]
@@ -1278,7 +1286,7 @@ class _NumbersModel(Cacheable):
1278
1286
  data[row][col].border.right.width
1279
1287
  for row in range(len(data))
1280
1288
  if data[row][col].border.right is not None
1281
- ]
1289
+ ],
1282
1290
  )
1283
1291
  width += max_left_border / 2
1284
1292
  width += max_right_border / 2
@@ -1288,21 +1296,21 @@ class _NumbersModel(Cacheable):
1288
1296
  self._col_widths[table_id][col] = floor(width)
1289
1297
  return self._col_widths[table_id][col]
1290
1298
 
1291
- def num_header_rows(self, table_id: int, num_headers: Optional[int] = None) -> int:
1299
+ def num_header_rows(self, table_id: int, num_headers: int | None = None) -> int:
1292
1300
  """Return/set the number of header rows."""
1293
1301
  table_model = self.objects[table_id]
1294
1302
  if num_headers is not None:
1295
1303
  table_model.number_of_header_rows = num_headers
1296
1304
  return table_model.number_of_header_rows
1297
1305
 
1298
- def num_header_cols(self, table_id: int, num_headers: Optional[int] = None) -> int:
1306
+ def num_header_cols(self, table_id: int, num_headers: int | None = None) -> int:
1299
1307
  """Return/set the number of header columns."""
1300
1308
  table_model = self.objects[table_id]
1301
1309
  if num_headers is not None:
1302
1310
  table_model.number_of_header_columns = num_headers
1303
1311
  return table_model.number_of_header_columns
1304
1312
 
1305
- def table_coordinates(self, table_id: int) -> Tuple[float]:
1313
+ def table_coordinates(self, table_id: int) -> tuple[float]:
1306
1314
  table_info = self.objects[self.table_info_id(table_id)]
1307
1315
  return (
1308
1316
  table_info.super.geometry.position.x,
@@ -1347,7 +1355,7 @@ class _NumbersModel(Cacheable):
1347
1355
  ),
1348
1356
  )
1349
1357
 
1350
- def add_table( # noqa: PLR0913
1358
+ def add_table(
1351
1359
  self,
1352
1360
  sheet_id: int,
1353
1361
  table_name: str,
@@ -1484,7 +1492,9 @@ class _NumbersModel(Cacheable):
1484
1492
  table_info.super.MergeFrom(self.create_drawable(sheet_id, x, y))
1485
1493
 
1486
1494
  self.add_component_reference(
1487
- table_info_id, location="Document", component_id=self.calc_engine_id()
1495
+ table_info_id,
1496
+ location="Document",
1497
+ component_id=self.calc_engine_id(),
1488
1498
  )
1489
1499
  self.create_caption_archive(table_model_id)
1490
1500
  self.caption_enabled(table_model_id, False)
@@ -1502,15 +1512,16 @@ class _NumbersModel(Cacheable):
1502
1512
  )
1503
1513
  return table_model_id
1504
1514
 
1505
- def add_formula_owner( # noqa: PLR0913
1515
+ def add_formula_owner(
1506
1516
  self,
1507
1517
  table_info_id: int,
1508
1518
  num_rows: int,
1509
1519
  num_cols: int,
1510
1520
  number_of_header_rows: int,
1511
1521
  number_of_header_columns: int,
1512
- ):
1513
- """Create a FormulaOwnerDependenciesArchive that references a TableInfoArchive
1522
+ ) -> None:
1523
+ """
1524
+ Create a FormulaOwnerDependenciesArchive that references a TableInfoArchive
1514
1525
  so that cross-references to cells in this table will work.
1515
1526
  """
1516
1527
  formula_owner_uuid = NumbersUUID()
@@ -1589,7 +1600,10 @@ class _NumbersModel(Cacheable):
1589
1600
  )
1590
1601
 
1591
1602
  self.add_component_reference(
1592
- sheet_id, location="CalculationEngine", component_id=DOCUMENT_ID, is_weak=True
1603
+ sheet_id,
1604
+ location="CalculationEngine",
1605
+ component_id=DOCUMENT_ID,
1606
+ is_weak=True,
1593
1607
  )
1594
1608
 
1595
1609
  self.objects[DOCUMENT_ID].sheets.append(TSPMessages.Reference(identifier=sheet_id))
@@ -1603,7 +1617,7 @@ class _NumbersModel(Cacheable):
1603
1617
  return self._styles
1604
1618
 
1605
1619
  @cache(num_args=0)
1606
- def available_paragraph_styles(self) -> Dict[str, Style]:
1620
+ def available_paragraph_styles(self) -> dict[str, Style]:
1607
1621
  theme_id = self.objects[DOCUMENT_ID].theme.identifier
1608
1622
  presets = find_extension(self.objects[theme_id].super, "paragraph_style_presets")
1609
1623
  presets_map = {
@@ -1707,7 +1721,7 @@ class _NumbersModel(Cacheable):
1707
1721
  self._styles[style.name] = style
1708
1722
  return para_style_id
1709
1723
 
1710
- def update_paragraph_style(self, style: Style):
1724
+ def update_paragraph_style(self, style: Style) -> None:
1711
1725
  if style.underline:
1712
1726
  underline = CharacterStyle.UnderlineType.kSingleUnderline
1713
1727
  else:
@@ -1734,8 +1748,9 @@ class _NumbersModel(Cacheable):
1734
1748
  style_obj.para_properties.left_indent = style.left_indent
1735
1749
  style_obj.para_properties.right_indent = style.right_indent
1736
1750
 
1737
- def update_paragraph_styles(self):
1738
- """Create new paragraph style archives for any new styles that
1751
+ def update_paragraph_styles(self) -> None:
1752
+ """
1753
+ Create new paragraph style archives for any new styles that
1739
1754
  have been created for this document.
1740
1755
  """
1741
1756
  new_styles = [x for x in self.styles.values() if x._text_style_obj_id is None]
@@ -1751,8 +1766,9 @@ class _NumbersModel(Cacheable):
1751
1766
  for style in updated_styles:
1752
1767
  self.update_paragraph_style(style)
1753
1768
 
1754
- def update_cell_styles(self, table_id: int, data: List):
1755
- """Create new cell style archives for any cells whose styles
1769
+ def update_cell_styles(self, table_id: int, data: list) -> None:
1770
+ """
1771
+ Create new cell style archives for any cells whose styles
1756
1772
  have changes that require a cell style.
1757
1773
  """
1758
1774
  cell_styles = {}
@@ -1781,7 +1797,7 @@ class _NumbersModel(Cacheable):
1781
1797
 
1782
1798
  def add_cell_style(self, style: Style) -> int:
1783
1799
  if style.bg_image is not None:
1784
- digest = sha1(style.bg_image.data).digest()
1800
+ digest = sha1(style.bg_image.data).digest() # noqa: S324
1785
1801
  if digest in self._images:
1786
1802
  image_id = self._images[digest]
1787
1803
  else:
@@ -1871,7 +1887,8 @@ class _NumbersModel(Cacheable):
1871
1887
  return entry.reference.identifier
1872
1888
 
1873
1889
  def custom_style_name(self) -> str:
1874
- """Find custom styles in the current document and return the next
1890
+ """
1891
+ Find custom styles in the current document and return the next
1875
1892
  highest numbered style.
1876
1893
  """
1877
1894
  stylesheet_id = self.objects[DOCUMENT_ID].stylesheet.identifier
@@ -1887,11 +1904,10 @@ class _NumbersModel(Cacheable):
1887
1904
  offset = len("Custom Style ")
1888
1905
  custom_style_ids = [int(x[offset:]) for x in custom_styles]
1889
1906
  return "Custom Style " + str(custom_style_ids[-1] + 1)
1890
- else:
1891
- return "Custom Style 1"
1907
+ return "Custom Style 1"
1892
1908
 
1893
1909
  @property
1894
- def custom_formats(self) -> Dict[str, CustomFormatting]:
1910
+ def custom_formats(self) -> dict[str, CustomFormatting]:
1895
1911
  if self._custom_formats is None:
1896
1912
  custom_format_list_id = self.objects[DOCUMENT_ID].super.custom_format_list.identifier
1897
1913
  custom_formats = self.objects[custom_format_list_id].custom_formats
@@ -1908,7 +1924,8 @@ class _NumbersModel(Cacheable):
1908
1924
  return self._custom_formats
1909
1925
 
1910
1926
  def custom_format_name(self) -> str:
1911
- """Find custom formats in the current document and return the next
1927
+ """
1928
+ Find custom formats in the current document and return the next
1912
1929
  highest numbered format.
1913
1930
  """
1914
1931
  current_formats = self.custom_formats.keys()
@@ -1920,15 +1937,14 @@ class _NumbersModel(Cacheable):
1920
1937
  if len(current_formats) > 0:
1921
1938
  last_id = int(current_formats[-1])
1922
1939
  return f"Custom Format {last_id + 1}"
1923
- else:
1924
- return "Custom Format 1"
1940
+ return "Custom Format 1"
1925
1941
 
1926
1942
  @cache()
1927
1943
  def table_formulas(self, table_id: int):
1928
1944
  return TableFormulas(self, table_id)
1929
1945
 
1930
1946
  @cache(num_args=2)
1931
- def table_rich_text(self, table_id: int, string_key: int) -> Dict:
1947
+ def table_rich_text(self, table_id: int, string_key: int) -> dict:
1932
1948
  """Extract bullets and hyperlinks from a rich text data cell."""
1933
1949
  # The table model base data store contains a richTextTable field
1934
1950
  # which is a reference to a TST.TableDataList. The TableDataList
@@ -1963,12 +1979,12 @@ class _NumbersModel(Cacheable):
1963
1979
  # a string with a new bullet character
1964
1980
  bds = self.objects[table_id].base_data_store
1965
1981
  rich_text_table = self.objects[bds.rich_text_table.identifier]
1966
- for entry in rich_text_table.entries: # pragma: no branch
1982
+ for entry in rich_text_table.entries: # pragma: no branch # noqa: RET503
1967
1983
  if string_key == entry.key:
1968
1984
  payload = self.objects[entry.rich_text_payload.identifier]
1969
1985
  payload_storage = self.objects[payload.storage.identifier]
1970
1986
  smartfield_entries = payload_storage.table_smartfield.entries
1971
- cell_text = payload_storage.text[0]
1987
+ cell_text = payload_storage.text[0] if len(payload_storage.text) > 0 else ""
1972
1988
 
1973
1989
  hyperlinks = []
1974
1990
  for i, e in enumerate(smartfield_entries):
@@ -2019,7 +2035,8 @@ class _NumbersModel(Cacheable):
2019
2035
  }
2020
2036
 
2021
2037
  def cell_text_style(self, cell: Cell) -> object:
2022
- """Return the text style object for the cell or, if none
2038
+ """
2039
+ Return the text style object for the cell or, if none
2023
2040
  is defined, the default header, footer or body style.
2024
2041
  """
2025
2042
  if cell._text_style_id is not None:
@@ -2028,9 +2045,9 @@ class _NumbersModel(Cacheable):
2028
2045
  table_model = self.objects[cell._table_id]
2029
2046
  if cell.row in range(table_model.number_of_header_rows):
2030
2047
  return self.objects[table_model.header_row_text_style.identifier]
2031
- elif cell.col in range(table_model.number_of_header_columns):
2048
+ if cell.col in range(table_model.number_of_header_columns):
2032
2049
  return self.objects[table_model.header_column_text_style.identifier]
2033
- elif table_model.number_of_footer_rows > 0:
2050
+ if table_model.number_of_footer_rows > 0:
2034
2051
  start_row_num = table_model.number_of_rows - table_model.number_of_footer_rows
2035
2052
  end_row_num = start_row_num + table_model.number_of_footer_rows
2036
2053
  if cell.row in range(start_row_num, end_row_num):
@@ -2048,7 +2065,7 @@ class _NumbersModel(Cacheable):
2048
2065
  vertical = VerticalJustification(self.cell_property(style, "vertical_alignment"))
2049
2066
  return Alignment(horizontal, vertical)
2050
2067
 
2051
- def cell_bg_color(self, cell: Cell) -> Union[Tuple, List[Tuple]]:
2068
+ def cell_bg_color(self, cell: Cell) -> tuple | list[tuple]:
2052
2069
  if cell._cell_style_id is None:
2053
2070
  return None
2054
2071
 
@@ -2057,115 +2074,111 @@ class _NumbersModel(Cacheable):
2057
2074
 
2058
2075
  if cell_properties.HasField("color"):
2059
2076
  return rgb(cell_properties.color)
2060
- elif cell_properties.HasField("gradient"):
2077
+ if cell_properties.HasField("gradient"):
2061
2078
  return [(rgb(s.color)) for s in cell_properties.gradient.stops]
2062
2079
  return None
2063
2080
 
2064
2081
  def char_property(self, style: object, field: str):
2065
- """Return a char_property field from a style if present
2082
+ """
2083
+ Return a char_property field from a style if present
2066
2084
  in the style, or from the parent if not.
2067
2085
  """
2068
2086
  if not style.char_properties.HasField(field):
2069
2087
  parent = self.objects[style.super.parent.identifier]
2070
2088
  return getattr(parent.char_properties, field)
2071
- else:
2072
- return getattr(style.char_properties, field)
2089
+ return getattr(style.char_properties, field)
2073
2090
 
2074
2091
  def para_property(self, style: object, field: str) -> float:
2075
- """Return a para_property field from a style if present
2092
+ """
2093
+ Return a para_property field from a style if present
2076
2094
  in the style, or from the parent if not.
2077
2095
  """
2078
2096
  if not style.para_properties.HasField(field):
2079
2097
  parent = self.objects[style.super.parent.identifier]
2080
2098
  return getattr(parent.para_properties, field)
2081
- else:
2082
- return getattr(style.para_properties, field)
2099
+ return getattr(style.para_properties, field)
2083
2100
 
2084
2101
  def cell_property(self, style: object, field: str) -> float:
2085
- """Return a cell_property field from a style if present
2102
+ """
2103
+ Return a cell_property field from a style if present
2086
2104
  in the style, or from the parent if not.
2087
2105
  """
2088
2106
  if not style.cell_properties.HasField(field):
2089
2107
  parent = self.objects[style.super.parent.identifier]
2090
2108
  return getattr(parent.cell_properties, field)
2091
- else:
2092
- return getattr(style.cell_properties, field)
2109
+ return getattr(style.cell_properties, field)
2093
2110
 
2094
- def cell_is_bold(self, obj: Union[Cell, object]) -> bool:
2111
+ def cell_is_bold(self, obj: Cell | object) -> bool:
2095
2112
  style = self.cell_text_style(obj) if isinstance(obj, Cell) else obj
2096
2113
  return self.char_property(style, "bold")
2097
2114
 
2098
- def cell_is_italic(self, obj: Union[Cell, object]) -> bool:
2115
+ def cell_is_italic(self, obj: Cell | object) -> bool:
2099
2116
  style = self.cell_text_style(obj) if isinstance(obj, Cell) else obj
2100
2117
  return self.char_property(style, "italic")
2101
2118
 
2102
- def cell_is_underline(self, obj: Union[Cell, object]) -> bool:
2119
+ def cell_is_underline(self, obj: Cell | object) -> bool:
2103
2120
  style = self.cell_text_style(obj) if isinstance(obj, Cell) else obj
2104
2121
  underline = self.char_property(style, "underline")
2105
2122
  return underline != CharacterStyle.UnderlineType.kNoUnderline
2106
2123
 
2107
- def cell_is_strikethrough(self, obj: Union[Cell, object]) -> bool:
2124
+ def cell_is_strikethrough(self, obj: Cell | object) -> bool:
2108
2125
  style = self.cell_text_style(obj) if isinstance(obj, Cell) else obj
2109
2126
  strikethru = self.char_property(style, "strikethru")
2110
2127
  return strikethru != CharacterStyle.StrikethruType.kNoStrikethru
2111
2128
 
2112
- def cell_style_name(self, obj: Union[Cell, object]) -> bool:
2129
+ def cell_style_name(self, obj: Cell | object) -> bool:
2113
2130
  style = self.cell_text_style(obj) if isinstance(obj, Cell) else obj
2114
2131
  return style.super.name
2115
2132
 
2116
- def cell_font_color(self, obj: Union[Cell, object]) -> Tuple:
2133
+ def cell_font_color(self, obj: Cell | object) -> tuple:
2117
2134
  style = self.cell_text_style(obj) if isinstance(obj, Cell) else obj
2118
2135
  return rgb(self.char_property(style, "font_color"))
2119
2136
 
2120
- def cell_font_size(self, obj: Union[Cell, object]) -> float:
2137
+ def cell_font_size(self, obj: Cell | object) -> float:
2121
2138
  style = self.cell_text_style(obj) if isinstance(obj, Cell) else obj
2122
2139
  return self.char_property(style, "font_size")
2123
2140
 
2124
- def cell_font_name(self, obj: Union[Cell, object]) -> str:
2141
+ def cell_font_name(self, obj: Cell | object) -> str:
2125
2142
  style = self.cell_text_style(obj) if isinstance(obj, Cell) else obj
2126
2143
  font_name = self.char_property(style, "font_name")
2127
2144
  return FONT_NAME_TO_FAMILY[font_name]
2128
2145
 
2129
- def cell_first_indent(self, obj: Union[Cell, object]) -> float:
2146
+ def cell_first_indent(self, obj: Cell | object) -> float:
2130
2147
  style = self.cell_text_style(obj) if isinstance(obj, Cell) else obj
2131
2148
  return self.para_property(style, "first_line_indent")
2132
2149
 
2133
- def cell_left_indent(self, obj: Union[Cell, object]) -> float:
2150
+ def cell_left_indent(self, obj: Cell | object) -> float:
2134
2151
  style = self.cell_text_style(obj) if isinstance(obj, Cell) else obj
2135
2152
  return self.para_property(style, "left_indent")
2136
2153
 
2137
- def cell_right_indent(self, obj: Union[Cell, object]) -> float:
2154
+ def cell_right_indent(self, obj: Cell | object) -> float:
2138
2155
  style = self.cell_text_style(obj) if isinstance(obj, Cell) else obj
2139
2156
  return self.para_property(style, "right_indent")
2140
2157
 
2141
2158
  def cell_text_inset(self, cell: Cell) -> float:
2142
2159
  if cell._cell_style_id is None:
2143
2160
  return DEFAULT_TEXT_INSET
2144
- else:
2145
- style = self.table_style(cell._table_id, cell._cell_style_id)
2146
- padding = self.cell_property(style, "padding")
2147
- # Padding is always identical (only one UI setting)
2148
- return padding.left
2161
+ style = self.table_style(cell._table_id, cell._cell_style_id)
2162
+ padding = self.cell_property(style, "padding")
2163
+ # Padding is always identical (only one UI setting)
2164
+ return padding.left
2149
2165
 
2150
2166
  def cell_text_wrap(self, cell: Cell) -> float:
2151
2167
  if cell._cell_style_id is None:
2152
2168
  return DEFAULT_TEXT_WRAP
2153
- else:
2154
- style = self.table_style(cell._table_id, cell._cell_style_id)
2155
- return self.cell_property(style, "text_wrap")
2169
+ style = self.table_style(cell._table_id, cell._cell_style_id)
2170
+ return self.cell_property(style, "text_wrap")
2156
2171
 
2157
2172
  def stroke_type(self, stroke_run: object) -> str:
2158
2173
  """Return the stroke type for a stroke run."""
2159
2174
  stroke_type = stroke_run.stroke.pattern.type
2160
2175
  if stroke_type == StrokePattern.StrokePatternType.TSDSolidPattern:
2161
2176
  return "solid"
2162
- elif stroke_type == StrokePattern.StrokePatternType.TSDPattern:
2177
+ if stroke_type == StrokePattern.StrokePatternType.TSDPattern:
2163
2178
  if stroke_run.stroke.pattern.pattern[0] < 1.0:
2164
2179
  return "dots"
2165
- else:
2166
- return "dashes"
2167
- else:
2168
- return "none"
2180
+ return "dashes"
2181
+ return "none"
2169
2182
 
2170
2183
  def cell_for_stroke(self, table_id: int, side: str, row: int, col: int) -> object:
2171
2184
  data = self._table_data[table_id]
@@ -2189,14 +2202,14 @@ class _NumbersModel(Cacheable):
2189
2202
  return cell
2190
2203
  return None
2191
2204
 
2192
- def set_cell_border( # noqa: PLR0913
2205
+ def set_cell_border(
2193
2206
  self,
2194
2207
  table_id: int,
2195
2208
  row: int,
2196
2209
  col: int,
2197
2210
  side: str,
2198
2211
  border_value: Border,
2199
- ):
2212
+ ) -> None:
2200
2213
  """Set the 2 borders adjacent to a stroke if within the table range."""
2201
2214
  if side == "top":
2202
2215
  if (cell := self.cell_for_stroke(table_id, "top", row, col)) is not None:
@@ -2231,7 +2244,7 @@ class _NumbersModel(Cacheable):
2231
2244
  self._col_widths[table_id].pop(col, None)
2232
2245
  self._col_widths[table_id].pop(col - 1, None)
2233
2246
 
2234
- def extract_strokes_in_layers(self, table_id: int, layer_ids: List, side: str):
2247
+ def extract_strokes_in_layers(self, table_id: int, layer_ids: list, side: str) -> None:
2235
2248
  for layer_id in layer_ids:
2236
2249
  stroke_layer = self.objects[layer_id.identifier]
2237
2250
  for stroke_run in stroke_layer.stroke_runs:
@@ -2253,7 +2266,7 @@ class _NumbersModel(Cacheable):
2253
2266
  self.set_cell_border(table_id, row, start_column, side, border_value)
2254
2267
 
2255
2268
  @cache()
2256
- def extract_strokes(self, table_id: int):
2269
+ def extract_strokes(self, table_id: int) -> None:
2257
2270
  table_obj = self.objects[table_id]
2258
2271
  sidecar_obj = self.objects[table_obj.stroke_sidecar.identifier]
2259
2272
  self.extract_strokes_in_layers(table_id, sidecar_obj.top_row_stroke_layers, "top")
@@ -2318,7 +2331,7 @@ class _NumbersModel(Cacheable):
2318
2331
  ),
2319
2332
  )
2320
2333
 
2321
- def add_stroke( # noqa: PLR0913
2334
+ def add_stroke(
2322
2335
  self,
2323
2336
  table_id: int,
2324
2337
  row: int,
@@ -2326,7 +2339,7 @@ class _NumbersModel(Cacheable):
2326
2339
  side: str,
2327
2340
  border_value: Border,
2328
2341
  length: int,
2329
- ):
2342
+ ) -> None:
2330
2343
  table_obj = self.objects[table_id]
2331
2344
  sidecar_obj = self.objects[table_obj.stroke_sidecar.identifier]
2332
2345
  sidecar_obj.max_order += 1
@@ -2420,8 +2433,7 @@ def range_end(obj):
2420
2433
  """Select end range for a IndexSetArchive.IndexSetEntry."""
2421
2434
  if obj.HasField("range_end"):
2422
2435
  return obj.range_end
2423
- else:
2424
- return obj.range_begin
2436
+ return obj.range_begin
2425
2437
 
2426
2438
 
2427
2439
  def formatted_number(number_type, index):
@@ -2439,18 +2451,16 @@ def node_to_col_ref(node: object, table_name: str, col: int) -> str:
2439
2451
  col_name = xl_col_to_name(col, node.AST_column.absolute)
2440
2452
  if table_name is not None:
2441
2453
  return f"{table_name}::{col_name}"
2442
- else:
2443
- return col_name
2454
+ return col_name
2444
2455
 
2445
2456
 
2446
2457
  def node_to_row_ref(node: object, table_name: str, row: int) -> str:
2447
2458
  row = node.AST_row.row if node.AST_row.absolute else row + node.AST_row.row
2448
2459
 
2449
- row_name = f"${row+1}" if node.AST_row.absolute else f"{row+1}"
2460
+ row_name = f"${row + 1}" if node.AST_row.absolute else f"{row + 1}"
2450
2461
  if table_name is not None:
2451
2462
  return f"{table_name}::{row_name}:{row_name}"
2452
- else:
2453
- return f"{row_name}:{row_name}"
2463
+ return f"{row_name}:{row_name}"
2454
2464
 
2455
2465
 
2456
2466
  def node_to_row_col_ref(node: object, table_name: str, row: int, col: int) -> str:
@@ -2465,8 +2475,7 @@ def node_to_row_col_ref(node: object, table_name: str, row: int, col: int) -> st
2465
2475
  )
2466
2476
  if table_name is not None:
2467
2477
  return f"{table_name}::{ref}"
2468
- else:
2469
- return ref
2478
+ return ref
2470
2479
 
2471
2480
 
2472
2481
  def get_storage_buffers_for_row(
@@ -2474,8 +2483,9 @@ def get_storage_buffers_for_row(
2474
2483
  offsets: list,
2475
2484
  num_cols: int,
2476
2485
  has_wide_offsets: bool,
2477
- ) -> List[bytes]:
2478
- """Extract storage buffers for each cell in a table row.
2486
+ ) -> list[bytes]:
2487
+ """
2488
+ Extract storage buffers for each cell in a table row.
2479
2489
 
2480
2490
  Args:
2481
2491
  ----
@@ -2487,6 +2497,7 @@ def get_storage_buffers_for_row(
2487
2497
  Returns:
2488
2498
  -------
2489
2499
  data: list of bytes for each cell in a row, or None if empty
2500
+
2490
2501
  """
2491
2502
  offsets = array("h", offsets).tolist()
2492
2503
  if has_wide_offsets:
@@ -2518,8 +2529,9 @@ def get_storage_buffers_for_row(
2518
2529
  return data
2519
2530
 
2520
2531
 
2521
- def clear_field_container(obj):
2522
- """Remove all entries from a protobuf RepeatedCompositeFieldContainer
2532
+ def clear_field_container(obj) -> None:
2533
+ """
2534
+ Remove all entries from a protobuf RepeatedCompositeFieldContainer
2523
2535
  in a portable fashion.
2524
2536
  """
2525
2537
  while len(obj) > 0:
@@ -2531,5 +2543,5 @@ def field_references(obj: object) -> dict:
2531
2543
  return {
2532
2544
  x[0].name: {"identifier": getattr(obj, x[0].name).identifier}
2533
2545
  for x in obj.ListFields()
2534
- if type(getattr(obj, x[0].name)) == TSPMessages.Reference
2546
+ if isinstance(getattr(obj, x[0].name), TSPMessages.Reference)
2535
2547
  }