4 ms·
Did you manage to get MyPy + Django to work together usefully? I tried the plugin you mentioned but it still seemed stymied by the dynamic nature of Django (rev
by rand_r 3y ago
Did you manage to get MyPy + Django to work together usefully? I tried the plugin you mentioned but it still seemed stymied by the dynamic nature of Django (reverse relations, etc), so I gave up on it.
If it’s actually possible to live in typed nirvana with Django I’ll bang my head against the wall some more.
We’re using Django 3.2 btw + FactoryBoy.
Actually there’s a number of annoyingly dynamic Python libraries out there where methods are created dynamically that it feels a bit like playing whack-a-mole. Is the situation like TypeScript where you need a MyLibrary.types.ts for each library?
- aleksanb 3y agoIt's quite useful on ci, and as a `make mypy` can run before pushing up your code, but for interactive errors we all use pyright, which is a bit of a letdown because you don't get autocomplete for fields and models accessed through reverse relation managers etc, pyright doesn't know about them. Many packages ship types nowadays, so the type coverage isn't too bad for us right now. Here's our plugin setup in mypy.ini in case this helps (Django 4.2 + drf 3.14) [mypy] plugins = mypy_django_plugin.main, mypy_drf_plugin.main ignore_missing_imports = True follow_imports = silent no_implicit_optional = True warn_unused_ignores = True check_untyped_defs = True disallow_untyped_defs = True disallow_untyped_calls = True warn_unreachable = True strict_equality = True allow_redefinition = True show_error_codes = True mypy_path = stubs [mypy.plugins.django-stubs] django_settings_module = 'mycompany.settings' with packages: mypy==1.6.0 django-stubs==4.2.4 django-stubs-ext==4.2.2 djangorestframework-stubs==3.14.3 with this horror of a regex in make (because you'll get drowned in wrong type errors in all of the untype files, and errors get shown from imports even if you don't care about that imported file), add more file targets as necessary: FILES_TO_MYPY = $(shell ls mycompany/\*/validators.py mycompany/\*/services.py mycompany/\*/selectors.py mycompany/\*/managers.py | sort | uniq) # 1)We have to grep out django-manager-missing like this until the following bug # is fixed: https://github.com/python/mypy/issues/12987. # 2) We grep out the line of `Found 95 errors in 16 files (checked 83 source # files)` that now appears as we use follow-imports: silent, because there's a # bug where errors from imported modules are counted against the total even # though they aren't emitted. If any real errors appear we get them as a # separate line anyways. .PHONY: mypy mypy: @{ MYPY_FORCE_COLOR=${NOT_CI} $(VENV)/bin/mypy --config-file mypy.ini $(FILES_TO_MYPY) 2>&3 | grep -v 'django-manager-missing\|errors in'; } 3>&1 | tee $(HYRE_TESTS_OUTPUT_PATH)/mypy.stdout.txt This allows you to get proper errors for things like model = MyModel.objects.get() othermodel = model.othermodel_set.first() reveal_type(othermodel) # correctly revealed to note: Revealed type is "Union[mycompany.importpath.models.OtherModel None]" and even errors on typos like model = MyModel.objects.get() othermodel = model.ooooothermodel_set.first() # revealed as MyModel has no attribute ooooothermodel_set, perhaps you ment othermodel_set .