numbers-parser 4.17.0.post1__py3-none-any.whl → 4.18.0__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/_cat_numbers.py +15 -4
- numbers_parser/cell.py +3 -15
- numbers_parser/document.py +42 -30
- numbers_parser/exceptions.py +1 -1
- numbers_parser/experimental.py +21 -7
- numbers_parser/formula.py +2 -413
- numbers_parser/model.py +73 -81
- numbers_parser/xrefs.py +0 -2
- {numbers_parser-4.17.0.post1.dist-info → numbers_parser-4.18.0.dist-info}/METADATA +35 -121
- {numbers_parser-4.17.0.post1.dist-info → numbers_parser-4.18.0.dist-info}/RECORD +14 -15
- numbers_parser/tokenizer.py +0 -548
- {numbers_parser-4.17.0.post1.dist-info → numbers_parser-4.18.0.dist-info}/WHEEL +0 -0
- {numbers_parser-4.17.0.post1.dist-info → numbers_parser-4.18.0.dist-info}/entry_points.txt +0 -0
- {numbers_parser-4.17.0.post1.dist-info → numbers_parser-4.18.0.dist-info}/licenses/LICENSE.rst +0 -0
- {numbers_parser-4.17.0.post1.dist-info → numbers_parser-4.18.0.dist-info}/top_level.txt +0 -0
numbers_parser/model.py
CHANGED
|
@@ -807,38 +807,6 @@ class _NumbersModel(Cacheable):
|
|
|
807
807
|
# Table can be empty if the document does not use FormulaOwnerDependenciesArchive
|
|
808
808
|
return self._table_id_to_base_id.get(table_id)
|
|
809
809
|
|
|
810
|
-
def get_formula_owner(self, table_id: int) -> object:
|
|
811
|
-
table_uuid = self.table_base_id(table_id)
|
|
812
|
-
return self.objects[self._table_base_id_to_formula_owner_id[table_uuid]]
|
|
813
|
-
|
|
814
|
-
def add_formula_dependency(self, row: int, col: int, table_id: int) -> None:
|
|
815
|
-
calc_engine = self.calc_engine()
|
|
816
|
-
calc_engine.dependency_tracker.number_of_formulas += 1
|
|
817
|
-
internal_formula_id = calc_engine.dependency_tracker.number_of_formulas
|
|
818
|
-
|
|
819
|
-
formula_owner = self.get_formula_owner(table_id)
|
|
820
|
-
formula_owner.cell_dependencies.cell_record.append(
|
|
821
|
-
TSCEArchives.CellRecordExpandedArchive(column=col, row=row),
|
|
822
|
-
)
|
|
823
|
-
if len(formula_owner.tiled_cell_dependencies.cell_record_tiles) == 0:
|
|
824
|
-
cell_record_id, cell_record = self.objects.create_object_from_dict(
|
|
825
|
-
"CalculationEngine",
|
|
826
|
-
{
|
|
827
|
-
"internal_owner_id": internal_formula_id,
|
|
828
|
-
"tile_column_begin": 0,
|
|
829
|
-
"tile_row_begin": 0,
|
|
830
|
-
},
|
|
831
|
-
TSCEArchives.CellRecordTileArchive,
|
|
832
|
-
)
|
|
833
|
-
formula_owner.tiled_cell_dependencies.cell_record_tiles.append(
|
|
834
|
-
TSPMessages.Reference(identifier=cell_record_id),
|
|
835
|
-
)
|
|
836
|
-
else:
|
|
837
|
-
cell_record_id = formula_owner.tiled_cell_dependencies.cell_record_tiles[0].identifier
|
|
838
|
-
cell_record = self.objects[cell_record_id]
|
|
839
|
-
|
|
840
|
-
cell_record.cell_records.append(formula_owner.cell_dependencies.cell_record[-1])
|
|
841
|
-
|
|
842
810
|
@cache(num_args=0)
|
|
843
811
|
def calc_engine_id(self):
|
|
844
812
|
"""Return the CalculationEngine ID for the current document."""
|
|
@@ -867,7 +835,7 @@ class _NumbersModel(Cacheable):
|
|
|
867
835
|
self._merge_cells[table_id].add_anchor(row_start, col_start, size)
|
|
868
836
|
|
|
869
837
|
@cache()
|
|
870
|
-
def
|
|
838
|
+
def calculate_merges_using_formula_stores(self, table_id) -> None:
|
|
871
839
|
table_model = self.objects[table_id]
|
|
872
840
|
formulas = table_model.merge_owner.formula_store.formulas
|
|
873
841
|
if len(formulas) == 0:
|
|
@@ -887,7 +855,7 @@ class _NumbersModel(Cacheable):
|
|
|
887
855
|
)
|
|
888
856
|
|
|
889
857
|
@cache()
|
|
890
|
-
def
|
|
858
|
+
def calculate_merges_using_dependency_archives(self, table_id) -> None:
|
|
891
859
|
"""Extract all the merge cell ranges for the Table."""
|
|
892
860
|
# See details in Numbers.md#merge-ranges.
|
|
893
861
|
owner_id_map = self.owner_id_map()
|
|
@@ -910,6 +878,8 @@ class _NumbersModel(Cacheable):
|
|
|
910
878
|
record_range.bottom_right_column,
|
|
911
879
|
)
|
|
912
880
|
|
|
881
|
+
@cache()
|
|
882
|
+
def calculate_merges_using_region_map(self, table_id) -> None:
|
|
913
883
|
base_data_store = self.objects[table_id].base_data_store
|
|
914
884
|
if base_data_store.merge_region_map.identifier == 0:
|
|
915
885
|
return
|
|
@@ -926,18 +896,12 @@ class _NumbersModel(Cacheable):
|
|
|
926
896
|
)
|
|
927
897
|
row_end = row_start + num_rows - 1
|
|
928
898
|
col_end = col_start + num_columns - 1
|
|
929
|
-
|
|
930
|
-
for col in range(col_start, col_end + 1):
|
|
931
|
-
self._merge_cells[table_id].add_reference(
|
|
932
|
-
row,
|
|
933
|
-
col,
|
|
934
|
-
(row_start, col_start, row_end, col_end),
|
|
935
|
-
)
|
|
936
|
-
self._merge_cells[table_id].add_anchor(row_start, col_start, (num_rows, num_columns))
|
|
899
|
+
self.add_merge_range(table_id, row_start, row_end, col_start, col_end)
|
|
937
900
|
|
|
938
901
|
def merge_cells(self, table_id):
|
|
939
|
-
self.
|
|
940
|
-
self.
|
|
902
|
+
self.calculate_merges_using_formula_stores(table_id)
|
|
903
|
+
self.calculate_merges_using_dependency_archives(table_id)
|
|
904
|
+
self.calculate_merges_using_region_map(table_id)
|
|
941
905
|
return self._merge_cells[table_id]
|
|
942
906
|
|
|
943
907
|
def table_id_to_sheet_id(self, table_id: int) -> int:
|
|
@@ -946,25 +910,14 @@ class _NumbersModel(Cacheable):
|
|
|
946
910
|
return sheet_id
|
|
947
911
|
return None
|
|
948
912
|
|
|
949
|
-
def table_name_to_uuid(self, sheet_name: str, table_name: str) -> str:
|
|
950
|
-
table_ids = [tid for tid in self.table_ids() if table_name == self.table_name(tid)]
|
|
951
|
-
if len(table_ids) == 1:
|
|
952
|
-
return self.table_base_id(table_ids[0])
|
|
953
|
-
|
|
954
|
-
sheet_name_to_id = {self.sheet_name(x): x for x in self.sheet_ids()}
|
|
955
|
-
sheet_id = sheet_name_to_id[sheet_name]
|
|
956
|
-
table_name_to_id = {self.table_name(x): x for x in self.table_ids(sheet_id)}
|
|
957
|
-
table_id = table_name_to_id[table_name]
|
|
958
|
-
return self.table_base_id(table_id)
|
|
959
|
-
|
|
960
913
|
@cache()
|
|
961
914
|
def table_uuids_to_id(self, table_uuid) -> int | None:
|
|
962
|
-
for sheet_id in self.sheet_ids(): # pragma: no branch
|
|
915
|
+
for sheet_id in self.sheet_ids(): # pragma: no branch # noqa: RET503
|
|
963
916
|
for table_id in self.table_ids(sheet_id):
|
|
964
917
|
if table_uuid == self.table_base_id(table_id):
|
|
965
918
|
return table_id
|
|
966
919
|
|
|
967
|
-
def node_to_ref(self, table_id: int, row: int, col: int, node
|
|
920
|
+
def node_to_ref(self, table_id: int, row: int, col: int, node):
|
|
968
921
|
def resolve_range(is_absolute, absolute_list, relative_list, offset, max_val):
|
|
969
922
|
if is_absolute:
|
|
970
923
|
return absolute_list[0].range_begin
|
|
@@ -1030,7 +983,6 @@ class _NumbersModel(Cacheable):
|
|
|
1030
983
|
col_end_is_abs=node.AST_sticky_bits.end_column_is_absolute,
|
|
1031
984
|
from_table_id=table_id,
|
|
1032
985
|
to_table_id=to_table_id,
|
|
1033
|
-
_do_init=not merge_mode,
|
|
1034
986
|
)
|
|
1035
987
|
|
|
1036
988
|
row = node.AST_row.row if node.AST_row.absolute else row + node.AST_row.row
|
|
@@ -1510,7 +1462,7 @@ class _NumbersModel(Cacheable):
|
|
|
1510
1462
|
},
|
|
1511
1463
|
TSTArchives.TableModelArchive,
|
|
1512
1464
|
)
|
|
1513
|
-
#
|
|
1465
|
+
# Suppress Numbers assertions for tables sharing the same data
|
|
1514
1466
|
table_model.category_owner.identifier = 0
|
|
1515
1467
|
|
|
1516
1468
|
column_headers_id, column_headers = self.objects.create_object_from_dict(
|
|
@@ -1719,7 +1671,7 @@ class _NumbersModel(Cacheable):
|
|
|
1719
1671
|
"bottom_right_column": 0x7FFF,
|
|
1720
1672
|
"bottom_right_row": 0x7FFFFFFF,
|
|
1721
1673
|
}
|
|
1722
|
-
|
|
1674
|
+
spanning_dependencies = {
|
|
1723
1675
|
"total_range_for_table": null_range_ref,
|
|
1724
1676
|
"body_range_for_table": null_range_ref,
|
|
1725
1677
|
}
|
|
@@ -1732,8 +1684,8 @@ class _NumbersModel(Cacheable):
|
|
|
1732
1684
|
"cell_dependencies": {},
|
|
1733
1685
|
"range_dependencies": {},
|
|
1734
1686
|
"volatile_dependencies": volatile_dependencies,
|
|
1735
|
-
"spanning_column_dependencies":
|
|
1736
|
-
"spanning_row_dependencies":
|
|
1687
|
+
"spanning_column_dependencies": spanning_dependencies,
|
|
1688
|
+
"spanning_row_dependencies": spanning_dependencies,
|
|
1737
1689
|
"whole_owner_dependencies": {"dependent_cells": {}},
|
|
1738
1690
|
"cell_errors": {},
|
|
1739
1691
|
"base_owner_uid": base_owner_uuid.dict2,
|
|
@@ -1809,7 +1761,7 @@ class _NumbersModel(Cacheable):
|
|
|
1809
1761
|
for k, v in presets_map.items()
|
|
1810
1762
|
}
|
|
1811
1763
|
for style in styles.values():
|
|
1812
|
-
# Override __setattr__
|
|
1764
|
+
# Override __setattr__ behavior for builtin styles
|
|
1813
1765
|
style.__dict__["_update_text_style"] = False
|
|
1814
1766
|
style.__dict__["_update_cell_style"] = False
|
|
1815
1767
|
return styles
|
|
@@ -2142,7 +2094,7 @@ class _NumbersModel(Cacheable):
|
|
|
2142
2094
|
# a string with a new bullet character
|
|
2143
2095
|
bds = self.objects[table_id].base_data_store
|
|
2144
2096
|
rich_text_table = self.objects[bds.rich_text_table.identifier]
|
|
2145
|
-
for entry in rich_text_table.entries: # pragma: no branch
|
|
2097
|
+
for entry in rich_text_table.entries: # pragma: no branch # noqa: RET503
|
|
2146
2098
|
if string_key == entry.key:
|
|
2147
2099
|
payload = self.objects[entry.rich_text_payload.identifier]
|
|
2148
2100
|
payload_storage = self.objects[payload.storage.identifier]
|
|
@@ -2596,6 +2548,59 @@ class _NumbersModel(Cacheable):
|
|
|
2596
2548
|
# datas never appears to be an empty list (default themes include images)
|
|
2597
2549
|
return max(image_ids) + 1
|
|
2598
2550
|
|
|
2551
|
+
@classmethod
|
|
2552
|
+
def cell_value_to_key(
|
|
2553
|
+
cls,
|
|
2554
|
+
cell_value: TSCEArchives.CellValueArchive,
|
|
2555
|
+
) -> str | int | bool | datetime:
|
|
2556
|
+
"""Convert a CellValueArchive to a key."""
|
|
2557
|
+
cell_value_type = cell_value.cell_value_type
|
|
2558
|
+
if cell_value_type == CellValueType.STRING_TYPE:
|
|
2559
|
+
return cell_value.string_value.value
|
|
2560
|
+
if cell_value_type == CellValueType.NUMBER_TYPE:
|
|
2561
|
+
return cell_value.number_value.value
|
|
2562
|
+
if cell_value_type == CellValueType.BOOLEAN_TYPE:
|
|
2563
|
+
return cell_value.boolean_value.value
|
|
2564
|
+
# Must be DATE_TYPE
|
|
2565
|
+
return cell_value.date_value.value
|
|
2566
|
+
|
|
2567
|
+
@cache(num_args=0)
|
|
2568
|
+
def group_uuid_values(self):
|
|
2569
|
+
return {
|
|
2570
|
+
NumbersUUID(self.objects[_id].group_uid): _NumbersModel.cell_value_to_key(
|
|
2571
|
+
self.objects[_id].group_cell_value,
|
|
2572
|
+
)
|
|
2573
|
+
for _id in self.find_refs("GroupNodeArchive")
|
|
2574
|
+
}
|
|
2575
|
+
|
|
2576
|
+
@cache()
|
|
2577
|
+
def table_category_row_map(self, table_id: int) -> dict[int, int] | None:
|
|
2578
|
+
category_owner_id = self.objects[table_id].category_owner.identifier
|
|
2579
|
+
if not category_owner_id:
|
|
2580
|
+
return None
|
|
2581
|
+
category_archive_id = self.objects[category_owner_id].group_by[0].identifier
|
|
2582
|
+
category_archive = self.objects[category_archive_id]
|
|
2583
|
+
if not category_archive.is_enabled:
|
|
2584
|
+
return None
|
|
2585
|
+
|
|
2586
|
+
table_info = self.objects[self.table_info_id(table_id)]
|
|
2587
|
+
category_order = self.objects[table_info.category_order.identifier]
|
|
2588
|
+
row_uid_map = self.objects[category_order.uid_map.identifier]
|
|
2589
|
+
|
|
2590
|
+
group_uuids = self.group_uuid_values()
|
|
2591
|
+
row_uuid_to_offset = {
|
|
2592
|
+
NumbersUUID(uuid): row for row, uuid in enumerate(category_archive.row_uid_lookup.uuids)
|
|
2593
|
+
}
|
|
2594
|
+
row_uid_for_index = [
|
|
2595
|
+
NumbersUUID(row_uid_map.sorted_row_uids[i]) for i in row_uid_map.row_uid_for_index
|
|
2596
|
+
]
|
|
2597
|
+
return {
|
|
2598
|
+
row: row_uuid_to_offset[uuid]
|
|
2599
|
+
for row, uuid in enumerate(
|
|
2600
|
+
uuid for uuid in row_uid_for_index if uuid not in group_uuids
|
|
2601
|
+
)
|
|
2602
|
+
}
|
|
2603
|
+
|
|
2599
2604
|
def table_category_data(self, table_id: int) -> dict | None:
|
|
2600
2605
|
category_owner_id = self.objects[table_id].category_owner.identifier
|
|
2601
2606
|
category_archive_id = self.objects[category_owner_id].group_by[0].identifier
|
|
@@ -2606,8 +2611,9 @@ class _NumbersModel(Cacheable):
|
|
|
2606
2611
|
table_info = self.objects[self.table_info_id(table_id)]
|
|
2607
2612
|
category_order = self.objects[table_info.category_order.identifier]
|
|
2608
2613
|
row_uid_map = self.objects[category_order.uid_map.identifier]
|
|
2614
|
+
|
|
2609
2615
|
sorted_row_uuids = [
|
|
2610
|
-
NumbersUUID(row_uid_map.sorted_row_uids[i]).hex for i in row_uid_map.
|
|
2616
|
+
NumbersUUID(row_uid_map.sorted_row_uids[i]).hex for i in row_uid_map.row_index_for_uid
|
|
2611
2617
|
]
|
|
2612
2618
|
|
|
2613
2619
|
data = self._table_data[table_id]
|
|
@@ -2623,22 +2629,8 @@ class _NumbersModel(Cacheable):
|
|
|
2623
2629
|
offsets += list(range(entry.range_begin, entry.range_begin + 1))
|
|
2624
2630
|
return offsets
|
|
2625
2631
|
|
|
2626
|
-
def cell_value_to_key(
|
|
2627
|
-
cell_value: TSCEArchives.CellValueArchive,
|
|
2628
|
-
) -> str | int | bool | datetime:
|
|
2629
|
-
"""Convert a CellValueArchive to a key."""
|
|
2630
|
-
cell_value_type = cell_value.cell_value_type
|
|
2631
|
-
if cell_value_type == CellValueType.STRING_TYPE:
|
|
2632
|
-
return cell_value.string_value.value
|
|
2633
|
-
if cell_value_type == CellValueType.NUMBER_TYPE:
|
|
2634
|
-
return cell_value.number_value.value
|
|
2635
|
-
if cell_value_type == CellValueType.BOOLEAN_TYPE:
|
|
2636
|
-
return cell_value.boolean_value.value
|
|
2637
|
-
# Must be DATE_TYPE
|
|
2638
|
-
return cell_value.date_value.value
|
|
2639
|
-
|
|
2640
2632
|
group_node_to_key = {
|
|
2641
|
-
NumbersUUID(self.objects[_id].group_uid).hex: cell_value_to_key(
|
|
2633
|
+
NumbersUUID(self.objects[_id].group_uid).hex: _NumbersModel.cell_value_to_key(
|
|
2642
2634
|
self.objects[_id].group_cell_value,
|
|
2643
2635
|
)
|
|
2644
2636
|
for _id in self.find_refs("GroupNodeArchive")
|
|
@@ -2660,7 +2652,7 @@ class _NumbersModel(Cacheable):
|
|
|
2660
2652
|
for child in children:
|
|
2661
2653
|
group_uuid = NumbersUUID(child.group_uid).hex
|
|
2662
2654
|
if len(child.child) == 0:
|
|
2663
|
-
key = cell_value_to_key(child.group_cell_value)
|
|
2655
|
+
key = _NumbersModel.cell_value_to_key(child.group_cell_value)
|
|
2664
2656
|
|
|
2665
2657
|
row_offsets = index_set_to_offsets(child.row_lookup_uids)
|
|
2666
2658
|
categories[group_uuid] = {
|
numbers_parser/xrefs.py
CHANGED
|
@@ -67,8 +67,6 @@ class CellRange:
|
|
|
67
67
|
_table_names: list[str] = field(init=False, default=None, repr=False)
|
|
68
68
|
|
|
69
69
|
def __post_init__(self):
|
|
70
|
-
if not self._do_init:
|
|
71
|
-
return
|
|
72
70
|
if self._table_names is None:
|
|
73
71
|
self._initialize_table_data()
|
|
74
72
|
self.model.name_ref_cache.refresh()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: numbers-parser
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.18.0
|
|
4
4
|
Summary: Read and write Apple Numbers spreadsheets
|
|
5
5
|
Author-email: Jon Connell <python@figsandfudge.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -26,20 +26,15 @@ Dynamic: license-file
|
|
|
26
26
|
|
|
27
27
|
[](https://github.com/masaccio/numbers-parser/actions/workflows/run-all-tests.yml)[](https://github.com/masaccio/numbers-parser/actions/workflows/codeql.yml)[](https://codecov.io/gh/masaccio/numbers-parser)[](https://badge.fury.io/py/numbers-parser)
|
|
28
28
|
|
|
29
|
-
`numbers-parser` is a Python module for
|
|
30
|
-
generated by Numbers version 10.3, and up with the latest tested version being 14.1
|
|
31
|
-
(current as of June 2024).
|
|
29
|
+
`numbers-parser` is a Python module for reading and editing [Apple Numbers](https://www.apple.com/numbers/)`.numbers` files. It supports Numbers files generated by Numbers versions 3.x and later. It is tested against Numbers documents from 10.0 through to 14.4 (the last version of Numbers) and Numbers Creator Studio up to version 15.1, which the most current as of February 2026.
|
|
32
30
|
|
|
33
|
-
It supports and is tested against Python versions from 3.10 onwards. It is not compatible
|
|
34
|
-
with earlier versions of Python.
|
|
31
|
+
It supports and is tested against Python versions from 3.10 onwards. It is not compatible with earlier versions of Python.
|
|
35
32
|
|
|
36
33
|
## Installation
|
|
37
34
|
|
|
38
35
|
A pre-requisite for this package is [python-snappy](https://pypi.org/project/python-snappy/) which will be installed by Python automatically, but python-snappy also requires binary libraries for snappy compression.
|
|
39
36
|
|
|
40
|
-
The most straightforward way to install the binary dependencies is to use
|
|
41
|
-
[Homebrew](https://brew.sh) and source Python from Homebrew rather than from macOS as described
|
|
42
|
-
in the [python-snappy github](https://github.com/andrix/python-snappy). Using [pipx](https://pipx.pypa.io/stable/installation/) for package management is also strongly recommended:
|
|
37
|
+
The most straightforward way to install the binary dependencies is to use [Homebrew](https://brew.sh) and source Python from Homebrew rather than from macOS as described in the [python-snappy github](https://github.com/andrix/python-snappy). Using [pipx](https://pipx.pypa.io/stable/installation/) for package management is also strongly recommended:
|
|
43
38
|
|
|
44
39
|
```bash
|
|
45
40
|
brew install snappy python3 pipx
|
|
@@ -52,9 +47,7 @@ For Linux (your package manager may be different):
|
|
|
52
47
|
sudo apt-get -y install libsnappy-dev
|
|
53
48
|
```
|
|
54
49
|
|
|
55
|
-
On Windows, you will need to either arrange for snappy to be found for VSC++ or you can install python
|
|
56
|
-
[pre-compiled binary libraries](https://github.com/cgohlke/win_arm64-wheels/) which are only available
|
|
57
|
-
for Windows on Arm. There appear to be no x86 pre-compiled packages for Windows.
|
|
50
|
+
On Windows, you will need to either arrange for snappy to be found for VSC++ or you can install python [pre-compiled binary libraries](https://github.com/cgohlke/win_arm64-wheels/) which are only available for Windows on Arm. There appear to be no x86 pre-compiled packages for Windows.
|
|
58
51
|
|
|
59
52
|
```text
|
|
60
53
|
pip install python_snappy-0.6.1-cp312-cp312-win_arm64.whl
|
|
@@ -118,12 +111,7 @@ python datatype. Available cell types are:
|
|
|
118
111
|
| ErrorCell | `None` | |
|
|
119
112
|
| MergedCell | `None` | See [Merged cells](https://masaccio.github.io/numbers-parser/api/cells.html#numbers_parser.MergedCell) |
|
|
120
113
|
|
|
121
|
-
Cell references can be either zero-offset row/column integers or an
|
|
122
|
-
Excel/Numbers A1 notation. Where cell values are not `None` the
|
|
123
|
-
property `formatted_value` returns the cell value as a `str` as
|
|
124
|
-
displayed in Numbers. Cells that have no values in a table are
|
|
125
|
-
represented as `EmptyCell` and cells containing evaluation errors of
|
|
126
|
-
any kind `ErrorCell`.
|
|
114
|
+
Cell references can be either zero-offset row/column integers or an Excel/Numbers A1 notation. Where cell values are not `None` the property `formatted_value` returns the cell value as a `str` as displayed in Numbers. Cells that have no values in a table are represented as `EmptyCell` and cells containing evaluation errors of any kind `ErrorCell`.
|
|
127
115
|
|
|
128
116
|
```python
|
|
129
117
|
>>> table.cell(1,0)
|
|
@@ -140,10 +128,7 @@ any kind `ErrorCell`.
|
|
|
140
128
|
|
|
141
129
|
### Pandas Support
|
|
142
130
|
|
|
143
|
-
Since the return value of `rows()` is a list of lists, you can pass
|
|
144
|
-
this directly to pandas. Assuming you have a Numbers table with a single
|
|
145
|
-
header which contains the names of the pandas series you want to create
|
|
146
|
-
you can construct a pandas dataframe using:
|
|
131
|
+
Since the return value of `rows()` is a list of lists, you can pass this directly to pandas. Assuming you have a Numbers table with a single header which contains the names of the pandas series you want to create you can construct a pandas dataframe using:
|
|
147
132
|
|
|
148
133
|
```python
|
|
149
134
|
import pandas as pd
|
|
@@ -157,14 +142,9 @@ df = pd.DataFrame(data[1:], columns=data[0])
|
|
|
157
142
|
|
|
158
143
|
### Writing Numbers Documents
|
|
159
144
|
|
|
160
|
-
Whilst support for writing numbers files has been stable since version
|
|
161
|
-
3.4.0, you are highly recommended not to overwrite working Numbers files
|
|
162
|
-
and instead save data to a new file.
|
|
145
|
+
Whilst support for writing numbers files has been stable since version 3.4.0, you are highly recommended not to overwrite working Numbers files and instead save data to a new file.
|
|
163
146
|
|
|
164
|
-
Cell values are written using
|
|
165
|
-
[Table.write()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.write) and
|
|
166
|
-
`numbers-parser` will automatically create empty rows and columns
|
|
167
|
-
for any cell references that are out of range of the current table.
|
|
147
|
+
Cell values are written using [Table.write()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.write) and `numbers-parser` will automatically create empty rows and columns for any cell references that are out of range of the current table.
|
|
168
148
|
|
|
169
149
|
```python
|
|
170
150
|
doc = Document("write.numbers")
|
|
@@ -176,9 +156,7 @@ table.write("B7", datetime(2020, 12, 25))
|
|
|
176
156
|
doc.save("new-sheet.numbers")
|
|
177
157
|
```
|
|
178
158
|
|
|
179
|
-
Additional tables and worksheets can be added to a `Document` before saving using
|
|
180
|
-
[Document.add_sheet()](https://masaccio.github.io/numbers-parser/api/document.html#numbers_parser.Document.add_sheet) and
|
|
181
|
-
[Sheet.add_table()](https://masaccio.github.io/numbers-parser/api/sheet.html#numbers_parser.Sheet.add_table) respectively:
|
|
159
|
+
Additional tables and worksheets can be added to a `Document` before saving using [Document.add_sheet()](https://masaccio.github.io/numbers-parser/api/document.html#numbers_parser.Document.add_sheet) and [Sheet.add_table()](https://masaccio.github.io/numbers-parser/api/sheet.html#numbers_parser.Sheet.add_table) respectively:
|
|
182
160
|
|
|
183
161
|
```python
|
|
184
162
|
doc = Document()
|
|
@@ -204,19 +182,11 @@ styles. The following styles are supported:
|
|
|
204
182
|
- cell background images
|
|
205
183
|
- cell indents (first line, left, right, and text inset)
|
|
206
184
|
|
|
207
|
-
Numbers conflates style attributes that can be stored in paragraph
|
|
208
|
-
styles (the style menu in the text panel) with the settings that are
|
|
209
|
-
available on the Style tab of the Text panel. Some attributes in Numbers
|
|
210
|
-
are not applied to new cells when a style is applied.
|
|
185
|
+
Numbers conflates style attributes that can be stored in paragraph styles (the style menu in the text panel) with the settings that are available on the Style tab of the Text panel. Some attributes in Numbers are not applied to new cells when a style is applied.
|
|
211
186
|
|
|
212
|
-
To keep the API simple, `numbers-parser` packs all styling into a single
|
|
213
|
-
[Style](https://masaccio.github.io/numbers-parser/api/style.html) object. When a document is saved, the attributes
|
|
214
|
-
not stored in a paragraph style are applied to each cell that includes it.
|
|
187
|
+
To keep the API simple, `numbers-parser` packs all styling into a single [Style](https://masaccio.github.io/numbers-parser/api/style.html) object. When a document is saved, the attributes not stored in a paragraph style are applied to each cell that includes it.
|
|
215
188
|
|
|
216
|
-
Styles are read from cells using the
|
|
217
|
-
[Cell.style](https://masaccio.github.io/numbers-parser/api/cells.html#numbers_parser.Cell.style) property and you can
|
|
218
|
-
add new styles with
|
|
219
|
-
[Document.add_style](https://masaccio.github.io/numbers-parser/api/document.html#numbers_parser.Document.add_style).
|
|
189
|
+
Styles are read from cells using the [Cell.style](https://masaccio.github.io/numbers-parser/api/cells.html#numbers_parser.Cell.style) property and you can add new styles with [Document.add_style](https://masaccio.github.io/numbers-parser/api/document.html#numbers_parser.Document.add_style).
|
|
220
190
|
|
|
221
191
|
```python
|
|
222
192
|
red_text = doc.add_style(
|
|
@@ -234,18 +204,11 @@ table.set_cell_style("C2", red_text)
|
|
|
234
204
|
|
|
235
205
|
### Cell Data Formatting
|
|
236
206
|
|
|
237
|
-
Numbers has two different cell formatting types: data formats and custom
|
|
238
|
-
formats.
|
|
207
|
+
Numbers has two different cell formatting types: data formats and custom formats.
|
|
239
208
|
|
|
240
|
-
Data formats are presented in Numbers in the Cell tab of the Format pane
|
|
241
|
-
and are applied to individual cells. Like Numbers, `numbers-parsers`
|
|
242
|
-
caches formatting information that is identical across multiple cells.
|
|
243
|
-
You do not need to take any action for this to happen; this is handled
|
|
244
|
-
internally by the package. Changing a data format for cell has no impact
|
|
245
|
-
on any other cells.
|
|
209
|
+
Data formats are presented in Numbers in the Cell tab of the Format pane and are applied to individual cells. Like Numbers, `numbers-parsers` caches formatting information that is identical across multiple cells. You do not need to take any action for this to happen; this is handled internally by the package. Changing a data format for cell has no impact on any other cells.
|
|
246
210
|
|
|
247
|
-
Cell formats are changed using
|
|
248
|
-
[Table.set_cell_formatting()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.set_cell_formatting):
|
|
211
|
+
Cell formats are changed using [Table.set_cell_formatting()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.set_cell_formatting):
|
|
249
212
|
|
|
250
213
|
```python
|
|
251
214
|
table.set_cell_formatting(
|
|
@@ -262,13 +225,7 @@ table.set_cell_formatting(
|
|
|
262
225
|
)
|
|
263
226
|
```
|
|
264
227
|
|
|
265
|
-
Custom formats are shared across a Document and can be applied to
|
|
266
|
-
multiple cells in multiple tables. Editing a custom format changes the
|
|
267
|
-
appearance of data in all cells that share that format. You must first
|
|
268
|
-
add a custom format to the document using
|
|
269
|
-
[Document.add_custom_format()](https://masaccio.github.io/numbers-parser/api/document.html#numbers_parser.Document.add_custom_format)
|
|
270
|
-
before assigning it to cells using
|
|
271
|
-
[Table.set_cell_formatting()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.set_cell_formatting):
|
|
228
|
+
Custom formats are shared across a Document and can be applied to multiple cells in multiple tables. Editing a custom format changes the appearance of data in all cells that share that format. You must first add a custom format to the document using [Document.add_custom_format()](https://masaccio.github.io/numbers-parser/api/document.html#numbers_parser.Document.add_custom_format) before assigning it to cells using [Table.set_cell_formatting()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.set_cell_formatting):
|
|
272
229
|
|
|
273
230
|
```python
|
|
274
231
|
long_date = doc.add_custom_format(
|
|
@@ -279,33 +236,17 @@ long_date = doc.add_custom_format(
|
|
|
279
236
|
table.set_cell_formatting("C1", "custom", format=long_date)
|
|
280
237
|
```
|
|
281
238
|
|
|
282
|
-
A limited number of currencies are formatted using symbolic notation
|
|
283
|
-
rather than an ISO code. These are defined in
|
|
284
|
-
`numbers_parser.currencies` and match the ones chosen by Numbers. For
|
|
285
|
-
example, US dollars are referred to as `US$` whereas Euros and British
|
|
286
|
-
Pounds are referred to using their symbols of `€` and `£`
|
|
287
|
-
respectively.
|
|
239
|
+
A limited number of currencies are formatted using symbolic notation rather than an ISO code. These are defined in `numbers_parser.currencies` and match the ones chosen by Numbers. For example, US dollars are referred to as `US$` whereas Euros and British Pounds are referred to using their symbols of `€` and `£` respectively.
|
|
288
240
|
|
|
289
241
|
### Borders
|
|
290
242
|
|
|
291
|
-
`numbers-parser` supports reading and writing cell borders, though the
|
|
292
|
-
interface for each differs. Individual cells can have each of their four
|
|
293
|
-
borders tested, but when drawing new borders, these are set for the
|
|
294
|
-
table to allow for drawing borders across multiple cells. Setting the
|
|
295
|
-
border of merged cells is not possible unless the edge of the cells is
|
|
296
|
-
at the end of the merged region.
|
|
243
|
+
`numbers-parser` supports reading and writing cell borders, though the interface for each differs. Individual cells can have each of their four borders tested, but when drawing new borders, these are set for the table to allow for drawing borders across multiple cells. Setting the border of merged cells is not possible unless the edge of the cells is at the end of the merged region.
|
|
297
244
|
|
|
298
|
-
Borders are represented using the [Border](https://masaccio.github.io/numbers-parser/api/border.html) class
|
|
299
|
-
that can be initialized with line width, color and line style. The
|
|
300
|
-
current state of a cell border is read using the
|
|
301
|
-
[Cell.border](https://masaccio.github.io/numbers-parser/api/cells.html#numbers_parser.Cell.border) property
|
|
302
|
-
and [Table.set_cell_border()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.set_cell_border)
|
|
303
|
-
sets the border for a cell edge or a range of cells.
|
|
245
|
+
Borders are represented using the [Border](https://masaccio.github.io/numbers-parser/api/border.html) class that can be initialized with line width, color and line style. The current state of a cell border is read using the [Cell.border](https://masaccio.github.io/numbers-parser/api/cells.html#numbers_parser.Cell.border) property and [Table.set_cell_border()](https://masaccio.github.io/numbers-parser/api/table.html#numbers_parser.Table.set_cell_border) sets the border for a cell edge or a range of cells.
|
|
304
246
|
|
|
305
247
|
## API
|
|
306
248
|
|
|
307
|
-
For more examples and details of all available classes and methods,
|
|
308
|
-
see the [full API docs](https://masaccio.github.io/numbers-parser/).
|
|
249
|
+
For more examples and details of all available classes and methods, see the [full API docs](https://masaccio.github.io/numbers-parser/).
|
|
309
250
|
|
|
310
251
|
## Command-line scripts
|
|
311
252
|
|
|
@@ -318,9 +259,7 @@ a number of command-line scripts are installed:
|
|
|
318
259
|
|
|
319
260
|
### cat-numbers
|
|
320
261
|
|
|
321
|
-
This script dumps Numbers spreadsheets into Excel-compatible CSV
|
|
322
|
-
format, iterating through all the spreadsheets passed on the
|
|
323
|
-
command-line.
|
|
262
|
+
This script dumps Numbers spreadsheets into Excel-compatible CSV format, iterating through all the spreadsheets passed on the command-line.
|
|
324
263
|
|
|
325
264
|
```text
|
|
326
265
|
usage: cat-numbers [-h] [-T | -S | -b] [-V] [--formulas] [--formatting]
|
|
@@ -349,25 +288,17 @@ options:
|
|
|
349
288
|
--debug Enable debug logging
|
|
350
289
|
```
|
|
351
290
|
|
|
352
|
-
Note: `--formatting` will return different capitalization for 12-hour
|
|
353
|
-
times due to differences between Numbers’ representation of these dates
|
|
354
|
-
and `datetime.strftime`. Numbers in English locales displays 12-hour
|
|
355
|
-
times with ‘am’ and ‘pm’, but `datetime.strftime` on macOS at least
|
|
356
|
-
cannot return lower-case versions of AM/PM.
|
|
291
|
+
Note: `--formatting` will return different capitalization for 12-hour times due to differences between Numbers’ representation of these dates and `datetime.strftime`. Numbers in English locales displays 12-hour times with ‘am’ and ‘pm’, but `datetime.strftime` on macOS at least cannot return lower-case versions of AM/PM.
|
|
357
292
|
|
|
358
293
|
### csv2numbers
|
|
359
294
|
|
|
360
|
-
This script converts Excel-compatible CSV files into Numbers documents. Output files
|
|
361
|
-
can optionally be provided, but is none are provided, the output is created by replacing
|
|
362
|
-
the input’s files suffix with .numbers. For example:
|
|
295
|
+
This script converts Excel-compatible CSV files into Numbers documents. Output files can optionally be provided, but is none are provided, the output is created by replacing the input’s files suffix with .numbers. For example:
|
|
363
296
|
|
|
364
297
|
```text
|
|
365
298
|
csv2numbers file1.csv file2.csv -o file1.numbers file2.numbers
|
|
366
299
|
```
|
|
367
300
|
|
|
368
|
-
Columns of data can have a number of transformations applied to them. The primary use-
|
|
369
|
-
case intended for `csv2numbers` is converting banking exports to well-formatted
|
|
370
|
-
spreadsheets.
|
|
301
|
+
Columns of data can have a number of transformations applied to them. The primary use- case intended for `csv2numbers` is converting banking exports to well-formatted spreadsheets.
|
|
371
302
|
|
|
372
303
|
```text
|
|
373
304
|
usage: csv2numbers [-h] [-V] [--whitespace] [--reverse] [--no-header]
|
|
@@ -455,39 +386,22 @@ csv2numbers --transform='Category=LOOKUP:Transaction;mapping.numbers' file1.csv
|
|
|
455
386
|
|
|
456
387
|
Current known limitations of `numbers-parser` which may be implemented in the future are:
|
|
457
388
|
|
|
458
|
-
- Table styles that allow new tables to adopt a style across the whole
|
|
459
|
-
table are not suppported
|
|
389
|
+
- Table styles that allow new tables to adopt a style across the whole table are not supported
|
|
460
390
|
- Creating cells of type `BulletedTextCell` is not supported
|
|
461
|
-
- New tables are inserted with a fixed offset below the last table in a
|
|
462
|
-
|
|
463
|
-
- Captions can be created and edited as of numbers-parser version 4.12, but cannot
|
|
464
|
-
be styled. New captions adopt the first caption style available in the current
|
|
465
|
-
document
|
|
391
|
+
- New tables are inserted with a fixed offset below the last table in a worksheet which does not take into account title or caption size
|
|
392
|
+
- Captions can be created and edited as of numbers-parser version 4.12, but cannot be styled. New captions adopt the first caption style available in the current document
|
|
466
393
|
- Formulas cannot be written to a document
|
|
467
|
-
- Pivot tables are unsupported and saving a document with a pivot table issues
|
|
468
|
-
|
|
394
|
+
- Pivot tables are unsupported and saving a document with a pivot table issues a UnsupportedWarning (see [issue 73](https://github.com/masaccio/numbers-parser/issues/73) for details).
|
|
395
|
+
- Tables which have been saved grouped cannot be safely edited as references to written cells refer to the ungrouped cell rows rather than the row number in the groups.
|
|
469
396
|
|
|
470
397
|
The following limitations are expected to always remain:
|
|
471
398
|
|
|
472
|
-
- New sheets insert tables with formats copied from the first table in
|
|
473
|
-
|
|
474
|
-
-
|
|
475
|
-
|
|
476
|
-
versions older than 3.11 do not support image filenames with UTF-8 characters
|
|
477
|
-
[Cell.add_style.bg_image()](https://masaccio.github.io/numbers-parser/api/sheet.html#numbers_parser.Style) returns
|
|
478
|
-
`None` for such files and issues a `RuntimeWarning`
|
|
479
|
-
(see [issue 69](https://github.com/masaccio/numbers-parser/issues/69) for details).
|
|
480
|
-
- Password-encrypted documents cannot be opened. You must first re-save without
|
|
481
|
-
a password to read (see [issue 88](https://github.com/masaccio/numbers-parser/issues/88) for details).
|
|
482
|
-
A UnsupportedError exception is raised when such documents are opened.
|
|
483
|
-
- Due to changes in the format of Numbers documents, decoding of category groups
|
|
484
|
-
(introduced in `numbers-parser` version 4.16) is supported only for documents
|
|
485
|
-
created by Numbers 12.0 and later. No warnings are issued for earlier
|
|
399
|
+
- New sheets insert tables with formats copied from the first table in the previous sheet rather than default table formats
|
|
400
|
+
- Due to a limitation in Python’s [ZipFile](https://docs.python.org/3/library/zipfile.html), Python versions older than 3.11 do not support image filenames with UTF-8 characters [Cell.add_style.bg_image()](https://masaccio.github.io/numbers-parser/api/sheet.html#numbers_parser.Style) returns `None` for such files and issues a `RuntimeWarning` (see [issue 69](https://github.com/masaccio/numbers-parser/issues/69) for details).
|
|
401
|
+
- Password-encrypted documents cannot be opened. You must first re-save without a password to read (see [issue 88](https://github.com/masaccio/numbers-parser/issues/88) for details). A UnsupportedError exception is raised when such documents are opened.
|
|
402
|
+
- Due to changes in the format of Numbers documents, decoding of category groups (introduced in `numbers-parser` version 4.16) is supported only for documents created by Numbers 12.0 and later. No warnings are issued for earlier
|
|
486
403
|
Numbers documents.
|
|
487
|
-
- Only standard macOS fonts are not supported. If a document includes a non-standard
|
|
488
|
-
font, numbers-parser will issue a UnsupportedWarning and default styles to
|
|
489
|
-
Helvetica Neue. Reading font names from the system would add additional system-specific
|
|
490
|
-
dependencies to the package and so this is not planned to changed.
|
|
404
|
+
- Only standard macOS fonts are not supported. If a document includes a non-standard font, numbers-parser will issue a UnsupportedWarning and default styles to Helvetica Neue. Reading font names from the system would add additional system-specific dependencies to the package and so this is not planned to changed.
|
|
491
405
|
|
|
492
406
|
## License
|
|
493
407
|
|
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
numbers_parser/__init__.py,sha256=fKvZmUi_UsY3DMwt54s7G20DCwUTuG28B7kGsQRw3wU,1481
|
|
2
|
-
numbers_parser/_cat_numbers.py,sha256=
|
|
2
|
+
numbers_parser/_cat_numbers.py,sha256=6JR69SW3yNx1zOPfxpd0QA8mb9XGnIQckzl5O1L-pK4,5311
|
|
3
3
|
numbers_parser/_csv2numbers.py,sha256=R_13gVe_RfLWLOv-DzVJ60xkqhdOA-RKna-Ce5ud4V8,14624
|
|
4
4
|
numbers_parser/_unpack_numbers.py,sha256=x4Od4qEruPpzkoOq_i_zOFiNbNonlSRHBT3WGwZGYo8,6685
|
|
5
5
|
numbers_parser/bullets.py,sha256=CKMjSYRzLM123wQNDG8B5vfodRLjW5UOc2HDPlvfNr4,2637
|
|
6
|
-
numbers_parser/cell.py,sha256=
|
|
6
|
+
numbers_parser/cell.py,sha256=l0r7n0QX-MrPNo5DoHNrtn4iJYidpHHGfW3ioyhE2tw,71955
|
|
7
7
|
numbers_parser/constants.py,sha256=FPkKRrkPtiV_KX9SWjR6DLlkDw644lmMw8GOBEG6Gsc,10658
|
|
8
8
|
numbers_parser/containers.py,sha256=SBD99t0ABHraGA8729jPXy5VcRHT21U_WM3ijOIiwd4,4886
|
|
9
9
|
numbers_parser/currencies.py,sha256=8k4a3WKmDoHeurkDICymHX13N7ManHSTaka_JNXCZYA,3767
|
|
10
|
-
numbers_parser/document.py,sha256=
|
|
11
|
-
numbers_parser/exceptions.py,sha256=
|
|
12
|
-
numbers_parser/experimental.py,sha256=
|
|
13
|
-
numbers_parser/formula.py,sha256=
|
|
10
|
+
numbers_parser/document.py,sha256=i0Bta5JtXYHRCcoARH6Yos2ZASugqv8RJIqLEpamWOc,61610
|
|
11
|
+
numbers_parser/exceptions.py,sha256=aTpY9FMXa7RgsazJ8WEPxgA9qOzYd3lC5BK1TfcgCTs,612
|
|
12
|
+
numbers_parser/experimental.py,sha256=Pox7smoekWsa4-TO0IN05-omE7HMf9PViWr_swf_B40,807
|
|
13
|
+
numbers_parser/formula.py,sha256=0X5BsRzotN5ktPoafJITNo3mHTLjtasZ0PiBkiiHMFQ,9260
|
|
14
14
|
numbers_parser/iwafile.py,sha256=nVwCcXvx8TgX-DkYqSbcJQzKyXR1Z8_y547XeY7Y-fs,11948
|
|
15
15
|
numbers_parser/iwork.py,sha256=Qx1Izf9cfQKnLTDiJyeCOsmL9PSsfV-XOf0Kkb2oPMo,9396
|
|
16
|
-
numbers_parser/model.py,sha256=
|
|
16
|
+
numbers_parser/model.py,sha256=WPVWnd8_QgBsMyi_sqdy1ML8WfxKAvBjyh_1lXavTfs,115812
|
|
17
17
|
numbers_parser/numbers_cache.py,sha256=uGngtJmP_AEDGZphyJpOMJ1dq8VGEeDyPdyrVy1E7lU,1100
|
|
18
18
|
numbers_parser/numbers_uuid.py,sha256=vVTgXgmtGx6PdbHfwyi82oRsZccmP7IW_o2q-6PGUNg,2880
|
|
19
19
|
numbers_parser/roman.py,sha256=CErv1uRp8eE9Bsuh_QsrBAzKFsfHSEs8CHpfFW0Gd70,725
|
|
20
|
-
numbers_parser/
|
|
21
|
-
numbers_parser/xrefs.py,sha256=Oq-EL5bSSmXvJGSX-MPtXDcX-EROX859knm9y_Zz568,30043
|
|
20
|
+
numbers_parser/xrefs.py,sha256=JZXH1FssaLVZL9tX8rvrdM6PfoM9Cte5F-hUxZVw-ZI,29994
|
|
22
21
|
numbers_parser/data/empty.numbers,sha256=zQjVqcNGN-xNZh51_eAxD8Zxmxh88Sd7kpf4JygUA_E,90601
|
|
23
22
|
numbers_parser/generated/TNArchives_pb2.py,sha256=ACEMFxxhu7QpKJT9bhx6k2WZMs_qBin-csiAiUi0YNc,17387
|
|
24
23
|
numbers_parser/generated/TNArchives_sos_pb2.py,sha256=kBurQK0i7wFZ6nIh3we0n7xHbOTLJ6IYx2yZzF336G4,1534
|
|
@@ -57,9 +56,9 @@ numbers_parser/generated/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
57
56
|
numbers_parser/generated/fontmap.py,sha256=N7RelrdanYW9mK7mcl42THasVcw0uQ9XeZ3wn4rOfKo,23586
|
|
58
57
|
numbers_parser/generated/functionmap.py,sha256=7GzgkZfONzhI35pnByINiIGCbhMxhNz6EWiJEBX4s1g,6672
|
|
59
58
|
numbers_parser/generated/mapping.py,sha256=W6fEWqar3TFvx2wyWgK4NutIz9EYKtjChhSfho2FGQQ,32266
|
|
60
|
-
numbers_parser-4.
|
|
61
|
-
numbers_parser-4.
|
|
62
|
-
numbers_parser-4.
|
|
63
|
-
numbers_parser-4.
|
|
64
|
-
numbers_parser-4.
|
|
65
|
-
numbers_parser-4.
|
|
59
|
+
numbers_parser-4.18.0.dist-info/licenses/LICENSE.rst,sha256=8vTa1-5KSdHrTpU9rlheO5005EWReEPMpjV7BjSaMc4,1050
|
|
60
|
+
numbers_parser-4.18.0.dist-info/METADATA,sha256=5wcfPZkOtf-S2t-YsNxDhQ12lqc9h45nDZUiy7TVzKc,23358
|
|
61
|
+
numbers_parser-4.18.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
62
|
+
numbers_parser-4.18.0.dist-info/entry_points.txt,sha256=_5biENfY3S-XG8BZL2AuE7Gvrw0zBwGjF6Un52u7FAk,165
|
|
63
|
+
numbers_parser-4.18.0.dist-info/top_level.txt,sha256=EOag5_Q4xjG7gstnrNVeAF_CLUAJBR_HDvciqMQ9RQo,15
|
|
64
|
+
numbers_parser-4.18.0.dist-info/RECORD,,
|