Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Typing Django
Search
Sobolev Nikita
March 27, 2020
Programming
0
320
Typing Django
Sobolev Nikita
March 27, 2020
Tweet
Share
More Decks by Sobolev Nikita
See All by Sobolev Nikita
Михаил Гурбанов – Are you NATS? @ PythoNN
sobolevn
0
42
Дмитрий Бровкин – Почему исправление опечаток сложнее, чем кажется, и как мы с этим српавляемся @ PythoNN
sobolevn
0
29
Алексей Гончарук – Современный веб с темлейтами @ PythoNN
sobolevn
0
90
Алексей Голобурдин – Демистификация PostgreSQL-индексов @ PythoNN
sobolevn
0
110
PythoNN – Александр Гончаров
sobolevn
0
59
PythoNN – Андрей Пронин
sobolevn
0
110
PythoNN: Василий Рябов – "Парсинг бинарных данных с помощью ctypes, или пишем на питоне как на Си"
sobolevn
0
220
GitHub Planet - OpenSource
sobolevn
0
260
Polymorphism and Typeclasses
sobolevn
2
150
Other Decks in Programming
See All in Programming
AWS Summit Hong Kong 2025: Reinventing Programming - How AI Transforms Our Enterprise Coding Approach
dwchiang
0
130
REALITY コマンド作成チュートリアル
nishiuriraku
0
120
プロダクトエンジニアのしごと 〜 受託 × 高難度を乗り越えるOptium開発 〜
algoartis
0
200
GitHub Copilot for Azureを使い倒したい
ymd65536
1
330
実践Webフロントパフォーマンスチューニング
cp20
45
10k
Flutterでllama.cppをつかってローカルLLMを試してみた
sakuraidayo
0
140
In geheimer Mission: AI Agents entwickeln
joergneumann
0
110
生成AIで知るお願いの仕方の難しさ
ohmori_yusuke
1
110
ComposeでWebアプリを作る技術
tbsten
0
130
Носок на сок
bo0om
0
1.2k
KANNA Android の技術的課題と取り組み
watabee
0
210
読書シェア会 vol.4 『ダイナミックリチーミング 第2版』
kotaro666
0
110
Featured
See All Featured
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
280
13k
Stop Working from a Prison Cell
hatefulcrawdad
268
20k
Typedesign – Prime Four
hannesfritz
41
2.6k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
105
19k
KATA
mclloyd
29
14k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
49k
YesSQL, Process and Tooling at Scale
rocio
172
14k
StorybookのUI Testing Handbookを読んだ
zakiyama
30
5.7k
Bootstrapping a Software Product
garrettdimon
PRO
307
110k
Making the Leap to Tech Lead
cromwellryan
133
9.3k
Git: the NoSQL Database
bkeepers
PRO
430
65k
Music & Morning Musume
bryan
47
6.5k
Transcript
Никита Соболев github.com/sobolevn
>_ X Типизация Django
Зачем?
Затем!
Затем! > Легче навигация по коду
Затем! > Легче навигация по коду > Быстрее обратная связь
Затем! > Легче навигация по коду > Быстрее обратная связь
> Совпадает с остальным стеком
>_ X Проблемы
А их много:
А их много: > Гигантская (и плохая) кодовая база без
типов
А их много: > Гигантская (и плохая) кодовая база без
типов > Нет прав на её редактирование (!)
А их много: > Гигантская (и плохая) кодовая база без
типов > Нет прав на её редактирование (!) > Куча магии
А их много: > Гигантская (и плохая) кодовая база без
типов > Нет прав на её редактирование (!) > Куча магии > Нет поддержки нового API типизации
>_ X Аннотация кода
MonkeyType github.com/Instagram/MonkeyType
from some.module import add add(1, 2)
monkeytype run myscript.py monkeytype stub some.module
def add(a: int, b: int) -> int: ...
None
И волонтеры!
None
None
Тысячи их! Спасибо.
>_ X Плагин для mypy
class User(models.Model): score = models.IntegerField()
class User(models.Model): score = models.IntegerField(null=True)
User.objects.filter(score=1) # ok! User.objects.filter(score__exact=1) # ok! User.objects.filter(score__exact='1') # Expected: int,
specified: str
django-stubs умеет почти все!
Чего не умеет?
Чего не умеет? > `QuerySet.as_manager()`
Чего не умеет? > `QuerySet.as_manager()` > Известные баги с `Manager.from_queryset()`
Чего не умеет? > `QuerySet.as_manager()` > Известные баги с `Manager.from_queryset()`
> Поддержка нескольких версий Django
Фичи!
class Blog(models.Model): title = models.CharField() num_posts = models.IntegerField(null=True) Blog.objects.values('title').get() #
type: TypedDict({'title': builtins.str}) blog: Blog blog.num_posts # type: Optional[int]
Как оно внутри?
def _callback(ctx: FunctionContext) -> mypy.types.Type: return AnyType() class _ExamplePlugin(Plugin): def
get_function_hook( self, fullname: str, ) -> Optional[Callable]: if fullname == 'django.db.models.fields.CharField': return _callback def plugin(version: str) -> Type[Plugin]: """Plugin's public API and entrypoint.""" return _ExamplePlugin
def _callback(ctx: FunctionContext) -> mypy.types.Type: return AnyType() class _ExamplePlugin(Plugin): def
get_function_hook( self, fullname: str, ) -> Optional[Callable]: if fullname == 'django.db.models.fields.CharField': return _callback def plugin(version: str) -> Type[Plugin]: """Plugin's public API and entrypoint.""" return _ExamplePlugin
def _callback(ctx: FunctionContext) -> mypy.types.Type: return AnyType() class _ExamplePlugin(Plugin): def
get_function_hook( self, fullname: str, ) -> Optional[Callable]: if fullname == 'django.db.models.fields.CharField': return _callback def plugin(version: str) -> Type[Plugin]: """Plugin's public API and entrypoint.""" return _ExamplePlugin
Ответственность плагина > Уточнение типов > Добавление магических атрибутов >
Прочая дичь!
django.setup()
Хотите глубже?
Как глубока кроличья нора?
Как глубока кроличья нора? > https://mypy.readthedocs.io/en/ stable/extending_mypy.html
Как глубока кроличья нора? > https://mypy.readthedocs.io/en/ stable/extending_mypy.html > https://github.com/typeddjango/ django-stubs/blob/master/
mypy_django_plugin/main.py
>_ X Тестирование типизации
None
None
None
# pytest-mypy-plugins # ./typesafety/test_first.yml - case: test_first main: | from
myapp import a reveal_type(a(1)) # N: Revealed type is 'builtins.float*' files: - path: myapp.py content: | def a(num: int) -> float: return float(num)
>_ X Будущее
Есть хорошие новости
None
Есть интересные новости
if DJANGO_3_0: ... # type specific for 3.0 else: ...
# type specific for other versions
Есть плохие новости
from django.models import QuerySet from myapp.models import User def filter_active_users()
-> QuerySet[User]: return User.objects.filter(is_active=True)
from django.models import QuerySet from myapp.models import User def filter_active_users()
-> 'QuerySet[User]': return User.objects.filter(is_active=True)
None
None
>_ X Попробуй!
github.com/wemake- services/wemake- django-template
>_ X Выводы
Сегодня мы многое поняли
Но что?
Но что? > Типизация – тяжело налазит на магию
Но что? > Типизация – тяжело налазит на магию >
Есть инструменты, которые помогут портировать нетипизированный проект в новый мир
Но что? > Типизация – тяжело налазит на магию >
Есть инструменты, которые помогут портировать нетипизированный проект в новый мир > Плагины справятся со всем остальным!
Что осталось за кадром?
Что осталось за кадром? > SemAnal / NewSemAnal
Что осталось за кадром? > SemAnal / NewSemAnal > Incremental
mode
Что осталось за кадром? > SemAnal / NewSemAnal > Incremental
mode > dmypy
Что осталось за кадром? > SemAnal / NewSemAnal > Incremental
mode > dmypy > Боль и страдания
Ссылки
Ссылки > https://github.com/typeddjango/ django-stubs
Ссылки > https://github.com/typeddjango/ django-stubs > https://github.com/typeddjango/ djangorestframework-stubs
Ссылки > https://github.com/typeddjango/ django-stubs > https://github.com/typeddjango/ djangorestframework-stubs > https://github.com/typeddjango/ pytest-mypy-plugins
Еще (полезные!) ссылки
Еще (полезные!) ссылки > https://github.com/typeddjango/ awesome-python-typing
Еще (полезные!) ссылки > https://github.com/typeddjango/ awesome-python-typing > https://sobolevn.me/2019/08/ typechecking-django-and-drf
Еще (полезные!) ссылки > https://github.com/typeddjango/ awesome-python-typing > https://sobolevn.me/2019/08/ typechecking-django-and-drf >
https://sobolevn.me/2019/08/ testing-mypy-types
Еще (полезные!) ссылки > https://github.com/typeddjango/ awesome-python-typing > https://sobolevn.me/2019/08/ typechecking-django-and-drf >
https://sobolevn.me/2019/08/ testing-mypy-types > https://sobolevn.me/2019/10/ testing-django-migrations
t.me/ opensource_findings 56
drylabs.io/py-quarantine
sobolevn.me Вопросы? github.com/sobolevn