Source code for pyx12.path
######################################################################
# Copyright (c)
# 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.
#
######################################################################
"""
Parses an x12 path
An x12 path is comprised of a sequence of loop identifiers, a segment
identifier, and element position, and a composite position.
The last loop id might be a segment id.
/LOOP_1/LOOP_2
/LOOP_1/LOOP_2/SEG
/LOOP_1/LOOP_2/SEG02
/LOOP_1/LOOP_2/SEG[424]02-1
SEG[434]02-1
02-1
02
"""
from __future__ import annotations
import re
from pyx12.errors import X12PathError
[docs]
class X12Path:
"""
Interface to an x12 path
"""
[docs]
re_seg_id: str = "(?P<seg_id>[A-Z][A-Z0-9]{1,2})?"
[docs]
re_id_val: str = r"(\[(?P<id_val>[A-Z0-9]+)\])?"
[docs]
re_ele_idx: str = "(?P<ele_idx>[0-9]{2})?"
[docs]
re_subele_idx: str = "(-(?P<subele_idx>[0-9]+))?"
[docs]
re_str: str = "^%s%s%s%s$" % (re_seg_id, re_id_val, re_ele_idx, re_subele_idx)
[docs]
rec_path: re.Pattern[str] = re.compile(re_str, re.S)
def __init__(self, path_str: str) -> None:
"""
:param path_str:
:type path_str: string
"""
# self.loop_list =
self.seg_id = None
self.id_val = None
self.ele_idx = None
self.subele_idx = None
self.relative = None
self.loop_list = []
if path_str == "":
self.relative = True
return
if path_str[0] == "/":
self.relative = False
self.loop_list = path_str[1:].split("/")
# self.loop_list = [x for x in path_str[1:].split('/') if x != '']
else:
self.relative = True
self.loop_list = path_str.split("/")
# self.loop_list = [x for x in path_str.split('/') if x != '']
if len(self.loop_list) == 0:
return
if len(self.loop_list) > 0 and self.loop_list[-1] == "":
# Ended in a /, so no segment
del self.loop_list[-1]
return
if len(self.loop_list) > 0:
seg_str = self.loop_list[-1]
m = X12Path.rec_path.search(seg_str)
if m is not None:
self.seg_id = m.group("seg_id")
self.id_val = m.group("id_val")
if m.group("ele_idx") is not None:
self.ele_idx = int(m.group("ele_idx"))
if m.group("subele_idx") is not None:
self.subele_idx = int(m.group("subele_idx"))
del self.loop_list[-1]
if self.seg_id is None and self.id_val is not None:
raise X12PathError(
'Path "%s" is invalid. Must specify a segment identifier with a qualifier'
% (path_str)
)
if (
self.seg_id is None
and (self.ele_idx is not None or self.subele_idx is not None)
and len(self.loop_list) > 0
):
raise X12PathError(
'Path "%s" is invalid. Must specify a segment identifier' % (path_str)
)
[docs]
def is_match(self, path_str: str) -> None:
pass
[docs]
def empty(self) -> bool:
"""
Is the path empty?
:return: True if contains no path data
:rtype: boolean
"""
return (
self.relative is True
and len(self.loop_list) == 0
and self.seg_id is None
and self.ele_idx is None
)
def _is_child_path(self, root_path: str, child_path: str) -> bool:
"""
Is the child path really a child of the root path?
:type root_path: string
:type child_path: string
:return: True if a child
:rtype: boolean
"""
root = root_path.split("/")
child = child_path.split("/")
if len(root) >= len(child):
return False
for i in range(len(root)):
if root[i] != child[i]:
return False
return True
def __eq__(self, other: object) -> bool:
if isinstance(other, X12Path):
return (
self.loop_list == other.loop_list
and self.seg_id == other.seg_id
and self.id_val == other.id_val
and self.ele_idx == other.ele_idx
and self.subele_idx == other.subele_idx
and self.relative == other.relative
)
return NotImplemented
def __lt__(self, other: object) -> bool:
return NotImplemented
__le__ = __lt__
__le__ = __lt__
__gt__ = __lt__
__ge__ = __lt__
# def __len__(self):
# """
# :rtype: int
# """
# return 1
def __repr__(self) -> str:
"""
:return: Formatted path
:rtype: string
"""
ret = ""
if not self.relative:
ret += "/"
ret += "/".join(self.loop_list)
if self.seg_id and ret != "" and ret != "/":
ret += "/"
ret += self.format_refdes()
return ret
def __hash__(self) -> int:
return self.__repr__().__hash__()
[docs]
def is_child_path(self, child_path: str) -> bool:
"""
Is the child path a child of this path?
:type child_path: string
:return: True if a child
:rtype: boolean
"""
root = self.format().split("/")
child = child_path.split("/")
if len(root) >= len(child):
return False
for i in range(len(root)):
if root[i] != child[i]:
return False
return True