pyx12 4.0.0rc1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. pyx12/__init__.py +10 -0
  2. pyx12/codes.py +120 -0
  3. pyx12/dataele.py +103 -0
  4. pyx12/decorators.py +79 -0
  5. pyx12/errh_xml.py +324 -0
  6. pyx12/error_997.py +457 -0
  7. pyx12/error_999.py +391 -0
  8. pyx12/error_debug.py +148 -0
  9. pyx12/error_handler.py +1358 -0
  10. pyx12/error_html.py +255 -0
  11. pyx12/error_item.py +102 -0
  12. pyx12/error_visitor.py +80 -0
  13. pyx12/errors.py +73 -0
  14. pyx12/map/270.4010.X092.A1.xml +2995 -0
  15. pyx12/map/271.4010.X092.A1.xml +4874 -0
  16. pyx12/map/276.4010.X093.A1.xml +2166 -0
  17. pyx12/map/277.4010.X093.A1.xml +2669 -0
  18. pyx12/map/277.5010.X212.xml +4179 -0
  19. pyx12/map/277.5010.X214.xml +2605 -0
  20. pyx12/map/277U.4010.X070.xml +2668 -0
  21. pyx12/map/278.4010.X094.27.A1.xml +7321 -0
  22. pyx12/map/278.4010.X094.A1.xml +9385 -0
  23. pyx12/map/820.4010.X061.A1.xml +2313 -0
  24. pyx12/map/820.5010.X218.v2.xml +1029 -0
  25. pyx12/map/820.5010.X218.xml +3142 -0
  26. pyx12/map/830.4010.PS.xml +881 -0
  27. pyx12/map/834.4010.X095.A1.xml +4032 -0
  28. pyx12/map/834.5010.X220.A1.v2.xml +2145 -0
  29. pyx12/map/834.5010.X220.A1.xml +5127 -0
  30. pyx12/map/835.4010.X091.A1.xml +3587 -0
  31. pyx12/map/835.5010.X221.A1.v2.xml +1410 -0
  32. pyx12/map/835.5010.X221.A1.xml +4233 -0
  33. pyx12/map/837.4010.X096.A1.xml +39589 -0
  34. pyx12/map/837.4010.X097.A1.xml +11478 -0
  35. pyx12/map/837.4010.X098.A1.xml +23842 -0
  36. pyx12/map/837.5010.X222.A1.xml +25900 -0
  37. pyx12/map/837Q3.I.5010.X223.A1.v2.xml +9987 -0
  38. pyx12/map/837Q3.I.5010.X223.A1.xml +30108 -0
  39. pyx12/map/841.4010.XXXC.xml +865 -0
  40. pyx12/map/997.4010.xml +961 -0
  41. pyx12/map/999.5010.xml +1283 -0
  42. pyx12/map/999.5010X231.A1.xml +1283 -0
  43. pyx12/map/README +16 -0
  44. pyx12/map/README.md +20 -0
  45. pyx12/map/codes.xml +2844 -0
  46. pyx12/map/codes.xsd +40 -0
  47. pyx12/map/comp_test.xml +69 -0
  48. pyx12/map/dataele.xml +363 -0
  49. pyx12/map/dataele.xsd +60 -0
  50. pyx12/map/dump.py +22 -0
  51. pyx12/map/map.v2.xsd +135 -0
  52. pyx12/map/map.xsd +150 -0
  53. pyx12/map/maps.xml +85 -0
  54. pyx12/map/maps.xsd +109 -0
  55. pyx12/map/ord.py +39 -0
  56. pyx12/map/x12.control.00401.xml +386 -0
  57. pyx12/map/x12.control.00501.xml +369 -0
  58. pyx12/map/x12simple.dtd +16 -0
  59. pyx12/map_if/__init__.py +39 -0
  60. pyx12/map_if/_base.py +189 -0
  61. pyx12/map_if/_composite.py +160 -0
  62. pyx12/map_if/_element.py +391 -0
  63. pyx12/map_if/_loader.py +58 -0
  64. pyx12/map_if/_loop.py +318 -0
  65. pyx12/map_if/_root.py +222 -0
  66. pyx12/map_if/_segment.py +504 -0
  67. pyx12/map_index.py +146 -0
  68. pyx12/map_override.py +45 -0
  69. pyx12/map_walker.py +695 -0
  70. pyx12/nodeCounter.py +88 -0
  71. pyx12/params.py +160 -0
  72. pyx12/path.py +218 -0
  73. pyx12/rawx12file.py +98 -0
  74. pyx12/scripts/__init__.py +22 -0
  75. pyx12/scripts/x12html.py +166 -0
  76. pyx12/scripts/x12info.py +107 -0
  77. pyx12/scripts/x12norm.py +106 -0
  78. pyx12/scripts/x12valid.py +179 -0
  79. pyx12/scripts/x12xml.py +153 -0
  80. pyx12/scripts/xmlx12.py +105 -0
  81. pyx12/segment.py +589 -0
  82. pyx12/syntax.py +147 -0
  83. pyx12/validation.py +275 -0
  84. pyx12/version.py +1 -0
  85. pyx12/x12context.py +1191 -0
  86. pyx12/x12file.py +687 -0
  87. pyx12/x12metadata.py +278 -0
  88. pyx12/x12n_document.py +278 -0
  89. pyx12/x12xml.py +234 -0
  90. pyx12/x12xml_simple.py +128 -0
  91. pyx12/xmlwriter.py +155 -0
  92. pyx12/xmlx12_simple.py +60 -0
  93. pyx12-4.0.0rc1.dist-info/METADATA +173 -0
  94. pyx12-4.0.0rc1.dist-info/RECORD +98 -0
  95. pyx12-4.0.0rc1.dist-info/WHEEL +5 -0
  96. pyx12-4.0.0rc1.dist-info/entry_points.txt +7 -0
  97. pyx12-4.0.0rc1.dist-info/licenses/LICENSE.txt +28 -0
  98. pyx12-4.0.0rc1.dist-info/top_level.txt +1 -0
pyx12/__init__.py ADDED
@@ -0,0 +1,10 @@
1
+ """
2
+ Validate and transform HIPAA X12 documents
3
+ """
4
+
5
+ __author__ = "John Holland <john.holland@swmbh.org>"
6
+ __status__ = "production"
7
+ from .version import __version__ as __version__
8
+
9
+ __date__ = "2021-05-28"
10
+ __revision__ = ""
pyx12/codes.py ADDED
@@ -0,0 +1,120 @@
1
+ ######################################################################
2
+ # Copyright
3
+ # John Holland <john@zoner.org>
4
+ # All rights reserved.
5
+ #
6
+ # This software is licensed as described in the file LICENSE.txt, which
7
+ # you should have received as part of this distribution.
8
+ #
9
+ ######################################################################
10
+
11
+ """
12
+ External Codes interface
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import logging
18
+ import os.path
19
+ from importlib.resources import files as _res_files
20
+ from typing import IO, Any, TypedDict
21
+
22
+ import defusedxml.ElementTree as et
23
+
24
+ from pyx12.errors import EngineError
25
+
26
+
27
+ class CodesError(Exception):
28
+ """Class for code modules errors."""
29
+
30
+
31
+ class _CodeSet(TypedDict):
32
+ name: str | None
33
+ dataele: str | None
34
+ codes: frozenset[str | None]
35
+
36
+
37
+ class ExternalCodes:
38
+ """
39
+ Validates an ID against an external list of codes
40
+ """
41
+
42
+ codes: dict[str | None, _CodeSet]
43
+ exclude_list: list[str]
44
+
45
+ def __init__(self, base_path: str | None = None, exclude: str | None = None) -> None:
46
+ """
47
+ Initialize the external list of codes
48
+
49
+ :param base_path: Override directory containing codes.xml.
50
+ If None, uses package resource folder.
51
+ :param exclude: comma-separated string of external code names to ignore.
52
+
53
+ ``self.codes`` maps codeset_id to ``{'name', 'dataele', 'codes'}``.
54
+ """
55
+ logger = logging.getLogger("pyx12")
56
+ self.codes = {}
57
+ codes_file = "codes.xml"
58
+ # ElementTree.parse accepts either text- or binary-mode streams; the
59
+ # file source differs between override path and bundled package resource.
60
+ code_fd: IO[Any]
61
+ if base_path is not None:
62
+ logger.debug(f"Looking for codes file '{codes_file}' in map_path '{base_path}'")
63
+ code_fd = open(os.path.join(base_path, codes_file), encoding="utf-8")
64
+ else:
65
+ logger.debug(f"Looking for codes file '{codes_file}' in package resources")
66
+ code_fd = _res_files("pyx12").joinpath("map", codes_file).open("rb")
67
+
68
+ self.exclude_list = exclude.split(",") if exclude is not None else []
69
+ with code_fd:
70
+ parser = et.XMLParser(encoding="utf-8")
71
+ for cElem in et.parse(code_fd, parser=parser).iter("codeset"):
72
+ codeset_id = cElem.findtext("id")
73
+ self.codes[codeset_id] = {
74
+ "name": cElem.findtext("name"),
75
+ "dataele": cElem.findtext("data_ele"),
76
+ "codes": frozenset(c.text for c in cElem.iterfind("version/code")),
77
+ }
78
+
79
+ def isValid(self, key: str | None, code: str | None, check_dte: str | None = None) -> bool:
80
+ """
81
+ Return True if code is in the codeset identified by key.
82
+ """
83
+ if not key:
84
+ raise EngineError(f"bad key {key!r}")
85
+ if key in self.exclude_list:
86
+ return True
87
+ if key not in self.codes:
88
+ raise EngineError(f'External Code "{key}" is not defined')
89
+ return code in self.codes[key]["codes"]
90
+
91
+ def debug_print(self, count: int = 10) -> None:
92
+ """Debug print first <count> codes for each codeset (alphabetical)."""
93
+ for key in self.codes:
94
+ print(sorted(self.codes[key]["codes"], key=lambda c: c or "")[:count])
95
+
96
+
97
+ def list_external_codesets(base_path: str | None = None) -> list[tuple[str, str]]:
98
+ """Return ``(id, name)`` for every codeset in ``codes.xml``.
99
+
100
+ Used by CLI scripts to populate ``--help`` with the list of names
101
+ accepted by the ``--exclude-external-codes`` flag. Loads the metadata
102
+ only — does not parse code values — so the cost is small.
103
+
104
+ :param base_path: Override directory containing codes.xml.
105
+ If None, uses package resource folder.
106
+ """
107
+ code_fd: IO[Any]
108
+ if base_path is not None:
109
+ code_fd = open(os.path.join(base_path, "codes.xml"), encoding="utf-8")
110
+ else:
111
+ code_fd = _res_files("pyx12").joinpath("map", "codes.xml").open("rb")
112
+ pairs: list[tuple[str, str]] = []
113
+ with code_fd:
114
+ parser = et.XMLParser(encoding="utf-8")
115
+ for cs in et.parse(code_fd, parser=parser).iter("codeset"):
116
+ cid = (cs.findtext("id") or "").strip()
117
+ name = (cs.findtext("name") or "").strip()
118
+ if cid:
119
+ pairs.append((cid, name))
120
+ return pairs
pyx12/dataele.py ADDED
@@ -0,0 +1,103 @@
1
+ ######################################################################
2
+ # Copyright (c) 2001-2019
3
+ # John Holland <john@zoner.org>
4
+ # All rights reserved.
5
+ #
6
+ # This software is licensed as described in the file LICENSE.txt, which
7
+ # you should have received as part of this distribution.
8
+ #
9
+ ######################################################################
10
+
11
+ """
12
+ Interface to normalized Data Elements
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import logging
18
+ import os.path
19
+ from importlib.resources import files as _res_files
20
+ from typing import IO, Any, TypedDict
21
+
22
+ import defusedxml.ElementTree as et
23
+
24
+ # Intrapackage imports
25
+ from pyx12.errors import EngineError
26
+
27
+
28
+ class DataElementsError(Exception):
29
+ """Class for data elements module errors."""
30
+
31
+
32
+ class _DataEle(TypedDict):
33
+ data_type: str | None
34
+ min_len: int
35
+ max_len: int
36
+ name: str | None
37
+
38
+
39
+ class DataElements:
40
+ """
41
+ Interface to normalized Data Elements
42
+ """
43
+
44
+ dataele: dict[str | None, _DataEle]
45
+
46
+ def __init__(self, base_path: str | None = None) -> None:
47
+ """
48
+ Initialize the list of data elements
49
+
50
+ :param base_path: Override directory containing dataele.xml. If None,
51
+ uses package resource folder
52
+ :type base_path: string
53
+
54
+ Note: ``self.dataele`` maps to the data element
55
+ ``{ele_num: {data_type, min_len, max_len, name}}``
56
+ """
57
+ logger = logging.getLogger("pyx12")
58
+ self.dataele = {}
59
+ dataele_file = "dataele.xml"
60
+ # ElementTree.parse accepts either text- or binary-mode streams; the
61
+ # file source differs between override path and bundled package resource.
62
+ fd: IO[Any]
63
+ if base_path is not None:
64
+ logger.debug(
65
+ f"Looking for data element definition file '{dataele_file}' in map_path '{base_path}'"
66
+ )
67
+ fd = open(os.path.join(base_path, dataele_file), encoding="utf-8")
68
+ else:
69
+ logger.debug(
70
+ f"Looking for data element definition file '{dataele_file}' in package resources"
71
+ )
72
+ fd = _res_files("pyx12").joinpath("map", dataele_file).open("rb")
73
+ with fd:
74
+ parser = et.XMLParser(encoding="utf-8")
75
+ for eElem in et.parse(fd, parser=parser).iter("data_ele"):
76
+ ele_num = eElem.get("ele_num")
77
+ self.dataele[ele_num] = {
78
+ "data_type": eElem.get("data_type"),
79
+ "min_len": int(eElem.get("min_len")),
80
+ "max_len": int(eElem.get("max_len")),
81
+ "name": eElem.get("name"),
82
+ }
83
+
84
+ def get_by_elem_num(self, ele_num: str | None) -> _DataEle:
85
+ """
86
+ Get the element characteristics for the indexed element code
87
+ :param ele_num: the data element code
88
+ :type ele_num: string
89
+ :return: {data_type, min_len, max_len, name}
90
+ :rtype: dict
91
+ """
92
+ if not ele_num:
93
+ raise EngineError(f"Bad data element {ele_num!r}")
94
+ if ele_num not in self.dataele:
95
+ raise EngineError(f'Data Element "{ele_num}" is not defined')
96
+ return self.dataele[ele_num]
97
+
98
+ def debug_print(self) -> None:
99
+ """
100
+ Debug print data elements
101
+ """
102
+ for ele_num in self.dataele:
103
+ print(self.dataele[ele_num])
pyx12/decorators.py ADDED
@@ -0,0 +1,79 @@
1
+ from __future__ import annotations
2
+
3
+ import collections.abc
4
+ import functools
5
+ from collections.abc import Callable
6
+ from typing import Any
7
+
8
+ # See https://wiki.python.org/moin/PythonDecoratorLibrary
9
+
10
+
11
+ def dump_args(func: Callable[..., Any]) -> Callable[..., Any]:
12
+ "This decorator dumps out the arguments passed to a function before calling it"
13
+ argnames = func.__code__.co_varnames[: func.__code__.co_argcount]
14
+ fname = func.__name__
15
+
16
+ def echo_func(*args: Any, **kwargs: Any) -> Any:
17
+ print(
18
+ (
19
+ fname,
20
+ ":",
21
+ ", ".join(
22
+ "%s=%r" % entry for entry in list(zip(argnames, args)) + list(kwargs.items())
23
+ ),
24
+ )
25
+ )
26
+ return func(*args, **kwargs)
27
+
28
+ return echo_func
29
+
30
+
31
+ def memoize(obj: Callable[..., Any]) -> Callable[..., Any]:
32
+ cache: dict[Any, Any] = {}
33
+ obj.cache = cache # type: ignore[attr-defined]
34
+
35
+ @functools.wraps(obj)
36
+ def memoizer(*args: Any, **kwargs: Any) -> Any:
37
+ if kwargs: # frozenset is used to ensure hashability
38
+ key: Any = (args, frozenset(kwargs.items()))
39
+ else:
40
+ key = args
41
+ if key not in cache:
42
+ cache[key] = obj(*args, **kwargs)
43
+ return cache[key]
44
+
45
+ return memoizer
46
+
47
+
48
+ class memoized:
49
+ """Decorator. Caches a function's return value each time it is called.
50
+ If called later with the same arguments, the cached value is returned
51
+ (not reevaluated).
52
+ """
53
+
54
+ func: Callable[..., Any]
55
+ cache: dict[Any, Any]
56
+
57
+ def __init__(self, func: Callable[..., Any]) -> None:
58
+ self.func = func
59
+ self.cache = {}
60
+
61
+ def __call__(self, *args: Any) -> Any:
62
+ if not isinstance(args, collections.abc.Hashable):
63
+ # uncacheable. a list, for instance.
64
+ # better to not cache than blow up.
65
+ return self.func(*args)
66
+ if args in self.cache:
67
+ return self.cache[args]
68
+ else:
69
+ value = self.func(*args)
70
+ self.cache[args] = value
71
+ return value
72
+
73
+ def __repr__(self) -> str:
74
+ """Return the function's docstring."""
75
+ return self.func.__doc__ or ""
76
+
77
+ def __get__(self, obj: Any, objtype: Any) -> Callable[..., Any]:
78
+ """Support instance methods."""
79
+ return functools.partial(self.__call__, obj)
pyx12/errh_xml.py ADDED
@@ -0,0 +1,324 @@
1
+ ######################################################################
2
+ # Copyright (c)
3
+ # John Holland <john@zoner.org>
4
+ # All rights reserved.
5
+ #
6
+ # This software is licensed as described in the file LICENSE.txt, which
7
+ # you should have received as part of this distribution.
8
+ #
9
+ ######################################################################
10
+
11
+ """
12
+ Capture X12 Errors
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import logging
18
+ import os
19
+ import tempfile
20
+ from types import TracebackType
21
+ from typing import IO, Any, Literal
22
+
23
+ # Intrapackage imports
24
+ from .errors import EngineError
25
+ from .xmlwriter import XMLWriter
26
+
27
+ # (kind, code, message, value, src_line)
28
+ _ErrTuple = tuple[str, str, str, Any, int | None]
29
+
30
+
31
+ class err_handler:
32
+ """
33
+ The interface to the error handling structures.
34
+ """
35
+
36
+ logger: logging.Logger
37
+ filename: str
38
+ fd: IO[Any]
39
+ cur_line: int | None
40
+ errors: list[_ErrTuple]
41
+ writer: XMLWriter
42
+
43
+ def __init__(self, xml_out: str | None = None, basedir: str | None = None) -> None:
44
+ """
45
+ :param xml_out: Output filename, if None, will dump to tempfile
46
+ :param basedir: working directory, where file will be created
47
+ """
48
+ self.logger = logging.getLogger("pyx12.errh_xml")
49
+ if xml_out:
50
+ self.filename = xml_out
51
+ self.fd = open(xml_out, "w", encoding="utf-8")
52
+ else:
53
+ try:
54
+ (fdesc, self.filename) = tempfile.mkstemp(".xml", "pyx12_")
55
+ self.fd = os.fdopen(fdesc, "w+b")
56
+ except OSError:
57
+ (fdesc, self.filename) = tempfile.mkstemp(
58
+ suffix=".xml", prefix="pyx12_", dir=basedir
59
+ )
60
+ self.fd = os.fdopen(fdesc, "w+b")
61
+ self.cur_line = None
62
+ self.errors = []
63
+ if not self.fd:
64
+ raise EngineError("Could not open temp error xml file")
65
+ self.writer = XMLWriter(self.fd) # type: ignore[arg-type]
66
+ self.writer.push("x12err")
67
+
68
+ def close(self) -> None:
69
+ """
70
+ Flush remaining XML closing tags and close the underlying file.
71
+ Idempotent.
72
+ """
73
+ while len(self.writer) > 0:
74
+ self.writer.pop()
75
+ if self.fd is not None and not self.fd.closed:
76
+ self.fd.close()
77
+
78
+ def __enter__(self) -> err_handler:
79
+ return self
80
+
81
+ def __exit__(
82
+ self,
83
+ exc_type: type[BaseException] | None,
84
+ exc: BaseException | None,
85
+ tb: TracebackType | None,
86
+ ) -> Literal[False]:
87
+ self.close()
88
+ return False
89
+
90
+ def getFilename(self) -> str:
91
+ return self.filename
92
+
93
+ def handleErrors(self, err_list: list[_ErrTuple]) -> None:
94
+ """
95
+ :param err_list: list of errors to apply
96
+ """
97
+ self.errors.extend(err_list)
98
+ # for (err_type, err_cde, err_str, err_val, src_line) in err_list:
99
+ # if err_type == 'isa':
100
+ # self.isa_error(err_cde, err_str)
101
+ # elif err_type == 'gs':
102
+ # self.gs_error(err_cde, err_str)
103
+ # elif err_type == 'st':
104
+ # self.st_error(err_cde, err_str)
105
+ # elif err_type == 'seg':
106
+ # self.seg_error(err_cde, err_str, err_val, src_line)
107
+
108
+ def getCurLine(self) -> int | None:
109
+ """
110
+ :return: Current file line number
111
+ :rtype: int
112
+ """
113
+ return self.cur_line
114
+
115
+ def Write(self, cur_line: int) -> None:
116
+ """
117
+ Generate XML for the segment data and matching map node
118
+
119
+ """
120
+ if len(self.errors) > 0:
121
+ self.writer.push("seg", attrs={"line": "%i" % (cur_line)})
122
+ for err_type, err_cde, err_str, err_val, src_line in self.errors:
123
+ self.writer.push("err", attrs={"code": err_cde})
124
+ # self.writer.elem(u"type", err_type)
125
+ # self.writer.elem(u"code", err_cde)
126
+ self.writer.elem("desc", err_str)
127
+ if err_val:
128
+ self.writer.elem("errval", err_val)
129
+ # self.writer.push(u"seg", {u'line': '%i'%(cur_line)})
130
+ # self.writer.elem(u'ele', seg_data.get_value('%02i' %
131
+ # (i+1)),
132
+ # attrs={u'id': child_node.id})
133
+ self.writer.pop() # end err
134
+ self.writer.pop() # end segment
135
+ self.errors = []
136
+
137
+
138
+ class ErrorErrhNull(Exception):
139
+ """Class for errh_null errors."""
140
+
141
+
142
+ class errh_list:
143
+ """
144
+ A null error object - used for testing.
145
+ Stores the current error in simple variables.
146
+ """
147
+
148
+ logger: logging.Logger
149
+ errors: list[_ErrTuple]
150
+ cur_line: int
151
+
152
+ def __init__(self) -> None:
153
+ self.logger = logging.getLogger("pyx12.errh_xml")
154
+ # self.id = 'ROOT'
155
+ self.errors = []
156
+ # self.cur_node = self
157
+ self.cur_line = 0
158
+ # self.err_cde = None
159
+ # self.err_str = None
160
+
161
+ def get_errors(self) -> list[_ErrTuple]:
162
+ return self.errors
163
+
164
+ def reset(self) -> None:
165
+ self.errors = []
166
+
167
+ def get_cur_line(self) -> int:
168
+ """
169
+ :return: Current file line number
170
+ :rtype: int
171
+ """
172
+ return self.cur_line
173
+
174
+ def set_cur_line(self, cur_line: int) -> None:
175
+ """ """
176
+ self.cur_line = cur_line
177
+
178
+ # def get_id(self):
179
+ # """
180
+ # :return: Error node type
181
+ # :rtype: string
182
+ # """
183
+ # return self.id
184
+
185
+ def add_isa_loop(self, seg: Any, src: Any) -> None:
186
+ """ """
187
+ # raise ErrorErrhNull, 'add_isa loop'
188
+ pass
189
+
190
+ def add_gs_loop(self, seg: Any, src: Any) -> None:
191
+ """ """
192
+ pass
193
+
194
+ def add_st_loop(self, seg: Any, src: Any) -> None:
195
+ """ """
196
+ pass
197
+
198
+ def add_seg(
199
+ self, map_node: Any, seg: Any, seg_count: int, cur_line: int, ls_id: str | None
200
+ ) -> None:
201
+ """ """
202
+ pass
203
+
204
+ def add_ele(self, map_node: Any) -> None:
205
+ """ """
206
+ pass
207
+
208
+ def isa_error(self, err_cde: str, err_str: str) -> None:
209
+ """
210
+ :param err_cde: ISA level error code
211
+ :type err_cde: string
212
+ :param err_str: Description of the error
213
+ :type err_str: string
214
+ """
215
+ self.errors.append(("isa", err_cde, err_str, None, None))
216
+ sout = ""
217
+ sout += "Line:%i " % (self.cur_line)
218
+ sout += "ISA:%s - %s" % (err_cde, err_str)
219
+ self.logger.error(sout)
220
+
221
+ def gs_error(self, err_cde: str, err_str: str) -> None:
222
+ """
223
+ :param err_cde: GS level error code
224
+ :type err_cde: string
225
+ :param err_str: Description of the error
226
+ :type err_str: string
227
+ """
228
+ self.errors.append(("gs", err_cde, err_str, None, None))
229
+ sout = ""
230
+ sout += "Line:%i " % (self.cur_line)
231
+ sout += "GS:%s - %s" % (err_cde, err_str)
232
+ self.logger.error(sout)
233
+
234
+ def st_error(self, err_cde: str, err_str: str) -> None:
235
+ """
236
+ :param err_cde: Segment level error code
237
+ :type err_cde: string
238
+ :param err_str: Description of the error
239
+ :type err_str: string
240
+ """
241
+ self.errors.append(("st", err_cde, err_str, None, None))
242
+ sout = ""
243
+ sout += "Line:%i " % (self.cur_line)
244
+ sout += "ST:%s - %s" % (err_cde, err_str)
245
+ self.logger.error(sout)
246
+
247
+ def seg_error(
248
+ self,
249
+ err_cde: str,
250
+ err_str: str,
251
+ err_value: str | None = None,
252
+ src_line: int | None = None,
253
+ ) -> None:
254
+ """
255
+ :param err_cde: Segment level error code
256
+ :type err_cde: string
257
+ :param err_str: Description of the error
258
+ :type err_str: string
259
+ """
260
+ self.errors.append(("seg", err_cde, err_str, err_value, src_line))
261
+ sout = ""
262
+ sout += "Line:%i " % (self.cur_line)
263
+ sout += "SEG:%s - %s" % (err_cde, err_str)
264
+ if err_value:
265
+ sout += " (%s)" % err_value
266
+ self.logger.error(sout)
267
+
268
+ def ele_error(self, err_cde: str, err_str: str, bad_value: str | None) -> None:
269
+ """
270
+ :param err_cde: Element level error code
271
+ :type err_cde: string
272
+ :param err_str: Description of the error
273
+ :type err_str: string
274
+ """
275
+ self.errors.append(("ele", err_cde, err_str, bad_value, None))
276
+ sout = ""
277
+ sout += "Line:%i " % (self.cur_line)
278
+ sout += "ELE:%s - %s" % (err_cde, err_str)
279
+ if bad_value:
280
+ sout += " (%s)" % (bad_value)
281
+ self.logger.error(sout)
282
+
283
+ def close_isa_loop(self, node: Any, seg: Any, src: Any) -> None:
284
+ """ """
285
+ pass
286
+
287
+ def close_gs_loop(self, node: Any, seg: Any, src: Any) -> None:
288
+ """ """
289
+ pass
290
+
291
+ def close_st_loop(self, node: Any, seg: Any, src: Any) -> None:
292
+ """ """
293
+ pass
294
+
295
+ def find_node(self, atype: str) -> None:
296
+ """
297
+ Find the last node of a type
298
+ """
299
+ pass
300
+
301
+ def get_parent(self) -> None:
302
+ return None
303
+
304
+ # def get_first_child(self):
305
+ # """
306
+ # """
307
+ # if len(self.children) > 0:
308
+ # return self.children[0]
309
+ # else:
310
+ # return None
311
+
312
+ def get_next_sibling(self) -> None:
313
+ """ """
314
+ return None
315
+
316
+ def get_error_count(self) -> int:
317
+ """ """
318
+ return len(self.errors)
319
+
320
+ def is_closed(self) -> bool:
321
+ """
322
+ :rtype: boolean
323
+ """
324
+ return True