Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client only parses xsd type extensions one level #1407

Open
atlantis-dsf opened this issue Feb 19, 2024 · 0 comments
Open

Client only parses xsd type extensions one level #1407

atlantis-dsf opened this issue Feb 19, 2024 · 0 comments

Comments

@atlantis-dsf
Copy link

atlantis-dsf commented Feb 19, 2024

  1. Zeep Version 4.2.1 (Python 3.11.2)
  2. The WSDL you are using
  3. And most importantly, a runnable example script which exposes the problem.

Hello, I know the issue looks long but that's just from the example code, the issue title describes the bug exactly, I only add explanations to "Current situation", "Expected behavior" and "Tried solutions"
The example code as well as excerpts from the .xsd file you can find under EXAMPLE CODE

I really appreciate you creating and maintaining this package, I don't know what else we would do
If you can solve this and you have a rate in mind let me know

Current situation: zeep.Client recognizes the extension of a type, so the ClassificationType generated by zeep does extend the RegistryObjectType. But the RegistryObjectType extends the IdentifiableType, and the ClassificationType generated doesn't include the attributes/elements of the IdentifiableType (in particular Slot[] and id)

Expected behavior: zeep.Client traverses the whole extension hierarchy

Tried solutions:

  • overwriting the types directly using client.wsdl.types.types stuff

  • creating a prepared_document using from zeep.wsdl.wsdl.Document, overwriting the types, and the creating the client based on the prepared_document

  • -> the problem here was that client.get_type() was returning my overwritten types, calling the service.Operation() was not using my overwritten types

  • I am creatting the message based on a dictionary, so I wrote various dictionary-traversing scripts that replace lists of dicts with lists of instantiated zeep elements (using my adulterated types)

  • -> this creates more and harder to debug errors, like duplicate keys and arrays filled with None (because in reality not all parent types extend all child attributes, but for zeep they do, and instantiating them without specifying the attribute defaults them to None)

  • -> example: {"Classification": {"Classification": [None, None]})

  • -> example error: TypeError: Argument must be bytes or unicode, got '_StaticIdentity'

  • SKIPPABLE I have a second problem (will open a second issue for it) which is that the type e.g. TListType is defined as having one element T, which is an array of T. The problem is that the array really consists of types that extend T, creating two problems: zeep fails when calling the service and I can't use the .extend approach because O doesn't extend the child-types, so what I tried was appending them to O._element, but this doesn't seem to affect the signature...

EXAMPLE CODE

# example script
from zeep import Client
from zeep.settings import Settings

# EntitiesForbidden: EntitiesForbidden(name='dsig', content='http://www.w3.org/2000/09/xmldsig#')
client_settings = Settings(strict=False, xml_huge_tree=True, forbid_entities=False)

wsdl_src = "https://raw.githubusercontent.com/gematik/epa-ps-sim/main/epa-fm-java-api/src/main/resources/schemas/conn/phrs/PHRService_V2_0_1.wsdl"

client = Client(wsdl=wsdl_src, settings=client_settings)

rim_qname = "{urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0}"
ClassificationType = client.get_type(rim_qname + "ClassificationType")

print("ClassificationType extends ", ClassificationType._extension_types)

RegistryObjectType = client.get_type(rim_qname + ClassificationType._extension_types[0].__name__)

print("RegistryObjectType extends ", RegistryObjectType._extension_types)

IdentifiableType = client.get_type(rim_qname + RegistryObjectType._extension_types[0].__name__)

print("IdentifiableType extends ", IdentifiableType._extension_types)

print("IdentifiableType base object: ", IdentifiableType(Slot=[]))

print("ClassificationType base object: ", ClassificationType())

# ClassificationType(Slot=[]) fails with TypeError
# TypeError: {urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0}ClassificationType() got an unexpected keyword argument 'Slot'. Signature: ...
try:
    ClassificationType(Slot=[])
except TypeError as e:
    print(e)

All the relevant types come from the "lib-ihe-xds" repository, from the ext\ebRS\rim.xsd type definition file

The relevant excerpts from the WSDL for convenience

<complexType name="ClassificationType">
    <annotation>
        <documentation xml:lang="en">
    Classification is the mapping of the same named interface in ebRIM.
    It extends RegistryObject.
    A Classification specifies references to two registry entrys.
    The classifiedObject is id of the Object being classified.
    The classificationNode is id of the ClassificationNode classying the object
    </documentation>
    </annotation>
    <complexContent>
        <extension base="tns:RegistryObjectType">
            <attribute name="classificationScheme" type="tns:referenceURI" use="optional"/>
            <attribute name="classifiedObject" type="tns:referenceURI" use="required"/>
            <attribute name="classificationNode" type="tns:referenceURI" use="optional"/>
            <attribute name="nodeRepresentation" type="tns:LongName" use="optional"/>
        </extension>
    </complexContent>
</complexType>
<element name="Classification" type="tns:ClassificationType" substitutionGroup="tns:Identifiable"/>```


```xml
<complexType name="RegistryObjectType">
    <complexContent>
        <extension base="tns:IdentifiableType">
            <sequence minOccurs="0" maxOccurs="1">
                <element ref="tns:Name" minOccurs="0" maxOccurs="1"/>
                <element ref="tns:Description" minOccurs="0" maxOccurs="1"/>
                <element name="VersionInfo" type="tns:VersionInfoType" minOccurs="0" maxOccurs="1"/>
                <element ref="tns:Classification" minOccurs="0" maxOccurs="unbounded"/>
                <element ref="tns:ExternalIdentifier" minOccurs="0" maxOccurs="unbounded"/>
            </sequence>
            <attribute name="lid" type="anyURI" use="optional"/>
            <attribute name="objectType" type="tns:referenceURI" use="optional"/>
            <attribute name="status" type="tns:referenceURI" use="optional"/>
        </extension>
    </complexContent>
</complexType>
<element name="RegistryObject" type="tns:RegistryObjectType" substitutionGroup="tns:Identifiable"/>
<complexType name="IdentifiableType">
    <annotation>
        <documentation xml:lang="en">
    Common base type for all types that have unique identity.     
    If id is provided and is not in proper URN syntax then it is used for
    linkage within document and is ignored by the registry. In this case the
    registry generates a UUID URN for id attribute.
    id must not be null when object is retrieved from the registry.
    </documentation>
    </annotation>
    <sequence>
        <element ref="tns:Slot" minOccurs="0" maxOccurs="unbounded"/>
    </sequence>
    <attribute name="id" type="anyURI" use="required"/>
    <attribute name="home" type="anyURI" use="optional"/>
    <!-- home attribute is required only for remote ObjectRef -->
</complexType>
<element name="Identifiable" type="tns:IdentifiableType"/>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant