Skip to content

Named XSD Element with unnamed complexType child generates invalid python. #97

@techdragon

Description

@techdragon

I'm dealing with a 3rd party vendor and their XSD schema seems to have revealed a shortcoming of soapfish's xsd2py functionality, and by extension, its wsdl2py functionality as well.

The trouble seems to be when an element and complex type are used like this in an XSD.

<xs:element name="fooCreateRequest">
    <xs:complexType>
        <xs:complexContent>
            <xs:extension base="FooCreateRequestBaseType"/>
        </xs:complexContent>
    </xs:complexType>
</xs:element>

<xs:complexType name="FooCreateRequestType">
    <xs:annotation>
        <xs:documentation>Foo Details to be created</xs:documentation>
    </xs:annotation>
    <xs:complexContent>
        <xs:extension base="FooCreateRequestBaseType">
            <xs:attribute name="version" type="xs:decimal" default="1" />
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

Initially this was just failing to generate at all, throwing a TypeError: 'NoneType' object is not subscriptable, one quick edit to the capitalize function in soapfish/utils.py and I was able to get it to generate the following python.

class FooCreateRequestType(FooCreateRequestBaseType):
    XSI_TYPE = xsd_types.XSDQName('https://www.example.com/ws', 'FooCreateRequestType')
    INHERITANCE = xsd.Inheritance.EXTENSION
    version = xsd.Attribute(xsd.Decimal, use=xsd.Use.OPTIONAL)


class (FooCreateRequestType):
    XSI_TYPE = xsd_types.XSDQName('https://www.example.com/ws', 'fooCreateRequest')
    INHERITANCE = xsd.Inheritance.EXTENSION

So it's not generating the classname.

I've cooked up a quick fix to this in my own local fork, but before I create a pull request that might mess up some of the work that is going on in @oskrkal 's branch over here in https://github.com/oskrkal/soapfish/tree/references , it seemed like I should check that I have actually fixed it correctly in the eyes of some people more familiar with what the code should be doing, not just written something that generates valid python syntax that won't do what it needs to do later.

My implemented fix generates the following code by checking for the existence of the complex type object name and using some extra logic to handle the case when the complex type object name is None

class FooCreateRequestType(FooCreateRequestBaseType):
    XSI_TYPE = xsd_types.XSDQName('https://www.example.com/ws', 'FooCreateRequestType')
    INHERITANCE = xsd.Inheritance.EXTENSION
    version = xsd.Attribute(xsd.Decimal, use=xsd.Use.OPTIONAL)


class FooCreateRequest(FooCreateRequestType):
    XSI_TYPE = xsd_types.XSDQName('https://www.example.com/ws', 'fooCreateRequest')
    INHERITANCE = xsd.Inheritance.EXTENSION

Does this look correct? I'm a little unsure about the capitalisation of the classname FooCreateRequest since it seems like it could be meant to match up with one of the names generated in the operations section, but it could just as easily not be meant to since that part also says "Put your own implementation here."

def FooCreate(request, fooCreateRequest):
    # TODO: Put your implementation here.
    return fooCreateResponse

With fooCreateResponse being undefined, but a FooCreateResponse has been generated.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions