Os tipos de fantasmas para Python ajudarão você a tornar os estados ilegais não representáveis e evitar a análise de espingarda, permitindo que você pratique "análise, não validar".
$ python3 -m pip install phantom-typesExistem alguns extras disponíveis que podem ser usados para ativar um recurso ou instalar uma versão compatível de uma biblioteca de terceiros.
| Nome extra | Recurso |
|---|---|
[dateutil] | Instala o Python-Dateutil. Necessário para analisar cordas com TZAware e TZNaive . |
[phonenumbers] | Instala o PhoneNumbers. Necessário para usar phantom.ext.phonenumbers . |
[pydantic] | Instala Pydantic. |
[hypothesis] | Instala hipótese. |
[all] | Instala todos os itens acima. |
$ python3 -m pip install phantom-types[all]Ao introduzir um tipo fantasma, podemos definir uma pré-condição para um argumento de função.
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 } !" )Agora, esta será uma chamada válida.
greet ( Name . parse ( "Jane" ))... e isso vai.
joe = "Joe"
assert isinstance ( joe , Name )
greet ( joe )Mas isso produzirá um erro de verificação do tipo estático.
greet ( "bird" ) Para ficar claro, a razão pela qual o primeiro exemplo passa não é porque o verificador de tipo de alguma forma conhece magicamente sobre o nosso predicado, mas porque fornecemos a prova do verificador de tipo através da assert . Todo o verificador de tipo se importa é que o tempo de execução não pode continuar executando a afirmação, a menos que a variável seja um Name . Se movermos as chamadas como no exemplo abaixo, o verificador de tipo daria um erro para a chamada greet() .
joe = "Joe"
greet ( joe )
assert isinstance ( joe , Name )Ao combinar tipos de fantasmas com um verificador de tipo de tempo de execução como Beartype ou TypeGuard, podemos atingir o mesmo nível de segurança que você ganharia com o uso de contratos.
import datetime
from beartype import beartype
from phantom . datetime import TZAware
@ beartype
def soon ( dt : TZAware ) -> TZAware :
return dt + datetime . timedelta ( seconds = 10 ) A função soon agora validará que seu argumento e valor de retorno está ciente do fuso horário, por exemplo, pré e postagem.
Os tipos de fantasmas estão prontos para usar com o Pydantic e têm suporte integrado pronto para uso. As subclasses do trabalho Phantom com a validação da Pydantic e sua geração de esquema.
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 ))O código acima gera o seguinte 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 " ]
}Instale os requisitos de desenvolvimento, de preferência em um VirtualENV:
$ python3 -m pip install .[all,test,type-check]Executar testes:
$ pytest
# or
$ make testExecução do tipo de execução:
$ mypyLintes e formatados são configurados com ganso, depois de instalá -lo, você pode executá -lo como:
# run all checks
$ goose run --select=all
# or just a single hook
$ goose run mypy --select=allAlém da verificação do tipo estático, o projeto é configurado com plugins de mipy-mipia para testar que os tipos MyPy expostos funcionam conforme o esperado, essas verificações serão executadas em conjunto com o restante do conjunto de testes, mas você pode destacá-las com o comando a seguir.
$ make test-typing