Buenas tardes amigos. Y seguimos aumentando la intensidad del lanzamiento de nuevos cursos y ahora nos complace anunciar que las clases en el curso
"Desarrollador web en Python" comenzarán a fines de abril. En este sentido, tradicionalmente compartimos la traducción de material útil. Empecemos
Python es conocido por ser un lenguaje de escritura dinámico. Es muy fácil escribir marcos similares a DSL que son difíciles de analizar con herramientas de comprobación de tipos estáticos. A pesar de esto, con
las últimas innovaciones funcionales de
mypy , como
protocolos y
tipos literales , así como soporte básico para metaclases y descriptores, a menudo podemos obtener tipos exactos, pero aún es difícil evitar falsos positivos y otros factores negativos. Para resolver este problema y evitar la necesidad de personalizar el sistema de tipos para cada marco,
mypy admite un sistema de
complemento . Los complementos son módulos en Python que proporcionan
enlaces de complementos que
mypy llamará al verificar los tipos de clases y funciones que interactúan con una biblioteca o marco. Por lo tanto, es posible identificar con mayor precisión el tipo de la función devuelta, que de otro modo es extremadamente difícil de expresar, o generar automáticamente algunos métodos de clase para reflejar los efectos del decorador. Para obtener más información sobre la arquitectura del sistema de complemento y ver la lista completa de características, consulte la
documentación .
Complementos relacionados para la biblioteca estándarMypy viene con complementos predeterminados para implementar funciones y clases básicas, así como
ctypes
,
contextlib
y
dataclasses
. También incluye complementos para
attrs
(históricamente ha sido el primer complemento de terceros escrito para
mypy ). Estos complementos le permiten a
mypy determinar con mayor precisión los tipos y verificar correctamente el código para el tipo utilizando estas funciones de biblioteca. Para mostrar esto con un ejemplo, eche un vistazo a un fragmento 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')
Arriba, se llama a
get_class_decorator_hook()
cuando se define la clase. Esto agrega métodos generados automáticamente, incluido
__init__()
, al cuerpo de la función.
Mypy utiliza dicho constructor para calcular correctamente
TaggedVector[int]
como el tipo de
position
. Como puede ver en el ejemplo, los complementos funcionan incluso con clases genéricas.
Aquí hay otra pieza de código:
from contextlib import contextmanager @contextmanager def timer(title: str) -> Iterator[float]: ... with timer(9000) as tm: ...
Aquí
get_function_hook()
proporciona el tipo de retorno exacto para el decorador de
contextmanager
, por lo que las llamadas a la función decorada pueden verificarse para el cumplimiento de un tipo específico. Ahora
mypy puede reconocer el error: el argumento para
timer()
debería ser una cadena.
Una combinación de complementos y talonesAdemás de usar funciones dinámicas de Python, los marcos a menudo se encuentran con el problema de tener API grandes.
Mypy necesita archivos de
código auxiliar para que las bibliotecas prueben el código que usa estas bibliotecas (solo si la biblioteca no contiene anotaciones incorporadas, lo que no es tan común). La distribución de stubs para marcos grandes con
typehed no
es una práctica común:
- Typehed tiene un ciclo de liberación relativamente lento (enviado con mypy ).
- Los talones incompletos pueden provocar llamadas falsas, lo que será extremadamente difícil de evitar.
- No solo mezcle trozos de diferentes versiones con tipografía .
Los paquetes de código auxiliar presentados en
PEP 561 hacen lo siguiente:
- Los desarrolladores pueden lanzar paquetes de código auxiliar tantas veces como lo deseen.
- Los usuarios que no hayan elegido usar el paquete no verán falsos positivos.
- Puede instalar de forma segura versiones arbitrarias de varios paquetes de código auxiliar diferentes.
Además,
pip
permite combinar varios stubs para bibliotecas y los complementos
mypy correspondientes en una sola distribución. Los apéndices para el marco
mypy o el complemento correspondiente pueden desarrollarse fácilmente y agruparse en una distribución, lo cual es extremadamente útil ya que los complementos completan definiciones faltantes o inexactas en apéndices.
El último ejemplo de dicho paquete son los
stubs y el complemento SQLAlchemy , con el primer lanzamiento público de la versión 0.1, que se publicó hace algún tiempo en PyPI. A pesar de que este proyecto se encuentra en la versión Alpha inicial, podemos usarlo con seguridad en DropBox para mejorar la verificación de tipos. El complemento comprende las declaraciones básicas de 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)
En el fragmento de código anterior, el complemento usa
get_dynamic_class_hook()
para decirle a
mypy que Base es una clase base válida, incluso si no lo parece. Luego se llama a
get_base_class_hook()
para definir Usuario y agrega varios atributos generados automáticamente. A continuación, creamos una instancia del modelo:
user = User(id=42, name=42)
get_function_hook()
, por lo que
mypy puede indicar un error: se recibe un valor
integer
lugar del nombre de usuario.
Los apéndices definen
Column
como un descriptor
genérico , para que los atributos del modelo obtengan los tipos correctos:
id_col = User.id
Damos la bienvenida a los RP que agregan tipos más precisos a los apéndices (
aquí se realiza un seguimiento del progreso de los módulos principales).
Aquí hay algunas trampas que descubrimos mientras trabajábamos en enchufes:
- Use
__getattr__()
para evitar falsos positivos en las primeras etapas cuando no se completen los apéndices (esto evita errores mypy si faltan atributos del módulo). También puede usar esto en archivos __init__.py
si faltan submódulos. - Los descriptores a menudo ayudan con definiciones de tipo más precisas para el acceso a atributos personalizados (como en el ejemplo de Columna que revisamos anteriormente). El uso de descriptores está bien incluso si la implementación real del tiempo de ejecución utiliza un mecanismo más complejo, que incluye una metaclase, por ejemplo.
- Sin dudarlo, declare las clases marco como generalizadas. A pesar de que no son tales en tiempo de ejecución, esta técnica le permite determinar con mayor precisión el tipo de algunos elementos del marco, mientras que los errores de tiempo de ejecución pueden eludirse fácilmente. (Esperamos que los marcos agreguen gradualmente soporte incorporado para tipos genéricos, heredando explícitamente las clases correspondientes de
typing.Generic
).
Complementos mypy lanzados recientementeYa hay varios complementos disponibles para los populares marcos de Python. Además del complemento
SQLAlchemy mencionado anteriormente, otros paquetes de muestra notables con
apéndices y el complemento
mypy incorporado incluyen
apéndices para las interfaces
Django y
Zope . Se está trabajando activamente en estos proyectos.
Instalar y conectar stub y paquetes de complementosUse pip para instalar el paquete de complemento para
mypy y / o stub en un entorno virtual donde
mypy ya
está instalado :
$ pip install sqlalchemy-stubs
Mypy detectará automáticamente los talones instalados. Para conectar los complementos instalados, inclúyalos directamente en mypy.ini (o en el archivo de configuración del usuario):
[mypy] plugins = sqlmypy, mypy_django_plugin.main
Desarrollo de complementos
mypy y talones de escritura
Si desea desarrollar un paquete de apéndices y complementos para el marco que usa, podemos usar
el repositorio sqlalchemy-stubs como plantilla. Incluye un
setup.py
, pruebas de infraestructura con pruebas basadas en datos y una clase de complemento de ejemplo con un conjunto de ganchos para el complemento (ganchos de complemento). Recomendamos usar
stubgen para generar automáticamente los stubs que vienen con
mypy para comenzar a usarlos.
Stubgen
ha mejorado un
mypy 0.670
en
mypy 0.670
.
Consulte la
documentación si desea obtener más información sobre el
sistema de complementos
mypy . También puede buscar en Internet los códigos fuente de los complementos discutidos en el artículo. Si tiene preguntas, puede hacerlas
aquí .
El 15 de abril será un
seminario web abierto gratuito sobre el curso, que será realizado por uno de los organizadores de la comunidad de Python de Moscú:
Vladimir Filonov , regístrese, será interesante. Y ahora estamos esperando sus comentarios sobre el material traducido.