Призрачные типы для Python помогут вам сделать нелегальные государства непреднамеренными и избежать анализа ружений, позволяя вам практиковать «Parse, не подтвердить».
$ python3 -m pip install phantom-typesСуществует несколько дополнительных дополнений, которые можно использовать для включения функции или установить совместимую версию сторонней библиотеки.
| Дополнительное имя | Особенность |
|---|---|
[dateutil] | Устанавливает Python-Dateutil. Требуется для анализа струн с TZAware и TZNaive . |
[phonenumbers] | Устанавливает Phonenumbers. Требуется использовать phantom.ext.phonenumbers . |
[pydantic] | Устанавливает Pydantic. |
[hypothesis] | Устанавливает гипотезу. |
[all] | Устанавливает все вышеперечисленное. |
$ python3 -m pip install phantom-types[all]Представляя фантомный тип, мы можем определить предварительное условие для аргумента функции.
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 } !" )Теперь это будет действительный вызов.
greet ( Name . parse ( "Jane" ))... и это будет так.
joe = "Joe"
assert isinstance ( joe , Name )
greet ( joe )Но это даст ошибку проверки статического типа.
greet ( "bird" ) Чтобы быть ясным, причина, по которой первый пример проходит не в том, что проверка типа каким -то образом волшебным образом знает о нашем предикате, а в том, что мы предоставили проверку типа с доказательством через assert . Все, что заботится о типе, это то, что время выполнения не может продолжать выполнять выполнение после утверждения, если переменная не является Name . Если мы перемещаем вызовы, как в примере ниже, проверка типа выдаст ошибку для вызова greet() .
joe = "Joe"
greet ( joe )
assert isinstance ( joe , Name )Комбинируя фантомные типы с крикером времени выполнения, такой как Beartype или Typeguard, мы можем достичь того же уровня безопасности, что и вы получите от использования контрактов.
import datetime
from beartype import beartype
from phantom . datetime import TZAware
@ beartype
def soon ( dt : TZAware ) -> TZAware :
return dt + datetime . timedelta ( seconds = 10 ) Функция soon теперь подтвердит, что как его аргумент, так и возвращаемая стоимость осведомлены о времени, например, условие до и после.
Призрачные типы готовы к использованию с Pydantic и имеют интегрированную поддержку вне коробки. Подклассы Phantom работы как с подтверждением Pydantic, так и с его генерацией схем.
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 ))Приведенный выше код выводит следующий jsonschema.
{
"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 " ]
}Установите требования к разработке, предпочтительно в VirtualEnv:
$ python3 -m pip install .[all,test,type-check]Запустите тесты:
$ pytest
# or
$ make testПроверьте Тип Проверка:
$ mypyЛинтеры и форматер настроены с гусями, после его установки вы можете запустить его как:
# run all checks
$ goose run --select=all
# or just a single hook
$ goose run mypy --select=allВ дополнение к проверке статического типа, проект настроен с Pytest-Mypy-Plugins для проверки того, что выявленные типы Mypy работают, как и ожидалось, эти проверки будут работать вместе с остальной частью тестового набора, но вы можете выделить их со следующей командой.
$ make test-typing