-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathhelpers.py
More file actions
131 lines (107 loc) · 4.82 KB
/
Copy pathhelpers.py
File metadata and controls
131 lines (107 loc) · 4.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import logging
from collections import defaultdict
from typing import Any, Dict, List
from openpyxl.worksheet.worksheet import Worksheet
def get_unique_table_names(worksheet: Worksheet) -> List[str]:
"""
Extracts unique table names from the Field Overview worksheet.
Args:
worksheet: The worksheet containing table names.
Returns:
List[str]: A list of unique table names.
"""
# Get all the table names in the order they appear in the Field Overview page
table_names = []
# Iterate over cells in the first column, but because we're in ReadOnly mode we
# can't do that in the simplest manner.
worksheet.reset_dimensions() # type: ignore
worksheet.calculate_dimension(force=True) # type: ignore
for row in worksheet.iter_rows(min_row=2, max_row=worksheet.max_row):
cell_value = row[0].value
if cell_value and isinstance(cell_value, str) and cell_value not in table_names:
# Truncate table names because sheet names are truncated to 31 characters in Excel
# NOTE: This can cause the table names to be duplicated
table_names.append(cell_value[:31])
return table_names
def remove_BOM(intermediate: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
"""
Given a list of dictionaries, remove any occurrences of the BOM in the keys.
Args:
intermediate (List[Dict[str, Any]]): List of dictionaries to remove from.
Returns:
The list of dictionaries with BOM removed from the keys.
"""
return [
{key.replace("\ufeff", ""): value for key, value in d.items()}
for d in intermediate
]
def process_four_item_dict(
four_item_data: List[Dict[str, Any]],
) -> Dict[str, Dict[str, Dict[str, str]]]:
"""
Converts a list of dictionaries (each with keys 'csv_file_name', 'field_name' and
'code' and 'value') to a nested dictionary with indices 'csv_file_name',
'field_name', 'code', and internal value 'value'.
Note: This function was copied from the shared project. More details can be found here:
app/shared/services/utils.py -> function: process_four_item_dict
"""
csv_file_names = set(row["csv_file_name"] for row in four_item_data)
# Initialise the dictionary with the keys, and each value set to a blank dict()
new_data_dictionary: Dict[str, Dict[str, Dict[str, str]]] = {}
for csv_file_name in csv_file_names:
new_data_dictionary[csv_file_name] = {}
for row in four_item_data:
if row["field_name"] not in new_data_dictionary[row["csv_file_name"]]:
new_data_dictionary[row["csv_file_name"]][row["field_name"]] = {}
new_data_dictionary[row["csv_file_name"]][row["field_name"]][row["code"]] = row[
"value"
]
return new_data_dictionary
def transform_scan_report_sheet_table(sheet: Worksheet) -> defaultdict[Any, List]:
"""
Transforms a worksheet data into a JSON like format.
Note: This function was copied from the workers project. More details can be found here:
app/workers/UploadQueue/__init__.py -> function: _transform_scan_report_sheet_table
Args:
sheet (Worksheet): Sheet of data to transform
Returns:
defaultdict[Any, List]: The transformed data.
"""
logging.debug("Start process_scan_report_sheet_table")
sheet.reset_dimensions() # type: ignore
sheet.calculate_dimension(force=True) # type: ignore
# Get header entries (skipping every second column which is just 'Frequency')
# So sheet_headers = ['a', 'b']
first_row = sheet[1]
sheet_headers = [cell.value for cell in first_row[::2]]
d = defaultdict(list)
for row in sheet.iter_rows(
min_col=1,
max_col=len(sheet_headers) * 2,
min_row=2,
max_row=sheet.max_row,
values_only=True,
):
# Set boolean to track whether we hit a blank row for early exit below.
this_row_empty = True
# Iterate across the pairs of cells in the row. If the pair is non-empty,
# then add it to the relevant dict entry.
for header, cell, freq in zip(sheet_headers, row[::2], row[1::2]):
if (cell != "" and cell is not None) or (freq != "" and freq is not None):
d[header].append((str(cell), freq))
this_row_empty = False
if this_row_empty:
break
# Clean BOM characters from keys before returning
cleaned_dict = defaultdict(list)
for key, value in d.items():
clean_key = key.replace("\ufeff", "") if isinstance(key, str) else key
cleaned_dict[clean_key] = value
logging.debug("Finish process_scan_report_sheet_table")
return cleaned_dict
def default_zero(value) -> float:
"""
Helper function that returns the input, replacing anything Falsey
(such as Nones or empty strings) with 0.0.
"""
return round(value or 0.0, 2)