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
260
Typing Django
Sobolev Nikita
March 27, 2020
Tweet
Share
More Decks by Sobolev Nikita
See All by Sobolev Nikita
PythoNN – Александр Гончаров
sobolevn
0
39
PythoNN – Андрей Пронин
sobolevn
0
78
PythoNN: Василий Рябов – "Парсинг бинарных данных с помощью ctypes, или пишем на питоне как на Си"
sobolevn
0
180
GitHub Planet - OpenSource
sobolevn
0
220
Polymorphism and Typeclasses
sobolevn
2
110
New GitHub Features
sobolevn
0
46
Problems of static analysis in Python
sobolevn
0
110
Announcing typed-linter
sobolevn
0
200
About GitHub Stars
sobolevn
0
170
Other Decks in Programming
See All in Programming
今年のアップデートで振り返るCDKセキュリティのシフトレフト/2024-cdk-security-shift-left
tomoki10
0
190
良いユニットテストを書こう
mototakatsu
5
1.9k
20年もののレガシープロダクトに 0からPHPStanを入れるまで / phpcon2024
hirobe1999
0
130
開発者とQAの越境で自動テストが増える開発プロセスを実現する
92thunder
1
180
あれやってみてー駆動から成長を加速させる / areyattemite-driven
nashiusagi
1
200
CSC305 Lecture 26
javiergs
PRO
0
140
短期間での新規プロダクト開発における「コスパの良い」Goのテスト戦略」 / kamakura.go
n3xem
2
170
MCP with Cloudflare Workers
yusukebe
2
220
なまけものオバケたち -PHP 8.4 に入った新機能の紹介-
tanakahisateru
1
120
コンテナをたくさん詰め込んだシステムとランタイムの変化
makihiro
1
120
Monixと常駐プログラムの勘どころ / Scalaわいわい勉強会 #4
stoneream
0
270
rails stats で紐解く ANDPAD のイマを支える技術たち
andpad
1
290
Featured
See All Featured
What's in a price? How to price your products and services
michaelherold
243
12k
Keith and Marios Guide to Fast Websites
keithpitt
410
22k
Side Projects
sachag
452
42k
Mobile First: as difficult as doing things right
swwweet
222
9k
Automating Front-end Workflow
addyosmani
1366
200k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
229
52k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
10
810
Documentation Writing (for coders)
carmenintech
66
4.5k
Docker and Python
trallard
42
3.1k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
365
25k
Practical Orchestrator
shlominoach
186
10k
A Modern Web Designer's Workflow
chriscoyier
693
190k
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