Source code for pyx12.dataele

######################################################################
# Copyright (c) 2001-2019
#   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.
#
######################################################################

"""
Interface to normalized Data Elements
"""

from __future__ import annotations

import logging
import os.path
from importlib.resources import files as _res_files
from typing import IO, Any, TypedDict

import defusedxml.ElementTree as et

# Intrapackage imports
from pyx12.errors import EngineError


[docs] class DataElementsError(Exception): """Class for data elements module errors."""
class _DataEle(TypedDict): data_type: str | None min_len: int max_len: int name: str | None
[docs] class DataElements: """ Interface to normalized Data Elements """
[docs] dataele: dict[str | None, _DataEle]
def __init__(self, base_path: str | None = None) -> None: """ Initialize the list of data elements :param base_path: Override directory containing dataele.xml. If None, uses package resource folder :type base_path: string Note: ``self.dataele`` maps to the data element ``{ele_num: {data_type, min_len, max_len, name}}`` """ logger = logging.getLogger("pyx12") self.dataele = {} dataele_file = "dataele.xml" # ElementTree.parse accepts either text- or binary-mode streams; the # file source differs between override path and bundled package resource. fd: IO[Any] if base_path is not None: logger.debug( f"Looking for data element definition file '{dataele_file}' in map_path '{base_path}'" ) fd = open(os.path.join(base_path, dataele_file), encoding="utf-8") else: logger.debug( f"Looking for data element definition file '{dataele_file}' in package resources" ) fd = _res_files("pyx12").joinpath("map", dataele_file).open("rb") with fd: parser = et.XMLParser(encoding="utf-8") for eElem in et.parse(fd, parser=parser).iter("data_ele"): ele_num = eElem.get("ele_num") self.dataele[ele_num] = { "data_type": eElem.get("data_type"), "min_len": int(eElem.get("min_len")), "max_len": int(eElem.get("max_len")), "name": eElem.get("name"), }
[docs] def get_by_elem_num(self, ele_num: str | None) -> _DataEle: """ Get the element characteristics for the indexed element code :param ele_num: the data element code :type ele_num: string :return: {data_type, min_len, max_len, name} :rtype: dict """ if not ele_num: raise EngineError(f"Bad data element {ele_num!r}") if ele_num not in self.dataele: raise EngineError(f'Data Element "{ele_num}" is not defined') return self.dataele[ele_num]
[docs] def debug_print(self) -> None: """ Debug print data elements """ for ele_num in self.dataele: print(self.dataele[ele_num])