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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. numbers_parser/__init__.py +1 -1
  2. numbers_parser/_cat_numbers.py +4 -4
  3. numbers_parser/_unpack_numbers.py +5 -5
  4. numbers_parser/cell.py +119 -119
  5. numbers_parser/constants.py +5 -6
  6. numbers_parser/containers.py +11 -8
  7. numbers_parser/document.py +135 -113
  8. numbers_parser/exceptions.py +0 -7
  9. numbers_parser/formula.py +3 -4
  10. numbers_parser/generated/TNArchives_pb2.py +24 -26
  11. numbers_parser/generated/TSAArchives_pb2.py +26 -28
  12. numbers_parser/generated/TSCEArchives_pb2.py +8 -10
  13. numbers_parser/generated/TSCHArchives_GEN_pb2.py +28 -34
  14. numbers_parser/generated/TSCHArchives_pb2.py +61 -65
  15. numbers_parser/generated/TSDArchives_pb2.py +100 -110
  16. numbers_parser/generated/TSKArchives_pb2.py +168 -170
  17. numbers_parser/generated/TSPArchiveMessages_pb2.py +32 -34
  18. numbers_parser/generated/TSPMessages_pb2.py +40 -40
  19. numbers_parser/generated/TSSArchives_pb2.py +36 -36
  20. numbers_parser/generated/TSTArchives_pb2.py +321 -325
  21. numbers_parser/generated/TSTStylePropertyArchiving_pb2.py +8 -10
  22. numbers_parser/generated/TSWPArchives_pb2.py +250 -286
  23. numbers_parser/generated/TSWPCommandArchives_pb2.py +95 -95
  24. numbers_parser/iwafile.py +16 -16
  25. numbers_parser/iwork.py +35 -29
  26. numbers_parser/model.py +64 -52
  27. numbers_parser/numbers_uuid.py +6 -4
  28. {numbers_parser-4.10.4.dist-info → numbers_parser-4.10.5.dist-info}/METADATA +7 -7
  29. {numbers_parser-4.10.4.dist-info → numbers_parser-4.10.5.dist-info}/RECORD +32 -32
  30. {numbers_parser-4.10.4.dist-info → numbers_parser-4.10.5.dist-info}/LICENSE.rst +0 -0
  31. {numbers_parser-4.10.4.dist-info → numbers_parser-4.10.5.dist-info}/WHEEL +0 -0
  32. {numbers_parser-4.10.4.dist-info → numbers_parser-4.10.5.dist-info}/entry_points.txt +0 -0
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
@@ -209,7 +209,7 @@ class _NumbersModel(Cacheable):
209
209
  Not to be used in application code.
210
210
  """
211
211
 
212
- def __init__(self, filepath: Path):
212
+ def __init__(self, filepath: Path) -> None:
213
213
  if filepath is None:
214
214
  filepath = Path(DEFAULT_DOCUMENT)
215
215
  self.objects = ObjectStore(filepath)
@@ -250,6 +250,7 @@ class _NumbersModel(Cacheable):
250
250
  return self.objects[sheet_id].name
251
251
  else:
252
252
  self.objects[sheet_id].name = value
253
+ return None
253
254
 
254
255
  def set_table_data(self, table_id: int, data: List):
255
256
  self._table_data[table_id] = data
@@ -331,10 +332,12 @@ class _NumbersModel(Cacheable):
331
332
  return self.objects[table_id].table_name
332
333
  else:
333
334
  self.objects[table_id].table_name = value
335
+ return None
334
336
 
335
- def table_name_enabled(self, table_id: int, enabled: bool = None):
337
+ def table_name_enabled(self, table_id: int, enabled: Optional[bool] = None):
336
338
  if enabled is not None:
337
339
  self.objects[table_id].table_name_enabled = enabled
340
+ return None
338
341
  else:
339
342
  return self.objects[table_id].table_name_enabled
340
343
 
@@ -359,7 +362,7 @@ class _NumbersModel(Cacheable):
359
362
 
360
363
  @cache(num_args=3)
361
364
  def format_archive(self, table_id: int, format_type: FormattingType, format: Formatting):
362
- """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."""
363
366
  attrs = {x: getattr(format, x) for x in ALLOWED_FORMATTING_PARAMETERS[format_type]}
364
367
  attrs["format_type"] = FORMAT_TYPE_MAP[format_type]
365
368
 
@@ -377,7 +380,7 @@ class _NumbersModel(Cacheable):
377
380
  "value": item,
378
381
  "format": {"format_type": FormatType.TEXT},
379
382
  },
380
- }
383
+ },
381
384
  )
382
385
  else:
383
386
  tsce_items.append(
@@ -387,7 +390,7 @@ class _NumbersModel(Cacheable):
387
390
  "value": item,
388
391
  "format": {"format_type": FormatType.DECIMAL},
389
392
  },
390
- }
393
+ },
391
394
  )
392
395
  popup_menu_id, _ = self.objects.create_object_from_dict(
393
396
  f"Index/Tables/DataList-{parent_id}",
@@ -398,7 +401,7 @@ class _NumbersModel(Cacheable):
398
401
  return popup_menu_id
399
402
 
400
403
  def control_cell_archive(self, table_id: int, format_type: FormattingType, format: Formatting):
401
- """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."""
402
405
  if format_type == FormattingType.TICKBOX:
403
406
  cell_spec = TSTArchives.CellSpecArchive(interaction_type=CellInteractionType.TOGGLE)
404
407
  elif format_type == FormattingType.RATING:
@@ -425,7 +428,7 @@ class _NumbersModel(Cacheable):
425
428
  return self._control_specs.lookup_key(table_id, cell_spec)
426
429
 
427
430
  def add_custom_decimal_format_archive(self, format: CustomFormatting) -> None:
428
- """Create a custom format from the format spec"""
431
+ """Create a custom format from the format spec."""
429
432
  integer_format = format.integer_format
430
433
  decimal_format = format.decimal_format
431
434
  num_integers = format.num_integers
@@ -513,7 +516,7 @@ class _NumbersModel(Cacheable):
513
516
  custom_format_list.uuids.append(format_uuid)
514
517
 
515
518
  def custom_format_id(self, table_id: int, format: CustomFormatting) -> int:
516
- """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."""
517
520
  format_type = CUSTOM_FORMAT_TYPE_MAP[format.type]
518
521
  format_uuid = self._custom_format_uuids[format.name]
519
522
  custom_format = TSKArchives.FormatStructArchive(
@@ -605,12 +608,13 @@ class _NumbersModel(Cacheable):
605
608
  obj = self.objects[dependency_id]
606
609
  # if obj.owner_kind == OwnerKind.HAUNTED_OWNER:
607
610
  if obj.HasField("base_owner_uid") and obj.HasField(
608
- "formula_owner_uid"
611
+ "formula_owner_uid",
609
612
  ): # pragma: no branch
610
613
  base_owner_uid = NumbersUUID(obj.base_owner_uid).hex
611
614
  formula_owner_uid = NumbersUUID(obj.formula_owner_uid).hex
612
615
  if formula_owner_uid == haunted_owner:
613
616
  return base_owner_uid
617
+ return None
614
618
 
615
619
  @cache()
616
620
  def formula_cell_ranges(self, table_id: int) -> list:
@@ -672,7 +676,7 @@ class _NumbersModel(Cacheable):
672
676
  for row in range(row_start, row_end + 1):
673
677
  for col in range(col_start, col_end + 1):
674
678
  self._merge_cells[table_id].add_reference(
675
- row, col, (row_start, col_start, row_end, col_end)
679
+ row, col, (row_start, col_start, row_end, col_end),
676
680
  )
677
681
  self._merge_cells[table_id].add_anchor(row_start, col_start, size)
678
682
 
@@ -695,7 +699,7 @@ class _NumbersModel(Cacheable):
695
699
  for row in range(row_start, row_end + 1):
696
700
  for col in range(col_start, col_end + 1):
697
701
  self._merge_cells[table_id].add_reference(
698
- row, col, (row_start, col_start, row_end, col_end)
702
+ row, col, (row_start, col_start, row_end, col_end),
699
703
  )
700
704
  self._merge_cells[table_id].add_anchor(row_start, col_start, (num_rows, num_columns))
701
705
 
@@ -707,6 +711,7 @@ class _NumbersModel(Cacheable):
707
711
  for sheet_id in self.sheet_ids(): # pragma: no branch
708
712
  if table_id in self.table_ids(sheet_id):
709
713
  return sheet_id
714
+ return None
710
715
 
711
716
  @cache()
712
717
  def table_uuids_to_id(self, table_uuid) -> int:
@@ -714,6 +719,7 @@ class _NumbersModel(Cacheable):
714
719
  for table_id in self.table_ids(sheet_id):
715
720
  if table_uuid == self.table_base_id(table_id):
716
721
  return table_id
722
+ return None
717
723
 
718
724
  def node_to_ref(self, this_table_id: int, row: int, col: int, node):
719
725
  if node.HasField("AST_cross_table_reference_extra_info"):
@@ -793,7 +799,8 @@ class _NumbersModel(Cacheable):
793
799
  buffers = []
794
800
  for tile in self.table_tiles(table_id):
795
801
  if not tile.last_saved_in_BNC:
796
- raise UnsupportedError("Pre-BNC storage is unsupported")
802
+ msg = "Pre-BNC storage is unsupported"
803
+ raise UnsupportedError(msg)
797
804
  for r in tile.rowInfos:
798
805
  buffer = get_storage_buffers_for_row(
799
806
  r.cell_storage_buffer,
@@ -851,7 +858,7 @@ class _NumbersModel(Cacheable):
851
858
  else:
852
859
  width = current_column_widths[col]
853
860
  header = TSTArchives.HeaderStorageBucket.Header(
854
- index=col, numberOfCells=num_rows, size=width, hidingState=0
861
+ index=col, numberOfCells=num_rows, size=width, hidingState=0,
855
862
  )
856
863
  buckets.headers.append(header)
857
864
 
@@ -859,7 +866,7 @@ class _NumbersModel(Cacheable):
859
866
  merge_cells = self.merge_cells(table_id)
860
867
 
861
868
  merge_map_id, merge_map = self.objects.create_object_from_dict(
862
- "CalculationEngine", {}, TSTArchives.MergeRegionMapArchive
869
+ "CalculationEngine", {}, TSTArchives.MergeRegionMapArchive,
863
870
  )
864
871
 
865
872
  merge_cells = self.merge_cells(table_id)
@@ -874,7 +881,7 @@ class _NumbersModel(Cacheable):
874
881
  base_data_store.merge_region_map.CopyFrom(TSPMessages.Reference(identifier=merge_map_id))
875
882
 
876
883
  def recalculate_row_info(
877
- 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,
878
885
  ) -> TSTArchives.TileRowInfo:
879
886
  row_info = TSTArchives.TileRowInfo()
880
887
  row_info.storage_version = 5
@@ -903,7 +910,7 @@ class _NumbersModel(Cacheable):
903
910
  return row_info
904
911
 
905
912
  @cache()
906
- def metadata_component(self, reference: Union[str, int] = None) -> int:
913
+ def metadata_component(self, reference: Optional[Union[str, int]] = None) -> int:
907
914
  """Return the ID of an object in the document metadata given it's name or ID."""
908
915
  component_map = {c.identifier: c for c in self.objects[PACKAGE_ID].components}
909
916
  if isinstance(reference, str):
@@ -933,8 +940,8 @@ class _NumbersModel(Cacheable):
933
940
  def add_component_reference(
934
941
  self,
935
942
  object_id: int,
936
- location: str = None,
937
- parent_id: int = None,
943
+ location: Optional[str] = None,
944
+ parent_id: Optional[int] = None,
938
945
  is_weak: bool = False,
939
946
  ):
940
947
  """Add an external reference to an object in a metadata component."""
@@ -946,7 +953,7 @@ class _NumbersModel(Cacheable):
946
953
  if is_weak:
947
954
  params["is_weak"] = True
948
955
  component.external_references.append(
949
- TSPArchiveMessages.ComponentExternalReference(**params)
956
+ TSPArchiveMessages.ComponentExternalReference(**params),
950
957
  )
951
958
 
952
959
  def recalculate_table_data(self, table_id: int, data: List):
@@ -990,7 +997,7 @@ class _NumbersModel(Cacheable):
990
997
  "should_use_wide_rows": True,
991
998
  }
992
999
  tile_id, tile = self.objects.create_object_from_dict(
993
- "Index/Tables/Tile-{}", tile_dict, TSTArchives.Tile
1000
+ "Index/Tables/Tile-{}", tile_dict, TSTArchives.Tile,
994
1001
  )
995
1002
  for row in range(row_start, row_end):
996
1003
  row_info = self.recalculate_row_info(table_id, data, row_start, row)
@@ -1033,7 +1040,7 @@ class _NumbersModel(Cacheable):
1033
1040
  height += table_model.default_row_height
1034
1041
  return round(height)
1035
1042
 
1036
- 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:
1037
1044
  if height is not None:
1038
1045
  if table_id not in self._row_heights:
1039
1046
  self._row_heights[table_id] = {}
@@ -1069,7 +1076,7 @@ class _NumbersModel(Cacheable):
1069
1076
  width += table_model.default_column_width
1070
1077
  return round(width)
1071
1078
 
1072
- 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:
1073
1080
  if width is not None:
1074
1081
  if table_id not in self._col_widths:
1075
1082
  self._col_widths[table_id] = {}
@@ -1089,14 +1096,14 @@ class _NumbersModel(Cacheable):
1089
1096
  else:
1090
1097
  return round(table_model.default_column_width)
1091
1098
 
1092
- 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:
1093
1100
  """Return/set the number of header rows."""
1094
1101
  table_model = self.objects[table_id]
1095
1102
  if num_headers is not None:
1096
1103
  table_model.number_of_header_rows = num_headers
1097
1104
  return table_model.number_of_header_rows
1098
1105
 
1099
- 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:
1100
1107
  """Return/set the number of header columns."""
1101
1108
  table_model = self.objects[table_id]
1102
1109
  if num_headers is not None:
@@ -1118,11 +1125,11 @@ class _NumbersModel(Cacheable):
1118
1125
  def last_table_offset(self, sheet_id):
1119
1126
  """Y offset of the last table in a sheet."""
1120
1127
  table_id = self.table_ids(sheet_id)[-1]
1121
- y_offset = [
1128
+ y_offset = next(
1122
1129
  self.objects[self.table_info_id(x)].super.geometry.position.y
1123
1130
  for x in self.table_ids(sheet_id)
1124
1131
  if x == table_id
1125
- ][0]
1132
+ )
1126
1133
 
1127
1134
  return self.table_height(table_id) + y_offset
1128
1135
 
@@ -1185,7 +1192,7 @@ class _NumbersModel(Cacheable):
1185
1192
  TSTArchives.HeaderStorageBucket,
1186
1193
  )
1187
1194
  self.add_component_metadata(
1188
- column_headers_id, "CalculationEngine", "Tables/HeaderStorageBucket-{}"
1195
+ column_headers_id, "CalculationEngine", "Tables/HeaderStorageBucket-{}",
1189
1196
  )
1190
1197
 
1191
1198
  style_table_id, _ = self.objects.create_object_from_dict(
@@ -1201,7 +1208,7 @@ class _NumbersModel(Cacheable):
1201
1208
  TSTArchives.TableDataList,
1202
1209
  )
1203
1210
  self.add_component_metadata(
1204
- formula_table_id, "CalculationEngine", "Tables/TableDataList-{}"
1211
+ formula_table_id, "CalculationEngine", "Tables/TableDataList-{}",
1205
1212
  )
1206
1213
 
1207
1214
  format_table_pre_bnc_id, _ = self.objects.create_object_from_dict(
@@ -1229,10 +1236,10 @@ class _NumbersModel(Cacheable):
1229
1236
  rowTileTree=TSTArchives.TableRBTree(),
1230
1237
  columnTileTree=TSTArchives.TableRBTree(),
1231
1238
  tiles=TSTArchives.TileStorage(
1232
- tile_size=DEFAULT_TILE_SIZE, should_use_wide_rows=True
1239
+ tile_size=DEFAULT_TILE_SIZE, should_use_wide_rows=True,
1233
1240
  ),
1234
1241
  **data_store_refs,
1235
- )
1242
+ ),
1236
1243
  )
1237
1244
 
1238
1245
  row_headers_id, _ = self.objects.create_object_from_dict(
@@ -1242,10 +1249,10 @@ class _NumbersModel(Cacheable):
1242
1249
  )
1243
1250
 
1244
1251
  self.add_component_metadata(
1245
- row_headers_id, "CalculationEngine", "Tables/HeaderStorageBucket-{}"
1252
+ row_headers_id, "CalculationEngine", "Tables/HeaderStorageBucket-{}",
1246
1253
  )
1247
1254
  table_model.base_data_store.rowHeaders.buckets.append(
1248
- TSPMessages.Reference(identifier=row_headers_id)
1255
+ TSPMessages.Reference(identifier=row_headers_id),
1249
1256
  )
1250
1257
 
1251
1258
  data = [
@@ -1272,7 +1279,7 @@ class _NumbersModel(Cacheable):
1272
1279
  )
1273
1280
 
1274
1281
  self.objects[sheet_id].drawable_infos.append(
1275
- TSPMessages.Reference(identifier=table_info_id)
1282
+ TSPMessages.Reference(identifier=table_info_id),
1276
1283
  )
1277
1284
  return table_model_id
1278
1285
 
@@ -1345,18 +1352,18 @@ class _NumbersModel(Cacheable):
1345
1352
  TSCEArchives.FormulaOwnerDependenciesArchive,
1346
1353
  )
1347
1354
  calc_engine.dependency_tracker.formula_owner_dependencies.append(
1348
- TSPMessages.Reference(identifier=formula_deps_id)
1355
+ TSPMessages.Reference(identifier=formula_deps_id),
1349
1356
  )
1350
1357
  owner_id_map.append(
1351
1358
  TSCEArchives.OwnerIDMapArchive.OwnerIDMapArchiveEntry(
1352
- internal_owner_id=next_owner_id, owner_id=formula_owner_uuid.protobuf4
1353
- )
1359
+ internal_owner_id=next_owner_id, owner_id=formula_owner_uuid.protobuf4,
1360
+ ),
1354
1361
  )
1355
1362
 
1356
1363
  def add_sheet(self, sheet_name: str) -> int:
1357
1364
  """Add a new sheet with a copy of a table from another sheet."""
1358
1365
  sheet_id, _ = self.objects.create_object_from_dict(
1359
- "Document", {"name": sheet_name}, TNArchives.SheetArchive
1366
+ "Document", {"name": sheet_name}, TNArchives.SheetArchive,
1360
1367
  )
1361
1368
 
1362
1369
  self.add_component_reference(sheet_id, "CalculationEngine", DOCUMENT_ID, is_weak=True)
@@ -1467,7 +1474,7 @@ class _NumbersModel(Cacheable):
1467
1474
  TSSArchives.StylesheetArchive.IdentifiedStyleEntry(
1468
1475
  identifier=style_id_name,
1469
1476
  style=TSPMessages.Reference(identifier=para_style_id),
1470
- )
1477
+ ),
1471
1478
  )
1472
1479
 
1473
1480
  theme_id = self.objects[DOCUMENT_ID].theme.identifier
@@ -1563,7 +1570,7 @@ class _NumbersModel(Cacheable):
1563
1570
  preferred_file_name=style.bg_image.filename,
1564
1571
  file_name=style.bg_image.filename,
1565
1572
  materialized_length=len(style.bg_image.data),
1566
- )
1573
+ ),
1567
1574
  )
1568
1575
  self._images[digest] = image_id
1569
1576
  color_attrs = {
@@ -1572,8 +1579,8 @@ class _NumbersModel(Cacheable):
1572
1579
  "technique": "ScaleToFill",
1573
1580
  "imagedata": {"identifier": image_id},
1574
1581
  "interpretsUntaggedImageDataAsGeneric": False,
1575
- }
1576
- }
1582
+ },
1583
+ },
1577
1584
  }
1578
1585
  elif style.bg_color is not None:
1579
1586
  color_attrs = {
@@ -1585,8 +1592,8 @@ class _NumbersModel(Cacheable):
1585
1592
  "b": style.bg_color.b / 255,
1586
1593
  "a": 1.0,
1587
1594
  "rgbspace": "srgb",
1588
- }
1589
- }
1595
+ },
1596
+ },
1590
1597
  }
1591
1598
  else:
1592
1599
  color_attrs = {}
@@ -1622,7 +1629,7 @@ class _NumbersModel(Cacheable):
1622
1629
  TSSArchives.StylesheetArchive.IdentifiedStyleEntry(
1623
1630
  identifier=style_id_name,
1624
1631
  style=TSPMessages.Reference(identifier=cell_style_id),
1625
- )
1632
+ ),
1626
1633
  )
1627
1634
 
1628
1635
  return cell_style_id
@@ -1665,7 +1672,7 @@ class _NumbersModel(Cacheable):
1665
1672
  custom_format_list_id = self.objects[DOCUMENT_ID].super.custom_format_list.identifier
1666
1673
  custom_formats = self.objects[custom_format_list_id].custom_formats
1667
1674
  custom_format_names = [x.name for x in custom_formats]
1668
- 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)
1669
1676
  self._custom_formats = {}
1670
1677
  self._custom_format_archives = {}
1671
1678
  self._custom_format_uuids = {}
@@ -1786,6 +1793,7 @@ class _NumbersModel(Cacheable):
1786
1793
  "bullet_chars": bullet_chars,
1787
1794
  "hyperlinks": hyperlinks,
1788
1795
  }
1796
+ return None
1789
1797
 
1790
1798
  def cell_text_style(self, cell: Cell) -> object:
1791
1799
  """Return the text style object for the cell or, if none
@@ -1828,6 +1836,7 @@ class _NumbersModel(Cacheable):
1828
1836
  return rgb(cell_properties.color)
1829
1837
  elif cell_properties.HasField("gradient"):
1830
1838
  return [(rgb(s.color)) for s in cell_properties.gradient.stops]
1839
+ return None
1831
1840
 
1832
1841
  def char_property(self, style: object, field: str):
1833
1842
  """Return a char_property field from a style if present
@@ -1958,7 +1967,7 @@ class _NumbersModel(Cacheable):
1958
1967
  return None
1959
1968
 
1960
1969
  def set_cell_border( # noqa: PLR0913
1961
- 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,
1962
1971
  ):
1963
1972
  """Set the 2 borders adjacent to a stroke if within the table range."""
1964
1973
  if side == "top":
@@ -2127,7 +2136,7 @@ class _NumbersModel(Cacheable):
2127
2136
  # New stroke in middle of existing stroke
2128
2137
  stroke_run.length = origin - stroke_start
2129
2138
  stroke_layer.stroke_runs.append(
2130
- TSTArchives.StrokeLayerArchive.StrokeRunArchive()
2139
+ TSTArchives.StrokeLayerArchive.StrokeRunArchive(),
2131
2140
  )
2132
2141
  stroke_layer.stroke_runs[-1].CopyFrom(stroke_run)
2133
2142
  stroke_layer.stroke_runs[-1].origin = origin + length
@@ -2150,7 +2159,8 @@ class _NumbersModel(Cacheable):
2150
2159
  """Store image data in the file store."""
2151
2160
  stored_filename = f"Data/{filename}"
2152
2161
  if stored_filename in self.objects.file_store:
2153
- raise IndexError(f"{filename}: image already exists in document")
2162
+ msg = f"{filename}: image already exists in document"
2163
+ raise IndexError(msg)
2154
2164
  self.objects.file_store[stored_filename] = data
2155
2165
 
2156
2166
  def next_image_identifier(self):
@@ -2220,17 +2230,19 @@ def node_to_row_col_ref(node: object, table_name: str, row: int, col: int) -> st
2220
2230
 
2221
2231
 
2222
2232
  def get_storage_buffers_for_row(
2223
- 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,
2224
2234
  ) -> List[bytes]:
2225
2235
  """Extract storage buffers for each cell in a table row.
2226
2236
 
2227
2237
  Args:
2238
+ ----
2228
2239
  storage_buffer: cell_storage_buffer or cell_storage_buffer for a table row
2229
2240
  offsets: 16-bit cell offsets for a table row
2230
2241
  num_cols: number of columns in a table row
2231
2242
  has_wide_offsets: use 4-byte offsets rather than 1-byte offset
2232
2243
 
2233
2244
  Returns:
2245
+ -------
2234
2246
  data: list of bytes for each cell in a row, or None if empty
2235
2247
  """
2236
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.4
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
@@ -1,59 +1,59 @@
1
- numbers_parser/__init__.py,sha256=w0ZhMcFpVol1VwjyYHjvqBmshvsMDfLIyFX-GmpOpMQ,1410
2
- numbers_parser/_cat_numbers.py,sha256=-HboBJT11Vjcr8sjLZl7Z6qAapnPEc_kFYq6PTqON20,4619
3
- numbers_parser/_unpack_numbers.py,sha256=U5SL16uNNe0BvYtUtIYJT-t3RN36Q8U-8UTr7lnOylw,7040
1
+ numbers_parser/__init__.py,sha256=1guReSiMinXSKkip4UoC-a1X9OAgdiYTTDiZ03FDmqE,1411
2
+ numbers_parser/_cat_numbers.py,sha256=3tLvBQEagGcNL26XxfqguNim0JDtTNgEbiGKpLjBxLI,4623
3
+ numbers_parser/_unpack_numbers.py,sha256=PNEENAir573lxIbocK5WdY2KIhIak323ixvNyp7S0js,7004
4
4
  numbers_parser/bullets.py,sha256=OnVVMPjhTDrC-ncw52Gb00UEXNmn2Rvd3xi7lfqW3hk,2616
5
- numbers_parser/cell.py,sha256=q8gDmrncUpZTNx-XGfTRDToDVFudSkOMhDLMOEJU5ss,75511
6
- numbers_parser/constants.py,sha256=gROxeu8wDj-a96rWy2bR_c8CoF0RagqWI3V4SE6SN4M,9908
7
- numbers_parser/containers.py,sha256=wbIE5jIKSAEVUyDv7kSCMkfb_J6oBY3uFm4puVZoLt4,4826
5
+ numbers_parser/cell.py,sha256=9egV1a9vd8ozchz7CENyAw-ftq0tz66uhLunuoh3rOU,75971
6
+ numbers_parser/constants.py,sha256=CyZvHPKHtET2TgpD-eiCS2vkoz8U5Of43rxPnAD0RgM,9912
7
+ numbers_parser/containers.py,sha256=j0FhaXPUG5YSRK5_3WIxXQOeckHVu24KMlYetWIZ_Xg,4882
8
8
  numbers_parser/currencies.py,sha256=8k4a3WKmDoHeurkDICymHX13N7ManHSTaka_JNXCZYA,3767
9
9
  numbers_parser/data/empty.numbers,sha256=8JOp035V-p2ff9_Wao7mLcYvb6_if6O2cus_esjVA9k,90316
10
- numbers_parser/document.py,sha256=34BegFJnEONgaAJbKG5zlaiJ4RnaJmQw3Zbw54SM8YM,56813
11
- numbers_parser/exceptions.py,sha256=G8dASUQZI8ksHYRVfdGWJzgsJD5CBpcZvmDJUZTqT-c,670
10
+ numbers_parser/document.py,sha256=DJkignOeTppAAoSWR-qz5x9NQ9HuCC4KvdMHN6zZ5RM,57593
11
+ numbers_parser/exceptions.py,sha256=0Jnmw06YlGvYcvzqc2wiR2Y4eAgvFJLpf0tFrsmlyPU,607
12
12
  numbers_parser/experimental.py,sha256=WARjTa-2ePb8Ga8Q6oDP6EJCs12ofLRF2YpwzUu66ZI,374
13
- numbers_parser/formula.py,sha256=JRsG0L21wS70oJ-FB46Amyoy-sKizWb-iUhSXUcVJ-U,10572
14
- numbers_parser/generated/TNArchives_pb2.py,sha256=txkTtPHvdXVvv7zO1dHCxxnixaFulK7hJVLQrH3cIJc,16007
13
+ numbers_parser/formula.py,sha256=4KQIhS6NMOdvz9rLsaVqXGnUDA4QCDpH8Lrz516PoU0,10574
14
+ numbers_parser/generated/TNArchives_pb2.py,sha256=cps3nLPpNWdSxhxmpWTDXiWeTE7HzxHcuaOReuY01v0,15834
15
15
  numbers_parser/generated/TNArchives_sos_pb2.py,sha256=AYI1X5t5Gb4l941jXlHEY0v97ToIze0bSYBR7KQmS0A,1215
16
16
  numbers_parser/generated/TNCommandArchives_pb2.py,sha256=AtDBJ_r-slDRVzHxJdXXZPAhpf-jpHj27ujIa2-aPtg,18271
17
17
  numbers_parser/generated/TNCommandArchives_sos_pb2.py,sha256=MhIENEtVylmebThyhglAwO6dhu23UuF2DvdxtUoEvf0,1857
18
- numbers_parser/generated/TSAArchives_pb2.py,sha256=Vz-K_0x8odnkmkXVBxwRPAfYDOBzJZpl3xHYysHQRHQ,19980
18
+ numbers_parser/generated/TSAArchives_pb2.py,sha256=P6IPcixKO2NdgJISbipbsCTI25SPjGMBqwsaRd5DxwE,19809
19
19
  numbers_parser/generated/TSAArchives_sos_pb2.py,sha256=UlEScYhun_N-Cbr2v5RcgvJuwkloUuPJbrWxnQTOAfo,2033
20
20
  numbers_parser/generated/TSACommandArchives_sos_pb2.py,sha256=dyjRN08Ly1qp5m3jcOE5yClARAzg5KyOYNMWyplRq8w,3907
21
- numbers_parser/generated/TSCEArchives_pb2.py,sha256=7RdPzirr4sR4pTdoHNOC-THKnei-asC_yqjwztyUcM0,64955
21
+ numbers_parser/generated/TSCEArchives_pb2.py,sha256=BgV0Bw70bSLqs9v_q75HxT5_VTu4pb75AFVuOJUxOpo,64758
22
22
  numbers_parser/generated/TSCH3DArchives_pb2.py,sha256=eV4GahEGv_3nGNgnN6xc3kfJ07UT3oALlLeJdh0GcQ4,11162
23
23
  numbers_parser/generated/TSCHArchives_Common_pb2.py,sha256=dqgymAVSSQmjp3XuuXFRfXoSXhbQqaQXWbd-JUJs7Nc,8655
24
- numbers_parser/generated/TSCHArchives_GEN_pb2.py,sha256=7a7gO3kjo8t7MHz1Zvj7_aZAR6oWGZ1HQWkJ3axkDZE,46323
25
- numbers_parser/generated/TSCHArchives_pb2.py,sha256=ARMdbSdTJswBxuJ28pYJze--KgxGfsEPZyuPTSDOBlI,24187
24
+ numbers_parser/generated/TSCHArchives_GEN_pb2.py,sha256=_v3oN76ohi0uDlzoIg6AZnGWyirjLzhBSRLunsFkSco,45616
25
+ numbers_parser/generated/TSCHArchives_pb2.py,sha256=r4iqZeywfS8kHaZoeMWUfXAXXycrSyhwyp0JpIVsPME,23803
26
26
  numbers_parser/generated/TSCHArchives_sos_pb2.py,sha256=xyzFKVpIc_SriTn-z_Y7-HkDSRwVfjwE_bl5WwHd0p0,63730
27
27
  numbers_parser/generated/TSCHCommandArchives_pb2.py,sha256=DkJUuBn-LXiY3a5rXipzFxb2mvOthHOKXdjaxYgt0as,27446
28
28
  numbers_parser/generated/TSCHPreUFFArchives_pb2.py,sha256=EWhd5HcquCEYeFac1hwlHJuWu1glbTicfa2MaKK-XPY,30051
29
- numbers_parser/generated/TSDArchives_pb2.py,sha256=W-8aRx9ziL0UjzRy3Fzb9sNx5U3wE9S7sy7pD2JlEOc,40151
29
+ numbers_parser/generated/TSDArchives_pb2.py,sha256=G5vUxZbx66eTdNgxbagUQmo6N7pvfoXwU07jBgv90cU,39093
30
30
  numbers_parser/generated/TSDArchives_sos_pb2.py,sha256=Q2MYAXjAW-PGE3FY8kFH89rry9PPUQv7DS956wymFwo,6022
31
31
  numbers_parser/generated/TSDCommandArchives_pb2.py,sha256=DFxngZeWeqjBc-Y_EZxP1emHK5I_qQj5ewkc_xq_gfo,29192
32
- numbers_parser/generated/TSKArchives_pb2.py,sha256=yEyn4FvOuoJR5bHKdHRq8WWjNsGqkaCX7DKu9aNAOv8,53520
32
+ numbers_parser/generated/TSKArchives_pb2.py,sha256=naNFAUk-D-rtD2vq-X2K6N7IOtDapBxF-ms4vVpdn-I,53324
33
33
  numbers_parser/generated/TSKArchives_sos_pb2.py,sha256=Pi6hjw0g3JSrZ-y0gbqkojRB6_abYavqwoygiqmxgYE,1941
34
- numbers_parser/generated/TSPArchiveMessages_pb2.py,sha256=NPRQWkREv0cPw8aXU4Yye0u3ueyEGnl01mOnl8RGcfQ,18142
34
+ numbers_parser/generated/TSPArchiveMessages_pb2.py,sha256=5Th08Q19AOsMEMggvM9fda1StJjV8LTDDI5x7pY6aM8,17950
35
35
  numbers_parser/generated/TSPDatabaseMessages_pb2.py,sha256=_jvq890xBQpSDcYOKgII30XlxukPBRZBu0kkRpbJ-z0,2024
36
- numbers_parser/generated/TSPMessages_pb2.py,sha256=DoGOVcVTGPuBDMlfpoZtmfxpaCwgDyjacXD6KoR-GOw,12975
37
- numbers_parser/generated/TSSArchives_pb2.py,sha256=iXl1r0Cze_25pKrQMvYjD4INFrGMiawYD8odsJhgJjU,9806
36
+ numbers_parser/generated/TSPMessages_pb2.py,sha256=LBHRhNnQdDu226sh3gK_AOjbO3LDkGCWpVi1wzf7emA,13032
37
+ numbers_parser/generated/TSSArchives_pb2.py,sha256=grvUGHXl2hHcXKzsuoxyquskuo0cV1y841hHERFiYz0,9893
38
38
  numbers_parser/generated/TSSArchives_sos_pb2.py,sha256=FAhtvQ9TBg18AcIk4HwGCreNWlEu3k_kK_9jRVsh7FM,2842
39
- numbers_parser/generated/TSTArchives_pb2.py,sha256=GSy8qjNbqTS8-09srh1zV9bo219KaIB_UJxk1EsrS7c,88532
39
+ numbers_parser/generated/TSTArchives_pb2.py,sha256=smmTu4cTaCsX4Jp0TpVuuzaS_KYznpUB-h-4vZg82Yg,88138
40
40
  numbers_parser/generated/TSTArchives_sos_pb2.py,sha256=JxiMXSdTH5VJo-c5zDdD_tzGQCTrUDE2K0YP_x-zh84,12597
41
41
  numbers_parser/generated/TSTCommandArchives_pb2.py,sha256=LEyGJBOLdhxVarepxGfHprNs8vIAmSCO-iNnl3Afdkk,59523
42
- numbers_parser/generated/TSTStylePropertyArchiving_pb2.py,sha256=z66IxH-81Lp5VicOQc4tBbIHOxEyTRHAi7vlW6HDrBM,12644
43
- numbers_parser/generated/TSWPArchives_pb2.py,sha256=yQkd0s-4x8kIcO-ZPaiyZKotfL0MLC3IfszU2fq6jZ8,59149
42
+ numbers_parser/generated/TSTStylePropertyArchiving_pb2.py,sha256=0ADsIwTk4GcTeQJRhYxEEjsD_SuLEOSUaGYdHnsO9CA,12415
43
+ numbers_parser/generated/TSWPArchives_pb2.py,sha256=1jndSYYOlamxOkUlcWeDgdScduqX9OhJy2HSuZEKFhU,55326
44
44
  numbers_parser/generated/TSWPArchives_sos_pb2.py,sha256=poJ49WA4JjZsHpmROyv4jFl2xGpJy6pTRCaJQZ5ZGr0,29114
45
- numbers_parser/generated/TSWPCommandArchives_pb2.py,sha256=CIb___7pyWeRF4x-HVzzgVfuHvbyW8NY9dByQKEG6dM,25441
45
+ numbers_parser/generated/TSWPCommandArchives_pb2.py,sha256=LCAklKgtN5EZt8cvO6jELYHyZhRqYunvbanV79a4Gu4,25482
46
46
  numbers_parser/generated/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
47
  numbers_parser/generated/fontmap.py,sha256=pqc1HwwTr3UbFMmhUaHJg1dX5-3pXbyhfS2bkdZHKnI,22748
48
48
  numbers_parser/generated/functionmap.py,sha256=VdZo0ERMYONcrnJFwABcSCHb8pjA4wY2ogt8Janz57M,6082
49
- numbers_parser/iwafile.py,sha256=xHDBZWd5EEaPHonlAAl4OYmmaXg_Nw4H0OmItt91URg,11861
50
- numbers_parser/iwork.py,sha256=U0Irxt-3v3vFP_feCuYMDxWUgqeq_YHMCfw1tsDpUcM,8947
49
+ numbers_parser/iwafile.py,sha256=zTRpKqKDtxTImbBsGL6QSpCCDfJoLsTKX5YXbBzzVI8,11917
50
+ numbers_parser/iwork.py,sha256=DtaBHh9_QGEVnz8t2DpttoBdo3zqCRY6_G2_PZ4kOj0,9143
51
51
  numbers_parser/mapping.py,sha256=in8W3S8DmTcPefFaxnATLw0FQ4YnFsnAE-cl5dljzJE,32215
52
- numbers_parser/model.py,sha256=oCiTOxpEhhvudbXzIC13ndurnf8EqUxF-Ggj9HbSADM,97562
52
+ numbers_parser/model.py,sha256=RAZlzZUirO_bjGdjsVTgwuVVx1hGsBtXjDiNujpC2uE,97956
53
53
  numbers_parser/numbers_cache.py,sha256=1ghEBghQAYFpPiEeOtb74i016mXc039v1pOubbqvaLs,1141
54
- numbers_parser/numbers_uuid.py,sha256=-LeAj_ULC0va57pEmyegGY0xXqkNNjyuLukCaiQJhOk,2642
55
- numbers_parser-4.10.4.dist-info/LICENSE.rst,sha256=8vTa1-5KSdHrTpU9rlheO5005EWReEPMpjV7BjSaMc4,1050
56
- numbers_parser-4.10.4.dist-info/METADATA,sha256=QF_jum826aFf8A3YMFPNAGeKZ-7OcgiFMHGVh8Q6mXk,16267
57
- numbers_parser-4.10.4.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
58
- numbers_parser-4.10.4.dist-info/entry_points.txt,sha256=V91uB9vBPxf3eCY1h-0syv21imYCT0MJfMxf87DmwIk,115
59
- numbers_parser-4.10.4.dist-info/RECORD,,
54
+ numbers_parser/numbers_uuid.py,sha256=q0IbHFKuBXC7MnZN3g55dgCVKOLD-4SO4MdXeN6dt0g,2699
55
+ numbers_parser-4.10.5.dist-info/LICENSE.rst,sha256=8vTa1-5KSdHrTpU9rlheO5005EWReEPMpjV7BjSaMc4,1050
56
+ numbers_parser-4.10.5.dist-info/METADATA,sha256=IfxVa2fGAEUt6EZMLi_k-KuaKseoUc_zv1nZTeD4siI,16217
57
+ numbers_parser-4.10.5.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
58
+ numbers_parser-4.10.5.dist-info/entry_points.txt,sha256=V91uB9vBPxf3eCY1h-0syv21imYCT0MJfMxf87DmwIk,115
59
+ numbers_parser-4.10.5.dist-info/RECORD,,