pythonpython-3.xversioningdistutils

Python list of versions without distutils.version


How can I sort a list of versions without using distutils?

distutils.version has a limit to how long a version number can be and so I get

StrictVersion

msg": "invalid version number '11.2.0.4.v4'" 

LooseVersion

"results": null 

Results without sorting

["11.2.0.4.v4", "11.2.0.4.v5", "11.2.0.4.v6", "11.2.0.4.v7", "11.2.0.4.v8", 
 "11.2.0.4.v9", "11.2.0.4.v10", "11.2.0.4.v11", "11.2.0.4.v12", 
 "11.2.0.4.v13", "11.2.0.4.v14", "11.2.0.4.v15", "11.2.0.4.v16", 
 "11.2.0.4.v17", "12.1.0.2.v1", "12.1.0.2.v2", "12.1.0.2.v3", "12.1.0.2.v4", 
 "12.1.0.2.v5", "12.1.0.2.v6", "12.1.0.2.v7", "12.1.0.2.v8", "12.1.0.2.v9", 
 "12.1.0.2.v10", "12.1.0.2.v11", "12.1.0.2.v12", "12.1.0.2.v13"]

Pertinent code

try:
    params = dict()
    params['Engine'] = module.params.get('engine_name')
    results = client.describe_db_engine_versions(**params)
    versions = [z['EngineVersion'] for z in results['DBEngineVersions']]
    return versions.sort(key=StrictVersion)        
except Exception as e:
    module.fail_json(msg=str(e))

Solution

  • Normally this would be done using packaging.version.Version, but it won't work in this case since the strings are not valid version numbers according to the specification.

    >>> from packaging.version import parse
    >>> parse("11.2.0.4.v4")
    InvalidVersion: Invalid version: '11.2.0.4.v4'
    

    You may use looseversion for ordering these strings. It is a backwards/forwards-compatible fork of the deprecated distutils.version.LooseVersion type, for occasions when strict PEP 440 constraints on the data are undesirable.

    >>> from looseversion import LooseVersion
    >>> sorted(vs, key=LooseVersion)
    ['11.2.0.4.v4',
     '11.2.0.4.v5',
     '11.2.0.4.v6',
     '11.2.0.4.v7',
     '11.2.0.4.v8',
     '11.2.0.4.v9',
     '11.2.0.4.v10',
     '11.2.0.4.v11',
     '11.2.0.4.v12',
     '11.2.0.4.v13',
     '11.2.0.4.v14',
     '11.2.0.4.v15',
     '11.2.0.4.v16',
     '11.2.0.4.v17',
     '12.1.0.2.v1',
     '12.1.0.2.v2',
     '12.1.0.2.v3',
     '12.1.0.2.v4',
     '12.1.0.2.v5',
     '12.1.0.2.v6',
     '12.1.0.2.v7',
     '12.1.0.2.v8',
     '12.1.0.2.v9',
     '12.1.0.2.v10',
     '12.1.0.2.v11',
     '12.1.0.2.v12',
     '12.1.0.2.v13']