Source code for pyx12.syntax

######################################################################
# Copyright (c) 2001-2011
#   John Holland <john@zoner.org>
# All rights reserved.
#
# This software is licensed as described in the file LICENSE.txt, which
# you should have received as part of this distribution.
#
######################################################################
"""
X12 syntax validation functions
"""

from __future__ import annotations

from typing import Any

import pyx12.segment


[docs] def is_syntax_valid( seg_data: pyx12.segment.Segment, syn: list[Any], ) -> tuple[bool, str | None]: """ Verifies the segment against the syntax :param seg_data: data segment instance :type seg_data: L{segment<segment.Segment>} :param syn: list containing the syntax type, and the indices of elements :type syn: list[string] :rtype: tuple(boolean, error string) """ # handle intra-segment dependancies if len(syn) < 3: err_str = f"Syntax string must have at least two comparators {syntax_str(syn)}" return (False, err_str) syn_code = syn[0] syn_idx = [int(s) for s in syn[1:]] if syn_code == "P": count = 0 for s in syn_idx: _val = seg_data.get_value(f"{s:02d}") if len(seg_data) >= s and _val != "": count += 1 if count != 0 and count != len(syn_idx): err_str = f"Syntax Error ({syntax_str(syn)}): If any of {syntax_ele_id_str(seg_data.get_seg_id(), syn_idx)} is present, then all are required" return (False, err_str) else: return (True, None) elif syn_code == "R": count = 0 for s in syn_idx: _val = seg_data.get_value(f"{s:02d}") if len(seg_data) >= s and _val != "": count += 1 if count == 0: err_str = f"Syntax Error ({syntax_str(syn)}): At least one element is required" return (False, err_str) else: return (True, None) elif syn_code == "E": count = 0 for s in syn_idx: _val = seg_data.get_value(f"{s:02d}") if len(seg_data) >= s and _val != "": count += 1 if count > 1: err_str = "Syntax Error (%s): At most one of %s may be present" % ( syntax_str(syn), syntax_ele_id_str(seg_data.get_seg_id(), syn_idx), ) return (False, err_str) else: return (True, None) elif syn_code == "C": # If the first is present, then all others are required if len(seg_data) >= syn_idx[0] and seg_data.get_value("%02i" % (syn_idx[0])) != "": count = 0 for s in syn_idx[1:]: _val = seg_data.get_value(f"{s:02d}") if len(seg_data) >= s and _val != "": count += 1 if count != len(syn_idx) - 1: if len(syn_idx[1:]) > 1: verb = "are" else: verb = "is" err_str = "Syntax Error (%s): If %s%02i is present, then %s %s required" % ( syntax_str(syn), seg_data.get_seg_id(), syn_idx[0], syntax_ele_id_str(seg_data.get_seg_id(), syn_idx[1:]), verb, ) return (False, err_str) else: return (True, None) else: return (True, None) elif syn_code == "L": if len(seg_data) > syn_idx[0] - 1 and seg_data.get_value("%02i" % (syn_idx[0])) != "": count = 0 for s in syn_idx[1:]: _val = seg_data.get_value(f"{s:02d}") if len(seg_data) >= s and _val != "": count += 1 if count == 0: err_str = "Syntax Error (%s): If %s%02i is present, then at least one of " % ( syntax_str(syn), seg_data.get_seg_id(), syn_idx[0], ) err_str += syntax_ele_id_str(seg_data.get_seg_id(), syn_idx[1:]) err_str += " is required" return (False, err_str) else: return (True, None) else: return (True, None) # raise EngineError return (False, "Syntax Type %s Not Found" % (syntax_str(syn)))
[docs] def syntax_str(syntax: list[Any]) -> str: """ :rtype: string """ output: str = str(syntax[0]) for i in syntax[1:]: output += f"{int(i):02d}" return output
[docs] def syntax_ele_id_str(seg_id: str | None, ele_pos_list: list[int]) -> str: """ :rtype: string """ output = "" output += f"{seg_id}{ele_pos_list[0]:02d}" for i in range(len(ele_pos_list) - 1): if i == len(ele_pos_list) - 2: output += f" or {seg_id}{ele_pos_list[i + 1]:02d}" else: output += f", {seg_id}{ele_pos_list[i + 1]:02d}" return output