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.
- numbers_parser/__init__.py +1 -1
- numbers_parser/_cat_numbers.py +4 -4
- numbers_parser/_unpack_numbers.py +5 -5
- numbers_parser/cell.py +119 -119
- numbers_parser/constants.py +5 -6
- numbers_parser/containers.py +13 -7
- numbers_parser/document.py +135 -113
- numbers_parser/exceptions.py +0 -7
- numbers_parser/formula.py +3 -4
- numbers_parser/generated/TNArchives_pb2.py +24 -26
- numbers_parser/generated/TSAArchives_pb2.py +26 -28
- numbers_parser/generated/TSCEArchives_pb2.py +8 -10
- numbers_parser/generated/TSCHArchives_GEN_pb2.py +28 -34
- numbers_parser/generated/TSCHArchives_pb2.py +61 -65
- numbers_parser/generated/TSDArchives_pb2.py +100 -110
- numbers_parser/generated/TSKArchives_pb2.py +168 -170
- numbers_parser/generated/TSPArchiveMessages_pb2.py +32 -34
- numbers_parser/generated/TSPMessages_pb2.py +40 -40
- numbers_parser/generated/TSSArchives_pb2.py +36 -36
- numbers_parser/generated/TSTArchives_pb2.py +321 -325
- numbers_parser/generated/TSTStylePropertyArchiving_pb2.py +8 -10
- numbers_parser/generated/TSWPArchives_pb2.py +250 -286
- numbers_parser/generated/TSWPCommandArchives_pb2.py +95 -95
- numbers_parser/iwafile.py +16 -16
- numbers_parser/iwork.py +35 -29
- numbers_parser/model.py +77 -55
- numbers_parser/numbers_uuid.py +6 -4
- {numbers_parser-4.10.3.dist-info → numbers_parser-4.10.5.dist-info}/METADATA +7 -7
- {numbers_parser-4.10.3.dist-info → numbers_parser-4.10.5.dist-info}/RECORD +32 -32
- {numbers_parser-4.10.3.dist-info → numbers_parser-4.10.5.dist-info}/LICENSE.rst +0 -0
- {numbers_parser-4.10.3.dist-info → numbers_parser-4.10.5.dist-info}/WHEEL +0 -0
- {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]["
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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()
|
numbers_parser/numbers_uuid.py
CHANGED
|
@@ -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
|
-
|
|
36
|
+
msg = "Unsupported UUID dict structure"
|
|
37
|
+
raise UnsupportedError(msg)
|
|
37
38
|
else:
|
|
38
|
-
|
|
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
|
+
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
|
|
20
|
-
Requires-Dist: importlib-resources (>=6.1
|
|
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.
|
|
24
|
-
Requires-Dist: regex (
|
|
25
|
-
Requires-Dist: roman (>=
|
|
26
|
-
Requires-Dist: setuptools (>=69.0.3
|
|
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
|