numbers-parser 4.14.1__py3-none-any.whl → 4.14.2__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.
@@ -1,4 +1,4 @@
1
- __doc__ = """Parse and extract data from Apple Numbers spreadsheets"""
1
+ """Parse and extract data from Apple Numbers spreadsheets."""
2
2
 
3
3
  import importlib.metadata
4
4
  import os
@@ -20,11 +20,11 @@ _DEFAULT_NUMBERS_INSTALL_PATH = "/Applications/Numbers.app"
20
20
  _VERSION_PLIST_PATH = "Contents/version.plist"
21
21
 
22
22
 
23
- def _get_version():
23
+ def _get_version() -> str:
24
24
  return __version__
25
25
 
26
26
 
27
- def _check_installed_numbers_version():
27
+ def _check_installed_numbers_version() -> str:
28
28
  try:
29
29
  fp = open(os.path.join(_DEFAULT_NUMBERS_INSTALL_PATH, _VERSION_PLIST_PATH), "rb")
30
30
  except OSError:
@@ -71,12 +71,12 @@ def command_line_parser():
71
71
  return parser
72
72
 
73
73
 
74
- def print_sheet_names(filename):
74
+ def print_sheet_names(filename) -> None:
75
75
  for sheet in Document(filename).sheets:
76
76
  print(f"{filename}: {sheet.name}")
77
77
 
78
78
 
79
- def print_table_names(filename):
79
+ def print_table_names(filename) -> None:
80
80
  for sheet in Document(filename).sheets:
81
81
  for table in sheet.tables:
82
82
  print(f"{filename}: {sheet.name}: {table.name}")
@@ -85,19 +85,18 @@ def print_table_names(filename):
85
85
  def cell_as_string(args, cell):
86
86
  if isinstance(cell, ErrorCell) and not (args.formulas):
87
87
  return "#REF!"
88
- elif args.formulas and cell.formula is not None:
88
+ if args.formulas and cell.formula is not None:
89
89
  return cell.formula
90
- elif args.formatting and cell.formatted_value is not None:
90
+ if args.formatting and cell.formatted_value is not None:
91
91
  return cell.formatted_value
92
- elif isinstance(cell, NumberCell):
92
+ if isinstance(cell, NumberCell):
93
93
  return sigfig(cell.value, sigfigs=MAX_SIGNIFICANT_DIGITS, warn=False)
94
- elif cell.value is None:
94
+ if cell.value is None:
95
95
  return ""
96
- else:
97
- return str(cell.value)
96
+ return str(cell.value)
98
97
 
99
98
 
100
- def print_table(args, filename):
99
+ def print_table(args, filename) -> None:
101
100
  writer = csv.writer(sys.stdout, dialect="excel")
102
101
  for sheet in Document(filename).sheets:
103
102
  if args.sheet is not None and sheet.name not in args.sheet:
@@ -112,7 +111,7 @@ def print_table(args, filename):
112
111
  writer.writerow(cells)
113
112
 
114
113
 
115
- def main():
114
+ def main() -> None:
116
115
  parser = command_line_parser()
117
116
  args = parser.parse_args()
118
117
 
@@ -138,7 +137,7 @@ def main():
138
137
  print_table_names(filename)
139
138
  else:
140
139
  print_table(args, filename)
141
- except FileFormatError as e:
140
+ except FileFormatError as e: # noqa: PERF203
142
141
  print(f"{filename}:", str(e), file=sys.stderr)
143
142
  sys.exit(1)
144
143
  except FileError as e:
@@ -3,13 +3,14 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import argparse
6
+ import contextlib
6
7
  import csv
7
8
  import re
8
9
  from dataclasses import dataclass
9
10
  from datetime import datetime, timezone
10
11
  from pathlib import Path
11
12
  from sys import exit, stderr
12
- from typing import NamedTuple, Tuple # noqa: F401
13
+ from typing import NamedTuple
13
14
 
14
15
  from dateutil.parser import parse
15
16
 
@@ -68,18 +69,18 @@ class Converter:
68
69
  """Parse a date string and return a datetime."""
69
70
  return parse(x, dayfirst=self.day_first).replace(tzinfo=timezone.utc)
70
71
 
71
- def _transform_data(self):
72
+ def _transform_data(self) -> None:
72
73
  """Apply type transformations to the data based in current configuration."""
73
74
  # Convert data rows to dicts. csv.DictReader is not enough as we support CSV
74
75
  # files with no header.
75
76
  if self.no_header:
76
- self.header = [x for x in range(len(self.data[0]))]
77
- self.data = [{k: v for k, v in dict(zip(self.header, row)).items()} for row in self.data]
77
+ self.header = list(range(len(self.data[0])))
78
+ self.data = [dict(dict(zip(self.header, row)).items()) for row in self.data]
78
79
 
79
80
  if self.reverse:
80
81
  self.data = list(reversed(self.data))
81
82
  if self.date_columns is not None:
82
- is_date_column = {x: True if x in self.date_columns else False for x in self.header}
83
+ is_date_column = {x: x in self.date_columns for x in self.header}
83
84
  for row in self.data:
84
85
  for k, v in row.items():
85
86
  if self.whitespace:
@@ -88,17 +89,15 @@ class Converter:
88
89
  row[k] = self._parse_date(v)
89
90
  else:
90
91
  # Attempt to coerce value into float
91
- try:
92
+ with contextlib.suppress(ValueError):
92
93
  row[k] = float(v.replace(",", ""))
93
- except ValueError:
94
- pass
95
94
 
96
95
  def rename_columns(self: Converter, mapper: dict) -> None:
97
96
  """Rename columns using column map."""
98
97
  if mapper is None:
99
98
  return
100
99
  self.no_header = False
101
- self.header = [mapper[x] if x in mapper else x for x in self.header]
100
+ self.header = [mapper.get(x, x) for x in self.header]
102
101
 
103
102
  def delete_columns(self: Converter, columns: list) -> None:
104
103
  """Delete columns from the data."""
@@ -131,10 +130,7 @@ class Converter:
131
130
  doc = Document(num_rows=2, num_cols=2)
132
131
  table = doc.sheets[0].tables[0]
133
132
 
134
- if self.no_header:
135
- data = []
136
- else:
137
- data = [self.header]
133
+ data = [] if self.no_header else [self.header]
138
134
  data += [row.values() for row in self.data]
139
135
 
140
136
  for row_num, row in enumerate(data):
@@ -142,7 +138,10 @@ class Converter:
142
138
  table.write(row_num, col_num, value)
143
139
  if isinstance(value, datetime):
144
140
  table.set_cell_formatting(
145
- row_num, col_num, "datetime", date_time_format="d MMM yyyy"
141
+ row_num,
142
+ col_num,
143
+ "datetime",
144
+ date_time_format="d MMM yyyy",
146
145
  )
147
146
 
148
147
  doc.save(self.output_filename)
@@ -64,13 +64,13 @@ class NumbersUnpacker(IWorkHandler):
64
64
  with open(target_path, "wb") as out:
65
65
  out.write(blob)
66
66
 
67
- def ensure_directory_exists(self, path: str):
67
+ def ensure_directory_exists(self, path: str) -> None:
68
68
  """Ensure that a path's directory exists."""
69
69
  parts = os.path.split(path)
70
70
  with contextlib.suppress(OSError):
71
71
  os.makedirs(os.path.join(*([self.output_dir, *list(parts[:-1])])))
72
72
 
73
- def prettify_uuids(self, obj: object):
73
+ def prettify_uuids(self, obj: object) -> None:
74
74
  if isinstance(obj, dict):
75
75
  for k, v in obj.items():
76
76
  if isinstance(v, dict):
@@ -90,7 +90,7 @@ class NumbersUnpacker(IWorkHandler):
90
90
  elif isinstance(v, list):
91
91
  self.prettify_uuids(v)
92
92
 
93
- def prettify_cell_storage(self, obj: object):
93
+ def prettify_cell_storage(self, obj: object) -> None:
94
94
  if isinstance(obj, dict):
95
95
  for k, v in obj.items():
96
96
  if isinstance(v, (dict, list)):
@@ -117,7 +117,7 @@ class NumbersUnpacker(IWorkHandler):
117
117
  return version in SUPPORTED_NUMBERS_VERSIONS
118
118
 
119
119
 
120
- def main():
120
+ def main() -> None:
121
121
  parser = ArgumentParser()
122
122
  parser.add_argument("document", help="Apple Numbers file(s)", nargs="*")
123
123
  parser.add_argument("-V", "--version", action="store_true")