numbers-parser 4.10.3__py3-none-any.whl → 4.10.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +13 -7
  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 +77 -55
  27. numbers_parser/numbers_uuid.py +6 -4
  28. {numbers_parser-4.10.3.dist-info → numbers_parser-4.10.5.dist-info}/METADATA +7 -7
  29. {numbers_parser-4.10.3.dist-info → numbers_parser-4.10.5.dist-info}/RECORD +32 -32
  30. {numbers_parser-4.10.3.dist-info → numbers_parser-4.10.5.dist-info}/LICENSE.rst +0 -0
  31. {numbers_parser-4.10.3.dist-info → numbers_parser-4.10.5.dist-info}/WHEEL +0 -0
  32. {numbers_parser-4.10.3.dist-info → numbers_parser-4.10.5.dist-info}/entry_points.txt +0 -0
numbers_parser/model.py CHANGED
@@ -4,7 +4,7 @@ from collections import defaultdict
4
4
  from hashlib import sha1
5
5
  from pathlib import Path
6
6
  from struct import pack
7
- from typing import Dict, List, Tuple, Union
7
+ from typing import Dict, List, Optional, Tuple, Union
8
8
 
9
9
  from numbers_parser.bullets import (
10
10
  BULLET_CONVERSION,
@@ -86,7 +86,7 @@ FONT_FAMILY_TO_NAME = create_font_name_map(FONT_NAME_TO_FAMILY)
86
86
 
87
87
 
88
88
  class MergeCells:
89
- def __init__(self):
89
+ def __init__(self) -> None:
90
90
  self._references = defaultdict(lambda: False)
91
91
 
92
92
  def add_reference(self, row: int, col: int, rect: Tuple):
@@ -119,7 +119,7 @@ class MergeCells:
119
119
  class DataLists(Cacheable):
120
120
  """Model for TST.DataList with caching and key generation for new values."""
121
121
 
122
- def __init__(self, model: object, datalist_name: str, value_attr: str = None):
122
+ def __init__(self, model: object, datalist_name: str, value_attr: Optional[str] = None) -> None:
123
123
  self._model = model
124
124
  self._datalists = {}
125
125
  self._value_attr = value_attr
@@ -136,12 +136,14 @@ class DataLists(Cacheable):
136
136
  self._datalists[table_id] = {}
137
137
  self._datalists[table_id]["by_key"] = {}
138
138
  self._datalists[table_id]["by_value"] = {}
139
+ self._datalists[table_id]["key_index"] = {}
139
140
  self._datalists[table_id]["datalist"] = datalist
140
141
  self._datalists[table_id]["id"] = datalist_id
141
- for entry in datalist.entries:
142
+ for i, entry in enumerate(datalist.entries):
142
143
  if entry.key > max_key:
143
144
  max_key = entry.key
144
145
  self._datalists[table_id]["by_key"][entry.key] = entry
146
+ self._datalists[table_id]["key_index"][entry.key] = i
145
147
  value_key = self.value_key(getattr(entry, self._value_attr))
146
148
  self._datalists[table_id]["by_value"][value_key] = entry.key
147
149
  self._datalists[table_id]["next_key"] = max_key + 1
@@ -166,6 +168,7 @@ class DataLists(Cacheable):
166
168
  self.add_table(table_id)
167
169
  self._datalists[table_id]["by_key"] = {}
168
170
  self._datalists[table_id]["by_value"] = {}
171
+ self._datalists[table_id]["key_index"] = {}
169
172
  self._datalists[table_id]["next_key"] = 1
170
173
  self._datalists[table_id]["datalist"].nextListID = 1
171
174
  clear_field_container(self._datalists[table_id]["datalist"].entries)
@@ -185,11 +188,15 @@ class DataLists(Cacheable):
185
188
  entry = TSTArchives.TableDataList.ListEntry(**attrs)
186
189
  self._datalists[table_id]["datalist"].entries.append(entry)
187
190
  self._datalists[table_id]["by_key"][key] = entry
191
+ self._datalists[table_id]["key_index"][key] = (
192
+ len(self._datalists[table_id]["datalist"].entries) - 1
193
+ )
188
194
  self._datalists[table_id]["by_value"][value_key] = key
189
195
  else:
190
196
  value_key = self.value_key(value)
191
197
  key = self._datalists[table_id]["by_value"][value_key]
192
- self._datalists[table_id]["by_key"][key].refcount += 1
198
+ index = self._datalists[table_id]["key_index"][key]
199
+ self._datalists[table_id]["datalist"].entries[index].refcount += 1
193
200
 
194
201
  return key
195
202
 
@@ -202,7 +209,7 @@ class _NumbersModel(Cacheable):
202
209
  Not to be used in application code.
203
210
  """
204
211
 
205
- def __init__(self, filepath: Path):
212
+ def __init__(self, filepath: Path) -> None:
206
213
  if filepath is None:
207
214
  filepath = Path(DEFAULT_DOCUMENT)
208
215
  self.objects = ObjectStore(filepath)
@@ -237,9 +244,13 @@ class _NumbersModel(Cacheable):
237
244
 
238
245
  def sheet_name(self, sheet_id, value=None):
239
246
  if value is None:
240
- return self.objects[sheet_id].name
247
+ if sheet_id not in self.objects:
248
+ return None
249
+ else:
250
+ return self.objects[sheet_id].name
241
251
  else:
242
252
  self.objects[sheet_id].name = value
253
+ return None
243
254
 
244
255
  def set_table_data(self, table_id: int, data: List):
245
256
  self._table_data[table_id] = data
@@ -321,10 +332,12 @@ class _NumbersModel(Cacheable):
321
332
  return self.objects[table_id].table_name
322
333
  else:
323
334
  self.objects[table_id].table_name = value
335
+ return None
324
336
 
325
- def table_name_enabled(self, table_id: int, enabled: bool = None):
337
+ def table_name_enabled(self, table_id: int, enabled: Optional[bool] = None):
326
338
  if enabled is not None:
327
339
  self.objects[table_id].table_name_enabled = enabled
340
+ return None
328
341
  else:
329
342
  return self.objects[table_id].table_name_enabled
330
343
 
@@ -349,7 +362,7 @@ class _NumbersModel(Cacheable):
349
362
 
350
363
  @cache(num_args=3)
351
364
  def format_archive(self, table_id: int, format_type: FormattingType, format: Formatting):
352
- """Create a table format from a Formatting spec and return the table format ID"""
365
+ """Create a table format from a Formatting spec and return the table format ID."""
353
366
  attrs = {x: getattr(format, x) for x in ALLOWED_FORMATTING_PARAMETERS[format_type]}
354
367
  attrs["format_type"] = FORMAT_TYPE_MAP[format_type]
355
368
 
@@ -367,7 +380,7 @@ class _NumbersModel(Cacheable):
367
380
  "value": item,
368
381
  "format": {"format_type": FormatType.TEXT},
369
382
  },
370
- }
383
+ },
371
384
  )
372
385
  else:
373
386
  tsce_items.append(
@@ -377,7 +390,7 @@ class _NumbersModel(Cacheable):
377
390
  "value": item,
378
391
  "format": {"format_type": FormatType.DECIMAL},
379
392
  },
380
- }
393
+ },
381
394
  )
382
395
  popup_menu_id, _ = self.objects.create_object_from_dict(
383
396
  f"Index/Tables/DataList-{parent_id}",
@@ -388,7 +401,7 @@ class _NumbersModel(Cacheable):
388
401
  return popup_menu_id
389
402
 
390
403
  def control_cell_archive(self, table_id: int, format_type: FormattingType, format: Formatting):
391
- """Create control cell archive from a Formatting spec and return the table format ID"""
404
+ """Create control cell archive from a Formatting spec and return the table format ID."""
392
405
  if format_type == FormattingType.TICKBOX:
393
406
  cell_spec = TSTArchives.CellSpecArchive(interaction_type=CellInteractionType.TOGGLE)
394
407
  elif format_type == FormattingType.RATING:
@@ -415,7 +428,7 @@ class _NumbersModel(Cacheable):
415
428
  return self._control_specs.lookup_key(table_id, cell_spec)
416
429
 
417
430
  def add_custom_decimal_format_archive(self, format: CustomFormatting) -> None:
418
- """Create a custom format from the format spec"""
431
+ """Create a custom format from the format spec."""
419
432
  integer_format = format.integer_format
420
433
  decimal_format = format.decimal_format
421
434
  num_integers = format.num_integers
@@ -503,7 +516,7 @@ class _NumbersModel(Cacheable):
503
516
  custom_format_list.uuids.append(format_uuid)
504
517
 
505
518
  def custom_format_id(self, table_id: int, format: CustomFormatting) -> int:
506
- """Look up the custom format and return the format ID for the table"""
519
+ """Look up the custom format and return the format ID for the table."""
507
520
  format_type = CUSTOM_FORMAT_TYPE_MAP[format.type]
508
521
  format_uuid = self._custom_format_uuids[format.name]
509
522
  custom_format = TSKArchives.FormatStructArchive(
@@ -595,12 +608,13 @@ class _NumbersModel(Cacheable):
595
608
  obj = self.objects[dependency_id]
596
609
  # if obj.owner_kind == OwnerKind.HAUNTED_OWNER:
597
610
  if obj.HasField("base_owner_uid") and obj.HasField(
598
- "formula_owner_uid"
611
+ "formula_owner_uid",
599
612
  ): # pragma: no branch
600
613
  base_owner_uid = NumbersUUID(obj.base_owner_uid).hex
601
614
  formula_owner_uid = NumbersUUID(obj.formula_owner_uid).hex
602
615
  if formula_owner_uid == haunted_owner:
603
616
  return base_owner_uid
617
+ return None
604
618
 
605
619
  @cache()
606
620
  def formula_cell_ranges(self, table_id: int) -> list:
@@ -662,7 +676,7 @@ class _NumbersModel(Cacheable):
662
676
  for row in range(row_start, row_end + 1):
663
677
  for col in range(col_start, col_end + 1):
664
678
  self._merge_cells[table_id].add_reference(
665
- row, col, (row_start, col_start, row_end, col_end)
679
+ row, col, (row_start, col_start, row_end, col_end),
666
680
  )
667
681
  self._merge_cells[table_id].add_anchor(row_start, col_start, size)
668
682
 
@@ -685,7 +699,7 @@ class _NumbersModel(Cacheable):
685
699
  for row in range(row_start, row_end + 1):
686
700
  for col in range(col_start, col_end + 1):
687
701
  self._merge_cells[table_id].add_reference(
688
- row, col, (row_start, col_start, row_end, col_end)
702
+ row, col, (row_start, col_start, row_end, col_end),
689
703
  )
690
704
  self._merge_cells[table_id].add_anchor(row_start, col_start, (num_rows, num_columns))
691
705
 
@@ -697,6 +711,7 @@ class _NumbersModel(Cacheable):
697
711
  for sheet_id in self.sheet_ids(): # pragma: no branch
698
712
  if table_id in self.table_ids(sheet_id):
699
713
  return sheet_id
714
+ return None
700
715
 
701
716
  @cache()
702
717
  def table_uuids_to_id(self, table_uuid) -> int:
@@ -704,6 +719,7 @@ class _NumbersModel(Cacheable):
704
719
  for table_id in self.table_ids(sheet_id):
705
720
  if table_uuid == self.table_base_id(table_id):
706
721
  return table_id
722
+ return None
707
723
 
708
724
  def node_to_ref(self, this_table_id: int, row: int, col: int, node):
709
725
  if node.HasField("AST_cross_table_reference_extra_info"):
@@ -783,7 +799,8 @@ class _NumbersModel(Cacheable):
783
799
  buffers = []
784
800
  for tile in self.table_tiles(table_id):
785
801
  if not tile.last_saved_in_BNC:
786
- raise UnsupportedError("Pre-BNC storage is unsupported")
802
+ msg = "Pre-BNC storage is unsupported"
803
+ raise UnsupportedError(msg)
787
804
  for r in tile.rowInfos:
788
805
  buffer = get_storage_buffers_for_row(
789
806
  r.cell_storage_buffer,
@@ -841,7 +858,7 @@ class _NumbersModel(Cacheable):
841
858
  else:
842
859
  width = current_column_widths[col]
843
860
  header = TSTArchives.HeaderStorageBucket.Header(
844
- index=col, numberOfCells=num_rows, size=width, hidingState=0
861
+ index=col, numberOfCells=num_rows, size=width, hidingState=0,
845
862
  )
846
863
  buckets.headers.append(header)
847
864
 
@@ -849,7 +866,7 @@ class _NumbersModel(Cacheable):
849
866
  merge_cells = self.merge_cells(table_id)
850
867
 
851
868
  merge_map_id, merge_map = self.objects.create_object_from_dict(
852
- "CalculationEngine", {}, TSTArchives.MergeRegionMapArchive
869
+ "CalculationEngine", {}, TSTArchives.MergeRegionMapArchive,
853
870
  )
854
871
 
855
872
  merge_cells = self.merge_cells(table_id)
@@ -864,7 +881,7 @@ class _NumbersModel(Cacheable):
864
881
  base_data_store.merge_region_map.CopyFrom(TSPMessages.Reference(identifier=merge_map_id))
865
882
 
866
883
  def recalculate_row_info(
867
- self, table_id: int, data: List, tile_row_offset: int, row: int
884
+ self, table_id: int, data: List, tile_row_offset: int, row: int,
868
885
  ) -> TSTArchives.TileRowInfo:
869
886
  row_info = TSTArchives.TileRowInfo()
870
887
  row_info.storage_version = 5
@@ -893,7 +910,7 @@ class _NumbersModel(Cacheable):
893
910
  return row_info
894
911
 
895
912
  @cache()
896
- def metadata_component(self, reference: Union[str, int] = None) -> int:
913
+ def metadata_component(self, reference: Optional[Union[str, int]] = None) -> int:
897
914
  """Return the ID of an object in the document metadata given it's name or ID."""
898
915
  component_map = {c.identifier: c for c in self.objects[PACKAGE_ID].components}
899
916
  if isinstance(reference, str):
@@ -923,8 +940,8 @@ class _NumbersModel(Cacheable):
923
940
  def add_component_reference(
924
941
  self,
925
942
  object_id: int,
926
- location: str = None,
927
- parent_id: int = None,
943
+ location: Optional[str] = None,
944
+ parent_id: Optional[int] = None,
928
945
  is_weak: bool = False,
929
946
  ):
930
947
  """Add an external reference to an object in a metadata component."""
@@ -936,7 +953,7 @@ class _NumbersModel(Cacheable):
936
953
  if is_weak:
937
954
  params["is_weak"] = True
938
955
  component.external_references.append(
939
- TSPArchiveMessages.ComponentExternalReference(**params)
956
+ TSPArchiveMessages.ComponentExternalReference(**params),
940
957
  )
941
958
 
942
959
  def recalculate_table_data(self, table_id: int, data: List):
@@ -980,7 +997,7 @@ class _NumbersModel(Cacheable):
980
997
  "should_use_wide_rows": True,
981
998
  }
982
999
  tile_id, tile = self.objects.create_object_from_dict(
983
- "Index/Tables/Tile-{}", tile_dict, TSTArchives.Tile
1000
+ "Index/Tables/Tile-{}", tile_dict, TSTArchives.Tile,
984
1001
  )
985
1002
  for row in range(row_start, row_end):
986
1003
  row_info = self.recalculate_row_info(table_id, data, row_start, row)
@@ -1023,7 +1040,7 @@ class _NumbersModel(Cacheable):
1023
1040
  height += table_model.default_row_height
1024
1041
  return round(height)
1025
1042
 
1026
- def row_height(self, table_id: int, row: int, height: int = None) -> int:
1043
+ def row_height(self, table_id: int, row: int, height: Optional[int] = None) -> int:
1027
1044
  if height is not None:
1028
1045
  if table_id not in self._row_heights:
1029
1046
  self._row_heights[table_id] = {}
@@ -1059,7 +1076,7 @@ class _NumbersModel(Cacheable):
1059
1076
  width += table_model.default_column_width
1060
1077
  return round(width)
1061
1078
 
1062
- def col_width(self, table_id: int, col: int, width: int = None) -> int:
1079
+ def col_width(self, table_id: int, col: int, width: Optional[int] = None) -> int:
1063
1080
  if width is not None:
1064
1081
  if table_id not in self._col_widths:
1065
1082
  self._col_widths[table_id] = {}
@@ -1079,14 +1096,14 @@ class _NumbersModel(Cacheable):
1079
1096
  else:
1080
1097
  return round(table_model.default_column_width)
1081
1098
 
1082
- def num_header_rows(self, table_id: int, num_headers: int = None) -> int:
1099
+ def num_header_rows(self, table_id: int, num_headers: Optional[int] = None) -> int:
1083
1100
  """Return/set the number of header rows."""
1084
1101
  table_model = self.objects[table_id]
1085
1102
  if num_headers is not None:
1086
1103
  table_model.number_of_header_rows = num_headers
1087
1104
  return table_model.number_of_header_rows
1088
1105
 
1089
- def num_header_cols(self, table_id: int, num_headers: int = None) -> int:
1106
+ def num_header_cols(self, table_id: int, num_headers: Optional[int] = None) -> int:
1090
1107
  """Return/set the number of header columns."""
1091
1108
  table_model = self.objects[table_id]
1092
1109
  if num_headers is not None:
@@ -1108,11 +1125,11 @@ class _NumbersModel(Cacheable):
1108
1125
  def last_table_offset(self, sheet_id):
1109
1126
  """Y offset of the last table in a sheet."""
1110
1127
  table_id = self.table_ids(sheet_id)[-1]
1111
- y_offset = [
1128
+ y_offset = next(
1112
1129
  self.objects[self.table_info_id(x)].super.geometry.position.y
1113
1130
  for x in self.table_ids(sheet_id)
1114
1131
  if x == table_id
1115
- ][0]
1132
+ )
1116
1133
 
1117
1134
  return self.table_height(table_id) + y_offset
1118
1135
 
@@ -1175,7 +1192,7 @@ class _NumbersModel(Cacheable):
1175
1192
  TSTArchives.HeaderStorageBucket,
1176
1193
  )
1177
1194
  self.add_component_metadata(
1178
- column_headers_id, "CalculationEngine", "Tables/HeaderStorageBucket-{}"
1195
+ column_headers_id, "CalculationEngine", "Tables/HeaderStorageBucket-{}",
1179
1196
  )
1180
1197
 
1181
1198
  style_table_id, _ = self.objects.create_object_from_dict(
@@ -1191,7 +1208,7 @@ class _NumbersModel(Cacheable):
1191
1208
  TSTArchives.TableDataList,
1192
1209
  )
1193
1210
  self.add_component_metadata(
1194
- formula_table_id, "CalculationEngine", "Tables/TableDataList-{}"
1211
+ formula_table_id, "CalculationEngine", "Tables/TableDataList-{}",
1195
1212
  )
1196
1213
 
1197
1214
  format_table_pre_bnc_id, _ = self.objects.create_object_from_dict(
@@ -1219,10 +1236,10 @@ class _NumbersModel(Cacheable):
1219
1236
  rowTileTree=TSTArchives.TableRBTree(),
1220
1237
  columnTileTree=TSTArchives.TableRBTree(),
1221
1238
  tiles=TSTArchives.TileStorage(
1222
- tile_size=DEFAULT_TILE_SIZE, should_use_wide_rows=True
1239
+ tile_size=DEFAULT_TILE_SIZE, should_use_wide_rows=True,
1223
1240
  ),
1224
1241
  **data_store_refs,
1225
- )
1242
+ ),
1226
1243
  )
1227
1244
 
1228
1245
  row_headers_id, _ = self.objects.create_object_from_dict(
@@ -1232,10 +1249,10 @@ class _NumbersModel(Cacheable):
1232
1249
  )
1233
1250
 
1234
1251
  self.add_component_metadata(
1235
- row_headers_id, "CalculationEngine", "Tables/HeaderStorageBucket-{}"
1252
+ row_headers_id, "CalculationEngine", "Tables/HeaderStorageBucket-{}",
1236
1253
  )
1237
1254
  table_model.base_data_store.rowHeaders.buckets.append(
1238
- TSPMessages.Reference(identifier=row_headers_id)
1255
+ TSPMessages.Reference(identifier=row_headers_id),
1239
1256
  )
1240
1257
 
1241
1258
  data = [
@@ -1262,7 +1279,7 @@ class _NumbersModel(Cacheable):
1262
1279
  )
1263
1280
 
1264
1281
  self.objects[sheet_id].drawable_infos.append(
1265
- TSPMessages.Reference(identifier=table_info_id)
1282
+ TSPMessages.Reference(identifier=table_info_id),
1266
1283
  )
1267
1284
  return table_model_id
1268
1285
 
@@ -1335,18 +1352,18 @@ class _NumbersModel(Cacheable):
1335
1352
  TSCEArchives.FormulaOwnerDependenciesArchive,
1336
1353
  )
1337
1354
  calc_engine.dependency_tracker.formula_owner_dependencies.append(
1338
- TSPMessages.Reference(identifier=formula_deps_id)
1355
+ TSPMessages.Reference(identifier=formula_deps_id),
1339
1356
  )
1340
1357
  owner_id_map.append(
1341
1358
  TSCEArchives.OwnerIDMapArchive.OwnerIDMapArchiveEntry(
1342
- internal_owner_id=next_owner_id, owner_id=formula_owner_uuid.protobuf4
1343
- )
1359
+ internal_owner_id=next_owner_id, owner_id=formula_owner_uuid.protobuf4,
1360
+ ),
1344
1361
  )
1345
1362
 
1346
1363
  def add_sheet(self, sheet_name: str) -> int:
1347
1364
  """Add a new sheet with a copy of a table from another sheet."""
1348
1365
  sheet_id, _ = self.objects.create_object_from_dict(
1349
- "Document", {"name": sheet_name}, TNArchives.SheetArchive
1366
+ "Document", {"name": sheet_name}, TNArchives.SheetArchive,
1350
1367
  )
1351
1368
 
1352
1369
  self.add_component_reference(sheet_id, "CalculationEngine", DOCUMENT_ID, is_weak=True)
@@ -1457,7 +1474,7 @@ class _NumbersModel(Cacheable):
1457
1474
  TSSArchives.StylesheetArchive.IdentifiedStyleEntry(
1458
1475
  identifier=style_id_name,
1459
1476
  style=TSPMessages.Reference(identifier=para_style_id),
1460
- )
1477
+ ),
1461
1478
  )
1462
1479
 
1463
1480
  theme_id = self.objects[DOCUMENT_ID].theme.identifier
@@ -1553,7 +1570,7 @@ class _NumbersModel(Cacheable):
1553
1570
  preferred_file_name=style.bg_image.filename,
1554
1571
  file_name=style.bg_image.filename,
1555
1572
  materialized_length=len(style.bg_image.data),
1556
- )
1573
+ ),
1557
1574
  )
1558
1575
  self._images[digest] = image_id
1559
1576
  color_attrs = {
@@ -1562,8 +1579,8 @@ class _NumbersModel(Cacheable):
1562
1579
  "technique": "ScaleToFill",
1563
1580
  "imagedata": {"identifier": image_id},
1564
1581
  "interpretsUntaggedImageDataAsGeneric": False,
1565
- }
1566
- }
1582
+ },
1583
+ },
1567
1584
  }
1568
1585
  elif style.bg_color is not None:
1569
1586
  color_attrs = {
@@ -1575,8 +1592,8 @@ class _NumbersModel(Cacheable):
1575
1592
  "b": style.bg_color.b / 255,
1576
1593
  "a": 1.0,
1577
1594
  "rgbspace": "srgb",
1578
- }
1579
- }
1595
+ },
1596
+ },
1580
1597
  }
1581
1598
  else:
1582
1599
  color_attrs = {}
@@ -1612,7 +1629,7 @@ class _NumbersModel(Cacheable):
1612
1629
  TSSArchives.StylesheetArchive.IdentifiedStyleEntry(
1613
1630
  identifier=style_id_name,
1614
1631
  style=TSPMessages.Reference(identifier=cell_style_id),
1615
- )
1632
+ ),
1616
1633
  )
1617
1634
 
1618
1635
  return cell_style_id
@@ -1655,7 +1672,7 @@ class _NumbersModel(Cacheable):
1655
1672
  custom_format_list_id = self.objects[DOCUMENT_ID].super.custom_format_list.identifier
1656
1673
  custom_formats = self.objects[custom_format_list_id].custom_formats
1657
1674
  custom_format_names = [x.name for x in custom_formats]
1658
- custom_format_uuids = [x for x in self.objects[custom_format_list_id].uuids]
1675
+ custom_format_uuids = list(self.objects[custom_format_list_id].uuids)
1659
1676
  self._custom_formats = {}
1660
1677
  self._custom_format_archives = {}
1661
1678
  self._custom_format_uuids = {}
@@ -1776,6 +1793,7 @@ class _NumbersModel(Cacheable):
1776
1793
  "bullet_chars": bullet_chars,
1777
1794
  "hyperlinks": hyperlinks,
1778
1795
  }
1796
+ return None
1779
1797
 
1780
1798
  def cell_text_style(self, cell: Cell) -> object:
1781
1799
  """Return the text style object for the cell or, if none
@@ -1818,6 +1836,7 @@ class _NumbersModel(Cacheable):
1818
1836
  return rgb(cell_properties.color)
1819
1837
  elif cell_properties.HasField("gradient"):
1820
1838
  return [(rgb(s.color)) for s in cell_properties.gradient.stops]
1839
+ return None
1821
1840
 
1822
1841
  def char_property(self, style: object, field: str):
1823
1842
  """Return a char_property field from a style if present
@@ -1948,7 +1967,7 @@ class _NumbersModel(Cacheable):
1948
1967
  return None
1949
1968
 
1950
1969
  def set_cell_border( # noqa: PLR0913
1951
- self, table_id: int, row: int, col: int, side: str, border_value: Border
1970
+ self, table_id: int, row: int, col: int, side: str, border_value: Border,
1952
1971
  ):
1953
1972
  """Set the 2 borders adjacent to a stroke if within the table range."""
1954
1973
  if side == "top":
@@ -2117,7 +2136,7 @@ class _NumbersModel(Cacheable):
2117
2136
  # New stroke in middle of existing stroke
2118
2137
  stroke_run.length = origin - stroke_start
2119
2138
  stroke_layer.stroke_runs.append(
2120
- TSTArchives.StrokeLayerArchive.StrokeRunArchive()
2139
+ TSTArchives.StrokeLayerArchive.StrokeRunArchive(),
2121
2140
  )
2122
2141
  stroke_layer.stroke_runs[-1].CopyFrom(stroke_run)
2123
2142
  stroke_layer.stroke_runs[-1].origin = origin + length
@@ -2140,7 +2159,8 @@ class _NumbersModel(Cacheable):
2140
2159
  """Store image data in the file store."""
2141
2160
  stored_filename = f"Data/{filename}"
2142
2161
  if stored_filename in self.objects.file_store:
2143
- raise IndexError(f"{filename}: image already exists in document")
2162
+ msg = f"{filename}: image already exists in document"
2163
+ raise IndexError(msg)
2144
2164
  self.objects.file_store[stored_filename] = data
2145
2165
 
2146
2166
  def next_image_identifier(self):
@@ -2210,17 +2230,19 @@ def node_to_row_col_ref(node: object, table_name: str, row: int, col: int) -> st
2210
2230
 
2211
2231
 
2212
2232
  def get_storage_buffers_for_row(
2213
- storage_buffer: bytes, offsets: list, num_cols: int, has_wide_offsets: bool
2233
+ storage_buffer: bytes, offsets: list, num_cols: int, has_wide_offsets: bool,
2214
2234
  ) -> List[bytes]:
2215
2235
  """Extract storage buffers for each cell in a table row.
2216
2236
 
2217
2237
  Args:
2238
+ ----
2218
2239
  storage_buffer: cell_storage_buffer or cell_storage_buffer for a table row
2219
2240
  offsets: 16-bit cell offsets for a table row
2220
2241
  num_cols: number of columns in a table row
2221
2242
  has_wide_offsets: use 4-byte offsets rather than 1-byte offset
2222
2243
 
2223
2244
  Returns:
2245
+ -------
2224
2246
  data: list of bytes for each cell in a row, or None if empty
2225
2247
  """
2226
2248
  offsets = array("h", offsets).tolist()
@@ -5,7 +5,7 @@ from numbers_parser.generated import TSPMessages_pb2 as TSPMessages
5
5
 
6
6
 
7
7
  class NumbersUUID(UUID):
8
- def __init__(self, uuid=None):
8
+ def __init__(self, uuid=None) -> None:
9
9
  if uuid is None:
10
10
  super().__init__(int=uuid1().int)
11
11
  elif isinstance(uuid, int):
@@ -33,9 +33,11 @@ class NumbersUUID(UUID):
33
33
  uuid_int = int(uuid["upper"]) << 64 | int(uuid["lower"])
34
34
  super().__init__(int=uuid_int)
35
35
  else:
36
- raise UnsupportedError("Unsupported UUID dict structure")
36
+ msg = "Unsupported UUID dict structure"
37
+ raise UnsupportedError(msg)
37
38
  else:
38
- raise UnsupportedError(f"Unsupported UUID init type {type(uuid).__name__}")
39
+ msg = f"Unsupported UUID init type {type(uuid).__name__}"
40
+ raise UnsupportedError(msg)
39
41
 
40
42
  @property
41
43
  def dict2(self) -> dict:
@@ -69,5 +71,5 @@ class NumbersUUID(UUID):
69
71
  uuid_w1 = (self.int >> 32) & 0xFFFFFFFF
70
72
  uuid_w0 = self.int & 0xFFFFFFFF
71
73
  return TSPMessages.CFUUIDArchive(
72
- uuid_w3=uuid_w3, uuid_w2=uuid_w2, uuid_w1=uuid_w1, uuid_w0=uuid_w0
74
+ uuid_w3=uuid_w3, uuid_w2=uuid_w2, uuid_w1=uuid_w1, uuid_w0=uuid_w0,
73
75
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: numbers-parser
3
- Version: 4.10.3
3
+ Version: 4.10.5
4
4
  Summary: Read and write Apple Numbers spreadsheets
5
5
  Home-page: https://github.com/masaccio/numbers-parser
6
6
  License: MIT
@@ -16,14 +16,14 @@ Classifier: Programming Language :: Python :: 3.11
16
16
  Classifier: Programming Language :: Python :: 3.12
17
17
  Classifier: Topic :: Office/Business :: Financial :: Spreadsheet
18
18
  Requires-Dist: compact-json (>=1.1.3,<2.0.0)
19
- Requires-Dist: enum-tools (>=0.11.0,<0.12.0)
20
- Requires-Dist: importlib-resources (>=6.1.1,<7.0.0)
19
+ Requires-Dist: enum-tools (>=0.11)
20
+ Requires-Dist: importlib-resources (>=6.1)
21
21
  Requires-Dist: pendulum (>=3.0,<4.0)
22
22
  Requires-Dist: protobuf
23
- Requires-Dist: python-snappy (>=0.6.1,<0.7.0)
24
- Requires-Dist: regex (>=2022.9.13,<2023.0.0)
25
- Requires-Dist: roman (>=3.3,<4.0)
26
- Requires-Dist: setuptools (>=69.0.3,<70.0.0)
23
+ Requires-Dist: python-snappy (>=0.7,<0.8)
24
+ Requires-Dist: regex (>2024.0)
25
+ Requires-Dist: roman (>=4.0)
26
+ Requires-Dist: setuptools (>=69.0.3)
27
27
  Requires-Dist: sigfig (>=1.3.2,<2.0.0)
28
28
  Project-URL: Documentation, https://github.com/masaccio/numbers-parser/blob/main/README.md
29
29
  Project-URL: Repository, https://github.com/masaccio/numbers-parser