nazrulworld / fhir.resources

FHIR Resources https://www.hl7.org/fhir/resourcelist.html
https://pypi.org/project/fhir.resources/
Other
373 stars 104 forks source link

Parsing error for StructureDefinitions with type slicing in R4B #159

Open cybernop opened 1 month ago

cybernop commented 1 month ago

Description

I was trying to read a structure definition that contains type slicing. The definition has the canonical http://fhir.de/StructureDefinition/observation-de-vitalsign.

What I Did

Then I tried to read the the resource from a JSON file

from fhir.resources.R4B.structuredefinition import StructureDefinition

file_path = pathlib.Path("profile.json")
StructureDefinition.parse_file(file_path)

which gave the errors

pydantic.v1.error_wrappers.ValidationError: 36 validation errors for StructureDefinition
differential -> element -> 2 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
differential -> element -> 4 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
differential -> element -> 5 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
differential -> element -> 7 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
differential -> element -> 8 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
differential -> element -> 9 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
differential -> element -> 10 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
differential -> element -> 11 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
differential -> element -> 12 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
differential -> element -> 14 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
differential -> element -> 15 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
differential -> element -> 16 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
differential -> element -> 17 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
differential -> element -> 18 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
differential -> element -> 19 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
snapshot -> element -> 14 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
snapshot -> element -> 19 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
snapshot -> element -> 20 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
snapshot -> element -> 25 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
snapshot -> element -> 28 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
snapshot -> element -> 29 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
snapshot -> element -> 30 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
snapshot -> element -> 31 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
snapshot -> element -> 32 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
snapshot -> element -> 33 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
snapshot -> element -> 34 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
snapshot -> element -> 35 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
snapshot -> element -> 60 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
snapshot -> element -> 61 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
snapshot -> element -> 62 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
snapshot -> element -> 63 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
snapshot -> element -> 64 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
snapshot -> element -> 65 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
snapshot -> element -> 66 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
snapshot -> element -> 67 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
snapshot -> element -> 68 -> id
  string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
def test_fhir_profile_from_json():
        file = Path(PROFILE_FILE)

        assert file.exists()

>       result = FhirProfile.from_json(file)

service/tests/data/test_fhir_profile.py:13: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
service/src/structure_comparer/data/fhir_profile.py:27: in from_json
    data = StructureDefinition.parse_file(file_path)
.venv/lib/python3.12/site-packages/fhir/resources/core/fhirabstractmodel.py:243: in parse_file
    return cls.parse_obj(obj)
.venv/lib/python3.12/site-packages/pydantic/v1/main.py:526: in parse_obj
    return cls(**obj)
.venv/lib/python3.12/site-packages/fhir/resources/core/fhirabstractmodel.py:105: in __init__
    BaseModel.__init__(__pydantic_self__, **data)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

__pydantic_self__ = StructureDefinition()
data = {'abstract': False, 'baseDefinition': 'http://hl7.org/fhir/StructureDefinition/Observation', 'contact': [{'telecom': [{'system': 'url', 'value': 'http://hl7.de/technische-komitees/fhir/'}]}], 'date': '2023-11-30', ...}
values = {'abstract': False, 'abstract__ext': None, 'baseDefinition': 'http://hl7.org/fhir/StructureDefinition/Observation', 'baseDefinition__ext': None, ...}
fields_set = {'abstract', 'baseDefinition', 'contact', 'date', 'derivation', 'description', ...}
validation_error = ValidationError(model='StructureDefinition', errors=[{'loc': ('differential', 'element', 2, 'id'), 'msg': 'string does...oes not match regex "^[A-Za-z0-9\\-.]+$"', 'type': 'value_error.str.regex', 'ctx': {'pattern': '^[A-Za-z0-9\\-.]+$'}}])

    def __init__(__pydantic_self__, **data: Any) -> None:
        """
        Create a new model by parsing and validating input data from keyword arguments.

        Raises ValidationError if the input data cannot be parsed to form a valid model.
        """
        # Uses something other than `self` the first arg to allow "self" as a settable attribute
        values, fields_set, validation_error = validate_model(__pydantic_self__.__class__, data)
        if validation_error:
>           raise validation_error
E           pydantic.v1.error_wrappers.ValidationError: 36 validation errors for StructureDefinition
E           differential -> element -> 2 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           differential -> element -> 4 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           differential -> element -> 5 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           differential -> element -> 7 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           differential -> element -> 8 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           differential -> element -> 9 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           differential -> element -> 10 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           differential -> element -> 11 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           differential -> element -> 12 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           differential -> element -> 14 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           differential -> element -> 15 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           differential -> element -> 16 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           differential -> element -> 17 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           differential -> element -> 18 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           differential -> element -> 19 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           snapshot -> element -> 14 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           snapshot -> element -> 19 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           snapshot -> element -> 20 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           snapshot -> element -> 25 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           snapshot -> element -> 28 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           snapshot -> element -> 29 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           snapshot -> element -> 30 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           snapshot -> element -> 31 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           snapshot -> element -> 32 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           snapshot -> element -> 33 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           snapshot -> element -> 34 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           snapshot -> element -> 35 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           snapshot -> element -> 60 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           snapshot -> element -> 61 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           snapshot -> element -> 62 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           snapshot -> element -> 63 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           snapshot -> element -> 64 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$)
E           snapshot -> element -> 65 -> id
E             string does not match regex "^[A-Za-z0-9\-.]+$" (type=value_error.str.regex; pattern=^[A-Za-z0-9\-.]+$

Expectation

It is expected to parse this definition correctly. The issue here is that a regex for id is used on Element.id which is an string and therefore does allow other symbols.

cybernop commented 1 month ago

This issue will be solved by PR https://github.com/nazrulworld/fhir.resources/pull/160