Skip to content

Commit

Permalink
Fixes #44
Browse files Browse the repository at this point in the history
  • Loading branch information
svituz committed Dec 21, 2020
1 parent 5b79963 commit 0b619c3
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 18 deletions.
4 changes: 3 additions & 1 deletion hl7apy/core.py
Expand Up @@ -702,6 +702,8 @@ def parse_children(self, text, **kwargs):
kwargs['version'] = self.version
kwargs['validation_level'] = self.validation_level
kwargs['encoding_chars'] = self.encoding_chars
if 'references' not in kwargs:
kwargs['references'] = self.structure_by_name

module = importlib.import_module("hl7apy.parser")
parser = getattr(module, self.child_parser[1])
Expand Down Expand Up @@ -1151,7 +1153,7 @@ def to_er7(self, encoding_chars=None, trailing_children=False):
try:
return self.value.to_er7(encoding_chars)
except AttributeError:
return self.value
return ''

def _set_value(self, value):
if value is None:
Expand Down
43 changes: 28 additions & 15 deletions hl7apy/parser.py
Expand Up @@ -160,13 +160,13 @@ def parse_segments(text, version=None, encoding_chars=None, validation_level=Non
current_parent = current_parent.parent
else:
if current_parent is None and parents_refs[-1][0] is not None or \
current_parent is not None and parents_refs[-1][0] != current_parent.name:
current_parent is not None and parents_refs[-1][0] != current_parent.name:
# create the parents group of the segment
if current_parent is not None:
cur_idx = parents_refs.index((current_parent.name, current_parent.reference))
else:
cur_idx = parents_refs.index((None, references))
for p_ref in parents_refs[cur_idx+1:]:
for p_ref in parents_refs[cur_idx + 1:]:
group = Group(p_ref[0], version=version, reference=p_ref[1],
validation_level=validation_level)
if current_parent is None:
Expand Down Expand Up @@ -299,7 +299,7 @@ def parse_fields(text, name_prefix=None, version=None, encoding_chars=None, vali
splitted_fields = text.split(field_sep)
fields = []
for index, field in enumerate(splitted_fields):
name = "{0}_{1}".format(name_prefix, index+1) if name_prefix is not None else None
name = "{0}_{1}".format(name_prefix, index + 1) if name_prefix is not None else None
try:
reference = references[name]['ref'] if references is not None else None
except KeyError:
Expand Down Expand Up @@ -446,9 +446,9 @@ def parse_components(text, field_datatype='ST', version=None, encoding_chars=Non
component_name = None
elif field_datatype is None or field_datatype == 'varies':
component_datatype = None
component_name = 'VARIES_{0}'.format(index+1)
component_name = 'VARIES_{0}'.format(index + 1)
else:
component_name = "{0}_{1}".format(field_datatype, index+1)
component_name = "{0}_{1}".format(field_datatype, index + 1)
component_datatype = None

try:
Expand Down Expand Up @@ -519,7 +519,8 @@ def parse_component(text, name=None, datatype='ST', version=None, encoding_chars
raise e
component = Component(datatype, version=version, validation_level=validation_level,
reference=reference)
children = parse_subcomponents(text, component.datatype, version, encoding_chars, validation_level)
children = parse_subcomponents(text, component.datatype, version, encoding_chars, validation_level,
component.structure_by_name)
if Validator.is_tolerant(component.validation_level) and is_base_datatype(component.datatype, version) and \
len(children) > 1:
component.datatype = None
Expand All @@ -528,7 +529,7 @@ def parse_component(text, name=None, datatype='ST', version=None, encoding_chars


def parse_subcomponents(text, component_datatype='ST', version=None, encoding_chars=None,
validation_level=None):
validation_level=None, references=None):
"""
Parse the given ER7-encoded subcomponents and return a list of
:class:`SubComponent <hl7apy.core.SubComponent>` instances.
Expand All @@ -552,9 +553,12 @@ def parse_subcomponents(text, component_datatype='ST', version=None, encoding_ch
:class:`VALIDATION_LEVEL <hl7apy.consts.VALIDATION_LEVEL>` class or ``None`` to use the default
validation level (see :func:`set_default_validation_level <hl7apy.set_default_validation_level>`)
:type references: ``list``
:param references: A list of the references of the :class:`SubComponent <hl7apy.core.SubComponent>`'s children
:return: a list of :class:`SubComponent <hl7apy.core.SubComponent>` instances
>>> subcomponents= "ID&TEST&&AHAH"
>>> subcomponents = "ID&TEST&&AHAH"
>>> cwe = parse_subcomponents(subcomponents, component_datatype="CWE")
>>> print(cwe)
[<SubComponent CWE_1>, <SubComponent CWE_2>, <SubComponent CWE_4>]
Expand All @@ -580,23 +584,32 @@ def parse_subcomponents(text, component_datatype='ST', version=None, encoding_ch
subcomponent_name = None
subcomponent_datatype = component_datatype if component_datatype is not None else 'ST'
else:
subcomponent_name = "{0}_{1}".format(component_datatype, index+1)
subcomponent_name = "{0}_{1}".format(component_datatype, index + 1)
subcomponent_datatype = None

try:
reference = references[subcomponent_name]['ref'] \
if None not in (references, subcomponent_name) else None
except KeyError:
reference = None
subcomponent_name = None
subcomponent_datatype = 'ST'

if subcomponent.strip() or subcomponent_name is None:
subcomponents.append(parse_subcomponent(subcomponent, subcomponent_name, subcomponent_datatype,
version, validation_level))
version, validation_level, reference))
return subcomponents


def parse_subcomponent(text, name=None, datatype='ST', version=None, validation_level=None):
def parse_subcomponent(text, name=None, datatype='ST', version=None, validation_level=None, reference=None):
"""
Parse the given ER7-encoded component and return an instance of
:class:`SubComponent <hl7apy.core.SubComponent>`.
:type text: ``str``
:param text: the ER7-encoded string containing the subcomponent data
:type name: ``str``
:type name: ``str``, None
:param name: the subcomponent's name (e.g. XPN_2)
:type datatype: ``str``
Expand All @@ -617,7 +630,7 @@ def parse_subcomponent(text, name=None, datatype='ST', version=None, validation_
validation_level = _get_validation_level(validation_level)

return SubComponent(name=name, datatype=datatype, value=text, version=version,
validation_level=validation_level)
validation_level=validation_level, reference=reference)


def _split_msh(content):
Expand Down Expand Up @@ -747,6 +760,6 @@ def _get_validation_level(validation_level):


if __name__ == '__main__':

import doctest
doctest.testmod()

doctest.testmod()
9 changes: 9 additions & 0 deletions tests/test_core.py
Expand Up @@ -1353,6 +1353,7 @@ def test_add_empty_subcomponent(self):
m = Message('RSP_K21', reference=self.rsp_k21_mp, validation_level=VALIDATION_LEVEL.TOLERANT)
c = m.add_segment('QPD').add_field('QPD_8').add_component('CX_4')
c.add(SubComponent(datatype='ST'))
self.assertEquals(c.value, '&&&')

def test_add_known_subcomponent_to_empty_component(self):
c = Component()
Expand Down Expand Up @@ -1914,6 +1915,14 @@ def test_bug_13(self):

self.assertEqual(s.children, c.cwe_1.children)

def test_assign_value_with_unknown_subcomponent(self):
c = Component(datatype='CE')
c.value = '555-55-5555&PRIMARY&PATRICIA P&6&&MD&UNKN'
self.assertEqual(c.children[-1].name, 'ST')
self.assertEqual(c.children[-1].datatype, 'ST')
self.assertEqual(c.children[-1].to_er7(), 'UNKN')
self.assertEqual(c.value, '555-55-5555&PRIMARY&PATRICIA P&6&&MD&UNKN')


class TestSubComponent(unittest.TestCase):

Expand Down
8 changes: 8 additions & 0 deletions tests/test_parser.py
Expand Up @@ -395,6 +395,14 @@ def test_parse_component(self):
self.assertEqual(c.children[0].to_er7(), 'comp1')
self.assertEqual(c.children[1].to_er7(), 'comp2')

def test_parse_component_with_datatype(self):
c = parse_component('555-55-5555&PRIMARY&PATRICIA&6&&MD', datatype='CE', version='2.5.1')
self.assertEqual(c.value, '555-55-5555&PRIMARY&PATRICIA&6&&MD')

def test_parse_component_with_datatype_and_unknown_subcomponent(self):
c = parse_component('555-55-5555&PRIMARY&PATRICIA P&6&&MD&UNKN', datatype='CE', version='2.5.1')
self.assertEqual(c.value, '555-55-5555&PRIMARY&PATRICIA P&6&&MD&UNKN')

def test_parse_component_invalid_encoding_chars(self):
component = 'comp'
self.assertRaises(InvalidEncodingChars, parse_component, component,
Expand Down
4 changes: 2 additions & 2 deletions tests/test_validation.py
Expand Up @@ -26,8 +26,8 @@
import hl7apy
from hl7apy.core import Group, Field, Component, SubComponent
from hl7apy.parser import parse_message, parse_segments, parse_segment, parse_field
from hl7apy.validation import Validator, VALIDATION_LEVEL
from hl7apy.exceptions import ValidationError, ValidationWarning
from hl7apy.validation import VALIDATION_LEVEL
from hl7apy.exceptions import ValidationError


class TestValidation(unittest.TestCase):
Expand Down

0 comments on commit 0b619c3

Please sign in to comment.