Phantomtypen für Python helfen Ihnen dabei, illegale Staaten nicht wiederzuverständlich zu gestalten und eine Schrotflinte zu vermeiden, indem Sie es Ihnen ermöglichen, "analysieren, nicht validieren" zu üben.
$ python3 -m pip install phantom-typesEs stehen einige Extras zur Verfügung, mit denen entweder eine Funktion aktiviert oder eine kompatible Version einer Drittanbieterbibliothek installiert werden kann.
| Zusätzlicher Name | Besonderheit |
|---|---|
[dateutil] | Installiert Python-datutil. Erforderlich, um Saiten mit TZAware und TZNaive zu analysieren. |
[phonenumbers] | Installiert Phonenumzentner. Erforderlich, um phantom.ext.phonenumbers zu verwenden. |
[pydantic] | Installiert Pydantic. |
[hypothesis] | Installiert Hypothese. |
[all] | Installiert alle oben genannten. |
$ python3 -m pip install phantom-types[all]Durch die Einführung eines Phantomtyps können wir eine Voraussetzung für ein Funktionsargument definieren.
from phantom import Phantom
from phantom . predicates . collection import contained
class Name ( str , Phantom , predicate = contained ({ "Jane" , "Joe" })): ...
def greet ( name : Name ):
print ( f"Hello { name } !" )Dies ist ein gültiger Anruf.
greet ( Name . parse ( "Jane" ))... und das auch.
joe = "Joe"
assert isinstance ( joe , Name )
greet ( joe )Dies führt jedoch zu einem statischen Überprüfungsfehler.
greet ( "bird" ) Um klar zu sein, ist der Grund, warum das erste Beispiel vergeht, nicht darauf, dass der Typ -Checker auf magische Weise über unser Prädikat weiß, sondern weil wir den Typ -Checker über die assert mit Beweisen geliefert haben. Alles, was sich um den Typ -Checker kümmert, ist, dass die Laufzeit nicht weiterhin die Behauptung überschreiten kann, es sei denn, die Variable ist ein Name . Wenn wir die Anrufe wie im folgenden Beispiel umgehen, würde der Typ -Checker einen Fehler für den Anruf greet() angeben.
joe = "Joe"
greet ( joe )
assert isinstance ( joe , Name )Durch die Kombination von Phantomtypen mit einem Laufzeitprüfungs-wie Beagype oder Typeguard können wir das gleiche Sicherheitsniveau erreichen, wie Sie es durch die Verwendung von Verträgen gewinnen würden.
import datetime
from beartype import beartype
from phantom . datetime import TZAware
@ beartype
def soon ( dt : TZAware ) -> TZAware :
return dt + datetime . timedelta ( seconds = 10 ) Die soon Funktion wird nun bestätigen, dass sowohl sein Argument als auch der Rückgabewert Timezone AWARE, z. B. Vor- und Postbedingungen, sind.
Phantomtypen können mit pydantisch verwendet werden und haben Unterstützung außerhalb des Boxs integriert. Unterklassen von Phantom funktionieren sowohl mit der Validierung von Pydantic als auch mit seiner Schema -Generierung.
class Name ( str , Phantom , predicate = contained ({ "Jane" , "Joe" })):
@ classmethod
def __schema__ ( cls ) -> Schema :
return super (). __schema__ () | {
"description" : "Either Jane or Joe" ,
"format" : "custom-name" ,
}
class Person ( BaseModel ):
name : Name
created : TZAware
print ( json . dumps ( Person . schema (), indent = 2 ))Der obige Code gibt das folgende Json -Schema aus.
{
"title" : " Person " ,
"type" : " object " ,
"properties" : {
"name" : {
"title" : " Name " ,
"description" : " Either Jane or Joe " ,
"format" : " custom-name " ,
"type" : " string "
},
"created" : {
"title" : " TZAware " ,
"description" : " A date-time with timezone data. " ,
"type" : " string " ,
"format" : " date-time "
}
},
"required" : [ " name " , " created " ]
}Installieren Sie die Entwicklungsanforderungen, vorzugsweise in einem Virtualenv:
$ python3 -m pip install .[all,test,type-check]Tests ausführen:
$ pytest
# or
$ make testTEILTEMENTRECHUNG FÜR DIE GEHANDEN:
$ mypyLinter und Formatters werden mit Gans eingerichtet. Nach der Installation können Sie es ausführen wie:
# run all checks
$ goose run --select=all
# or just a single hook
$ goose run mypy --select=allZusätzlich zur statischen Überprüfung des Typs wird das Projekt mit PyTest-Mypy-Plugins eingerichtet, um zu testen, dass die exponierten MyPy-Typen wie erwartet funktionieren. Diese Überprüfungen werden zusammen mit dem Rest der Testsuite zusammengestellt, aber Sie können sie mit dem folgenden Befehl ausgeben.
$ make test-typing