Boa tarde amigos E continuamos a aumentar a intensidade do lançamento de novos cursos e agora temos o prazer de anunciar que as aulas no curso 
"Desenvolvedor da Web em Python" começarão no final de abril. A esse respeito, tradicionalmente compartilhamos a tradução de material útil. Vamos começar.
O Python é conhecido por ser uma linguagem de digitação dinâmica. É muito fácil escrever estruturas do tipo DSL que são difíceis de analisar com ferramentas de verificação de tipo estático. Apesar disso, com 
as mais recentes inovações funcionais 
do mypy , como 
protocolos e 
tipos literais , além de suporte básico para metaclasses e suporte a descritores, geralmente podemos obter tipos exatos, mas ainda é difícil evitar falsos positivos e outros fatores negativos. Para resolver esse problema e evitar a necessidade de personalizar o sistema de tipos para cada estrutura, o 
mypy suporta um sistema de 
plug-in . Plugins são módulos em Python que fornecem ganchos de plugins que o 
mypy chamará ao verificar os tipos de classes e funções que interagem com uma biblioteca ou estrutura. Assim, é possível distinguir com mais precisão o tipo da função retornada, que é extremamente difícil de expressar ou gerar automaticamente alguns métodos de classe para refletir os efeitos do decorador. Para saber mais sobre a arquitetura do sistema de plug-in e ver a lista completa de recursos, consulte a 
documentação .
 Plugins relacionados para a biblioteca padrãoO Mypy
Plugins relacionados para a biblioteca padrãoO Mypy vem com plugins padrão para implementar funções e classes básicas, bem como 
dataclasses ctypes , 
contextlib e 
dataclasses . Ele também inclui plugins para 
attrs (historicamente, foi o primeiro plug-in de terceiros 
criado para 
mypy ). Esses plugins permitem 
ao mypy determinar com mais precisão os tipos e verificar o código corretamente, usando essas funções da biblioteca. Para mostrar isso com um exemplo, dê uma olhada em um trecho de código:
 from dataclasses import dataclass from typing import Generic, TypeVar @dataclass class TaggedVector(Generic[T]): data: List[T] tag: str position = TaggedVector([0, 0, 0], 'origin') 
Acima, 
get_class_decorator_hook() é chamado quando a classe é definida. Isso adiciona métodos gerados automaticamente, incluindo 
__init__() , ao corpo da função. 
Mypy usa esse construtor para calcular corretamente 
TaggedVector[int] como o tipo de 
position . Como você pode ver no exemplo, os plugins funcionam mesmo com classes genéricas.
Aqui está outro pedaço de código:
 from contextlib import contextmanager @contextmanager def timer(title: str) -> Iterator[float]: ... with timer(9000) as tm: ... 
Aqui, 
get_function_hook() fornece o tipo de retorno exato para o decorador do 
contextmanager , para que as chamadas para a função decorada possam ser verificadas quanto à conformidade com um tipo específico. Agora 
mypy pode reconhecer o erro: o argumento para 
timer() deve ser uma string.
Uma combinação de plugins e stubsAlém de usar funções dinâmicas Python, as estruturas frequentemente enfrentam o problema de ter grandes APIs. 
Mypy precisa de arquivos 
stub para bibliotecas para testar o código que usa essas bibliotecas (apenas se a biblioteca não contiver anotações internas, o que não é tão comum). Distribuir stubs para grandes estruturas com 
datilografado não 
é uma prática comum:
- Typeshed tem um ciclo de liberação relativamente lento (enviado com mypy ).
- Os stubs incompletos podem levar a chamadas falsas, o que será extremamente difícil de evitar.
- Não basta misturar stubs de diferentes versões datilografadas .
Os pacotes de stub introduzidos no 
PEP 561 fazem o seguinte:
- Os desenvolvedores podem liberar pacotes stub quantas vezes quiserem.
- Os usuários que não optaram por usar o pacote não verão falsos positivos.
- Você pode instalar com segurança versões arbitrárias de vários pacotes stub diferentes.
Além disso, o 
pip permite combinar vários stubs para bibliotecas e os plugins 
mypy correspondentes em uma distribuição. Os 
stubs da estrutura 
mypy ou do plug-in correspondente podem ser facilmente desenvolvidos e agrupados em uma distribuição, o que é extremamente útil, pois os plug-ins preenchem definições ausentes ou imprecisas nos stubs.
O exemplo mais recente desse pacote é o 
stub e o plug-in SQLAlchemy , com o primeiro lançamento público da versão 0.1, publicado há algum tempo no PyPI. Apesar de esse projeto estar na versão Alpha inicial, podemos usá-lo com segurança no DropBox para melhorar a verificação de tipo. O plug-in entende as declarações básicas do ORM:
 from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String Base = declarative_base() class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(String) 
No trecho de código acima, o plug-in usa 
get_dynamic_class_hook() para informar ao 
mypy que Base é uma classe base válida, mesmo que não pareça. Em seguida, 
get_base_class_hook() é chamado para definir Usuário e adiciona vários atributos gerados automaticamente. Em seguida, criamos uma instância do modelo:
user = User(id=42, name=42)get_function_hook() chamado, então 
mypy pode indicar um erro: um valor 
integer é recebido em vez do nome de usuário.
Os stubs definem a 
Column como um descritor 
genérico , para que os atributos do modelo obtenham os tipos corretos:
 id_col = User.id  
Congratulamo-nos com PRs que adicionam tipos mais precisos aos stubs (o progresso dos módulos principais é rastreado 
aqui ).
Aqui estão algumas armadilhas que descobrimos ao trabalhar em plugues:
- Use __getattr__()para evitar falsos positivos nos estágios iniciais quando os stubs não forem concluídos (isso evita erros mypy se houver falta de atributos do módulo). Você também pode usar isso em arquivos__init__.pyse algum sub-módulo estiver ausente.
- Os descritores geralmente ajudam com definições de tipo mais precisas para acesso a atributos personalizados (como no exemplo da coluna que analisamos acima). O uso de descritores é bom, mesmo que a implementação real do tempo de execução use um mecanismo mais complexo, incluindo uma metaclasse, por exemplo.
- Sem hesitar, declare as classes de estrutura como generalizadas. Apesar do fato de que eles não são assim no tempo de execução, essa técnica permite determinar com mais precisão o tipo de alguns elementos da estrutura, enquanto os erros de tempo de execução podem ser facilmente contornados . (Esperamos que as estruturas adicionem gradualmente suporte typing.Genericpara tipos genéricos, herdando explicitamente as classes correspondentes datyping.Generic.)
Plugins mypy lançados recentementeJá existem vários plugins disponíveis para as estruturas populares do Python. Além do plug-in 
SQLAlchemy mencionado acima, outros pacotes de amostra dignos de nota com stubs e o plug-in 
mypy embutido incluem stubs para as interfaces 
Django e 
Zope . O trabalho ativo está em andamento nesses projetos.
Instalando e Conectando Pacotes de Stub e PluginsUse pip para instalar o pacote de plugins para 
mypy e / ou stub em um ambiente virtual em que 
mypy já 
esteja instalado :
  $ pip install sqlalchemy-stubs 
O Mypy detectará automaticamente os stubs instalados. Para conectar plug-ins instalados, inclua-os diretamente no mypy.ini (ou no arquivo de configuração do usuário):
 [mypy] plugins = sqlmypy, mypy_django_plugin.main 
Desenvolvendo plugins 
mypy e escrevendo stubs
Se você deseja desenvolver um pacote de stubs e plugins para a estrutura que você usa, podemos usar 
o repositório sqlalchemy-stubs como modelo. Ele inclui um 
setup.py , teste de infraestrutura usando testes controlados por dados e um exemplo de classe de plug-in com um conjunto de ganchos para o plug-in (ganchos de plug-in). Recomendamos o uso do 
stubgen para gerar automaticamente os stubs que acompanham o 
mypy para começar a usá-los. 
Stubgen melhorou um 
mypy 0.670 em 
mypy 0.670 .
Confira a 
documentação se você quiser saber mais sobre o 
sistema de plugins 
mypy . Você também pode pesquisar na Internet os códigos-fonte dos plug-ins discutidos no artigo. Se você tiver dúvidas, pode perguntar 
aqui .
O dia 15 de abril será um 
webinar gratuito e 
aberto sobre o curso, que será realizado por um dos organizadores da comunidade Python de Moscou - 
Vladimir Filonov , inscreva-se, será interessante. E agora estamos aguardando seus comentários sobre o material traduzido.