Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Typing Django

Typing Django

8c3a2ebf7c2b84f8390d99c7bf8c8a48?s=128

Sobolev Nikita

March 27, 2020
Tweet

Transcript

  1. Никита Соболев github.com/sobolevn

  2. >_ X Типизация Django

  3. Зачем?

  4. Затем!

  5. Затем! > Легче навигация по коду

  6. Затем! > Легче навигация по коду > Быстрее обратная связь

  7. Затем! > Легче навигация по коду > Быстрее обратная связь

    > Совпадает с остальным стеком
  8. >_ X Проблемы

  9. А их много:

  10. А их много: > Гигантская (и плохая) кодовая база без

    типов
  11. А их много: > Гигантская (и плохая) кодовая база без

    типов > Нет прав на её редактирование (!)
  12. А их много: > Гигантская (и плохая) кодовая база без

    типов > Нет прав на её редактирование (!) > Куча магии
  13. А их много: > Гигантская (и плохая) кодовая база без

    типов > Нет прав на её редактирование (!) > Куча магии > Нет поддержки нового API типизации
  14. >_ X Аннотация кода

  15. MonkeyType github.com/Instagram/MonkeyType

  16. from some.module import add add(1, 2)

  17. monkeytype run myscript.py monkeytype stub some.module

  18. def add(a: int, b: int) -> int: ...

  19. None
  20. И волонтеры!

  21. None
  22. None
  23. Тысячи их! Спасибо.

  24. >_ X Плагин для mypy

  25. class User(models.Model): score = models.IntegerField()

  26. class User(models.Model): score = models.IntegerField(null=True)

  27. User.objects.filter(score=1) # ok! User.objects.filter(score__exact=1) # ok! User.objects.filter(score__exact='1') # Expected: int,

    specified: str
  28. django-stubs умеет почти все!

  29. Чего не умеет?

  30. Чего не умеет? > `QuerySet.as_manager()`

  31. Чего не умеет? > `QuerySet.as_manager()` > Известные баги с `Manager.from_queryset()`

  32. Чего не умеет? > `QuerySet.as_manager()` > Известные баги с `Manager.from_queryset()`

    > Поддержка нескольких версий Django
  33. Фичи!

  34. 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]
  35. Как оно внутри?

  36. 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
  37. 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
  38. 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
  39. Ответственность плагина > Уточнение типов > Добавление магических атрибутов >

    Прочая дичь!
  40. django.setup()

  41. Хотите глубже?

  42. Как глубока кроличья нора?

  43. Как глубока кроличья нора? > https://mypy.readthedocs.io/en/ stable/extending_mypy.html

  44. Как глубока кроличья нора? > https://mypy.readthedocs.io/en/ stable/extending_mypy.html > https://github.com/typeddjango/ django-stubs/blob/master/

    mypy_django_plugin/main.py
  45. >_ X Тестирование типизации

  46. None
  47. None
  48. None
  49. # 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)
  50. >_ X Будущее

  51. Есть хорошие новости

  52. None
  53. Есть интересные новости

  54. if DJANGO_3_0: ... # type specific for 3.0 else: ...

    # type specific for other versions
  55. Есть плохие новости

  56. from django.models import QuerySet from myapp.models import User def filter_active_users()

    -> QuerySet[User]: return User.objects.filter(is_active=True)
  57. from django.models import QuerySet from myapp.models import User def filter_active_users()

    -> 'QuerySet[User]': return User.objects.filter(is_active=True)
  58. None
  59. None
  60. >_ X Попробуй!

  61. github.com/wemake- services/wemake- django-template

  62. >_ X Выводы

  63. Сегодня мы многое поняли

  64. Но что?

  65. Но что? > Типизация – тяжело налазит на магию

  66. Но что? > Типизация – тяжело налазит на магию >

    Есть инструменты, которые помогут портировать нетипизированный проект в новый мир
  67. Но что? > Типизация – тяжело налазит на магию >

    Есть инструменты, которые помогут портировать нетипизированный проект в новый мир > Плагины справятся со всем остальным!
  68. Что осталось за кадром?

  69. Что осталось за кадром? > SemAnal / NewSemAnal

  70. Что осталось за кадром? > SemAnal / NewSemAnal > Incremental

    mode
  71. Что осталось за кадром? > SemAnal / NewSemAnal > Incremental

    mode > dmypy
  72. Что осталось за кадром? > SemAnal / NewSemAnal > Incremental

    mode > dmypy > Боль и страдания
  73. Ссылки

  74. Ссылки > https://github.com/typeddjango/ django-stubs

  75. Ссылки > https://github.com/typeddjango/ django-stubs > https://github.com/typeddjango/ djangorestframework-stubs

  76. Ссылки > https://github.com/typeddjango/ django-stubs > https://github.com/typeddjango/ djangorestframework-stubs > https://github.com/typeddjango/ pytest-mypy-plugins

  77. Еще (полезные!) ссылки

  78. Еще (полезные!) ссылки > https://github.com/typeddjango/ awesome-python-typing

  79. Еще (полезные!) ссылки > https://github.com/typeddjango/ awesome-python-typing > https://sobolevn.me/2019/08/ typechecking-django-and-drf

  80. Еще (полезные!) ссылки > https://github.com/typeddjango/ awesome-python-typing > https://sobolevn.me/2019/08/ typechecking-django-and-drf >

    https://sobolevn.me/2019/08/ testing-mypy-types
  81. Еще (полезные!) ссылки > 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
  82. t.me/ opensource_findings 56

  83. drylabs.io/py-quarantine

  84. sobolevn.me Вопросы? github.com/sobolevn