2016-04-25 5 views
1

Gegeben zwei Versionsnummern und einem Vergleich Spezifizierer:Python vergleicht Versionsnummern mit dynamischem Vergleich Spezifizierer

def check_versions(ver1, specifier, ver2): 
    # TODO 

check_versions("1.2.3", ">=", "2.0.0") # Should return True 
check_versions("1.2.3", "==", "2.0.0") # Should return False 

Ich mag den Vergleich zu den beiden Versionen anzuwenden, so dass ich die erwarteten Ausgabe von oben erhalten.

Ich habe festgestellt, dass ich Versionen LooseVersion von distutils.version wie so verwenden vergleichen:

LooseVersion("1.2.3") >= LooseVersion("2.0.0") 

Aber wie kann ich den Vergleich selbst mache in specifier auf dem bestandenen ab?

konnte ich die Lösung von here verwenden:

def check_versions(ver1, specifier, ver2): 
    return { 
     '==': LooseVersion(ver1) == LooseVersion(ver2), 
     '>=': LooseVersion(ver1) >= LooseVersion(ver2), 
     '<=': LooseVersion(ver1) <= LooseVersion(ver2), 
     '>': LooseVersion(ver1) > LooseVersion(ver2), 
     '<': LooseVersion(ver1) < LooseVersion(ver2), 
    }.get(x, False) 

Aber das fühlt sich einfach wirklich klobig zu mir. Gibt es keine elegantere Lösung?

+0

Warum verwenden Sie nicht smerver: https://github.com/k-bx/python-semver –

+0

@Apero Wenn der Vergleichsoperator dynamisch ist, bedeutet das, ich weiß nicht, ob der Scheck '

+0

oh ich verpasste diesen wichtigen Punkt, in der Tat –

Antwort

5

Statt Um ein Wörterbuch mit allen möglichen Vergleichen für die Versionen zu erstellen, können Sie einfach eine Suche nach den verwendeten Operatoren erstellen, zB:

import operator as op 
from distutils.version import LooseVersion 

lookup = {'<': op.lt, '<=': op.le, '==': op.eq, '>=': op.ge, '>': op.gt} 

def check_versions(ver1, specifier, ver2): 
    try: 
     return lookup[specifier](LooseVersion(ver1), LooseVersion(ver2)) 
    except KeyError: 
     # unknown specifier 
     return False 
1

Sie könnten eval verwenden.

def check_versions(ver1, specifier, ver2): 
    return eval("LooseVersion(ver1) " + specifier + " LooseVersion(ver2)") 

jedoch vorsichtig sein, wenn specifier aus Benutzereingaben kommt, könnten Sie einen bösartigen Anruf erhalten:

check_versions("1.0.0", " == 1; pkg_resources.get_distribution("really bad virus"); 
       import really_bad_virus; really_bad_virus.bobby_tables();", "1.0.0") 

Wenn ja, könnten Sie sanitize your inputs bevor sie zu bewerten:

def check_versions(ver1, specifier, ver2): 
    if specifier in ['==', '<=', '>=', '>', '>']: 
     return eval("LooseVersion(ver1) " + specifier + " LooseVersion(ver2)") 
+3

Ich muss sagen, das ist definitiv nicht etwas Wert in 'Eval' über bringen. Jedes Mal, wenn jemand sich das ansieht, müssen sie aufhören und darüber nachdenken, ob das sicher ist. 5 Zeilen zu sparen ist das nicht wert. (Sie haben auch keine Handhabung für einen 'Spezifizierer', der nicht in Ihrer Liste enthalten ist.) – user2357112