Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion application/database/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -2151,7 +2151,9 @@ def dbNodeFromStandard(standard: cre_defs.Node) -> Node:
section=standard.section,
subsection=standard.subsection,
version=standard.version,
section_id=standard.sectionID,
# str() guard: sectionID must reach the DB column as a string.
# Protects against any float that slipped through upstream coercion.
section_id=str(standard.sectionID) if standard.sectionID is not None else "",
)


Expand Down
8 changes: 8 additions & 0 deletions application/defs/cre_defs.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,11 @@ class Standard(Node):
subsection: Optional[str] = ""

def __post_init__(self):
# Coerce sectionID to str before building self.id.
# YAML or gspread can deliver numeric types (e.g. float 7.1 instead of
# str "7.10" when the numericise_ignore range was off-by-one).
# None is normalised to "" so the field type is always str.
self.sectionID = str(self.sectionID) if self.sectionID is not None else ""
self.id = f"{self.name}"
if self.sectionID:
self.id += f":{self.sectionID}"
Expand Down Expand Up @@ -496,6 +501,9 @@ class Tool(Standard):
doctype: Credoctypes = Credoctypes.Tool

def __post_init__(self):
# Tool builds self.id before calling super().__post_init__(), so the
# same sectionID str-coercion guard from Standard must be repeated here.
self.sectionID = str(self.sectionID) if self.sectionID is not None else ""
self.id = f"{self.name}"
if self.sectionID:
self.id += f":{self.sectionID}"
Expand Down
11 changes: 8 additions & 3 deletions application/utils/spreadsheet.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,23 @@ def read_spreadsheet(
)
records = wsh.get_all_records(
head=1,
# +1 fixes off-by-one: range(1, col_count) excluded the last
# column, leaving it numericized by gspread and converting
# section IDs like "7.10" silently to float 7.1.
numericise_ignore=list(
range(1, wsh.col_count)
range(1, wsh.col_count + 1)
), # Added numericise_ignore parameter
) # workaround because of https://github.com/burnash/gspread/issues/1007 # this will break if the column names are in any other line
toyaml = yaml.safe_load(yaml.safe_dump(records))
result[wsh.title] = toyaml
elif not parse_numbered_only:
records = wsh.get_all_records(
head=1,
# +1 fixes off-by-one: range(1, col_count) excluded the last column.
# DO NOT make this 'all', gspread has a bug
numericise_ignore=list(
range(1, wsh.col_count)
), # Added numericise_ignore parameter -- DO NOT make this 'all', gspread has a bug
range(1, wsh.col_count + 1)
), # Added numericise_ignore parameter
) # workaround because of https://github.com/burnash/gspread/issues/1007 # this will break if the column names are in any other line
toyaml = yaml.safe_load(yaml.safe_dump(records))
result[wsh.title] = toyaml
Expand Down
7 changes: 6 additions & 1 deletion application/utils/spreadsheet_parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,12 @@ def parse_export_format(lfile: List[Dict[str, Any]]) -> Dict[str, List[defs.Docu
if not is_empty(mapping_line.get(f"{s}{defs.ExportFormat.separator}name")):
working_standard = defs.Standard(
name=s,
sectionID=mapping_line.get(f"{s}{defs.ExportFormat.separator}id"),
# Explicit str() cast: YAML/gspread can deliver a numeric
# type (e.g. float 7.1 instead of str "7.10"). Casting here
# ensures Standard always receives a string.
sectionID=str(
mapping_line.get(f"{s}{defs.ExportFormat.separator}id") or ""
),
section=mapping_line.get(f"{s}{defs.ExportFormat.separator}name"),
hyperlink=mapping_line.get(
f"{s}{defs.ExportFormat.separator}hyperlink", ""
Expand Down