Skip to content
Open
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
40 changes: 28 additions & 12 deletions src/dicom_parser/utils/siemens/csa/ascii/ascconv.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@
#: Regular expression to replace terminal integer identifiers.
TERMINAL_DIGIT_RE = re.compile(TERMINAL_DIGIT_PATTERN, re.M)

# Resolve legacy node types once – they fall back to ast.Constant on 3.14+
NumNode = getattr(ast, "Num", tuple())
StrNode = getattr(ast, "Str", tuple())
IndexNode = getattr(ast, "Index", tuple())

class AscconvParseError(Exception):
"""
Expand All @@ -68,6 +72,16 @@ class NoValue:
Signals no value present.
"""

def _slice_index(subscript):
slc = subscript.slice
if IndexNode and isinstance(slc, IndexNode):
slc = slc.value
idx = _literal_value(slc)
if not isinstance(idx, int):
raise AscconvParseError(
messages.UNEXPECTED_LHS.format(target=subscript)
)
return idx

def assign_to_atoms(assign_ast, default_class=int):
"""
Expand Down Expand Up @@ -104,10 +118,7 @@ def assign_to_atoms(assign_ast, default_class=int):
target = target.value
prev_target_type = dict
elif isinstance(target, ast.Subscript):
if isinstance(target.slice, ast.Constant): # PY39
index = target.slice.n
else: # PY38
index = target.slice.value.n
index = _slice_index(target)
atoms.append((target, prev_target_type, index))
target = target.value
prev_target_type = list
Expand Down Expand Up @@ -198,19 +209,24 @@ def obj_from_atoms(atoms, namespace):
raise AscconvParseError(message)
return prev_root, name

def _literal_value(node):
if isinstance(node, ast.Constant):
return node.value
if NumNode and isinstance(node, NumNode):
return node.n
if StrNode and isinstance(node, StrNode):
return node.s
return None

def _get_value(assign):
value = assign.value
if isinstance(value, ast.Num):
return value.n
if isinstance(value, ast.Str):
return value.s
if isinstance(value, ast.UnaryOp) and isinstance(value.op, ast.USub):
return -value.operand.n
value = _literal_value(assign.value)
if value is not None:
return value
if isinstance(assign.value, ast.UnaryOp) and isinstance(assign.value.op, ast.USub):
return -_literal_value(assign.value.operand)
message = messages.UNEXPECTED_RHS.format(value=value)
raise AscconvParseError(message)


def parse_ascconv_text(content, delimiter='"'):
"""
Parse ASCCONV text format from `content` string.
Expand Down