Forum Discussion

jcalcote's avatar
jcalcote
New Contributor
2 months ago

Python 3.6 client support

I've spent a lot of time with OpenAPI in the last month. Our product used swagger for many years to both document our rest interface and generate a python (2.7) client for customers and internal uses.

It's time to upgrade - has been for some time now. 

However, our product is essentially an appliance that runs on a hardened Linux platform. Most of those support python 3.6 - period. Ok, yes, you can get 3.11 installed, but it's not the default python on the system. 

I find it hard to believe the openapi community could have seen it as a good idea to jump from python2.7 (swagger 1.5) directly to python 3.7+ (openapi 3.1) without even a thought for all those enterprise applications whose main python version is still 3.6 (rocky 8/9). 

Am I missing something? How do I generate a python client that takes full advantage of python 3 (ahem, enums) without sacrificing the ability to run on common enterprise Linux platforms?

I'm now considering pulling the source code for openapi generator and building my own python 3.6 compatible client generator.

Help me Obiwan Kenobi - you're my only hope!

  • jcalcote's avatar
    jcalcote
    New Contributor

    I went to github and looked at the python client generator code and started moving the version tag back one release at a time until I found the release (6.1.0) that last supported python 3.6 (2022). I pulled this release and built it and generated a python client from my spec. 

    Now I have to ask - Rather than generating standard python 3.4+ Enum classes:

    from enum import Enum
    class NetIdEnum(Enum):
            RDMA = "RDMA"
            RDMA6 = "RDMA6"
            TCP = "TCP"
            TCP6 = "TCP6"

    Or, if scoping is a concern:

    from enum import Enum
    class QualifiedAddressView(NormalMode):
        class NetIdEnum(Enum):
            RDMA = "RDMA"
            RDMA6 = "RDMA6"
            TCP = "TCP"
            TCP6 = "TCP6"

    it does this:

    class QualifiedAddressView(ModelNormal):
    ...
        allowed_values = {
            ('net_id',): {
                'RDMA': "RDMA",
                'RDMA6': "RDMA6",
                'TCP': "TCP",
                'TCP6': "TCP6",
            },
        }

    which makes for pretty unwieldy client usage:

    if QualifiedAddressView.allowed_values[('net_id',)]['RDMA'] == "RDMA":
        print("This is an RDMA type")

    rather than the much simpler:

    # Checking the value of net_id
    if address.net_id == QualifiedAddressView.NetIdEnum.RDMA:
        print("This address uses RDMA protocol")

    Can anyone expound on why this choice was made?