Model.objects is only available on classes and while we cannot force this, without ClassVar it's kind of only available on instances.
I have noticed this when I was writing a Jedi plugin that makes django-stubs work properly.
* Add lots of missing argument & return type hints
Discovered by setting mypy options disallow_untyped_defs, disallow_incomplete_defs.
* Sequence -> List
* Fixes from review
* Drop ordering_field
* Revert ModelBackend.with_perm
* typing_extensions.TypedDict instead
* bla
* Remove private method _get_lines_from_file
* A few additions
* Hints for BaseSpatialFeatures
* Add test for both issue cases
* Use generic type and add new django 4.1 `get_latest_lastmod` method
* Add Sitemap to monkeypatch
* Update test case to use generic + add failing case
* Test GenericSitemap too
* Reparametrize managers without explicit type parameters
This extracts the reparametrization logic from #1030 in addition to
removing the codepath that copied methods from querysets to managers.
That code path seems to not be needed with this change.
* Use typevars from parent instead of base
* Use typevars from parent manager instead of base manager
This removes warnings when subclassing from something other than the
base manager class, where the typevar has been restricted.
* Remove unused imports
* Fix failed test
* Only reparametrize if generics are omitted
* Fix docstring
* Add test with disallow_any_generics=True
* Add an FAQ section and document disallow_any_generics behaviour
* Fix type of <fieldname>_id when using ForeignKey(to_field=)
Previously mypy_django_plugin would always use the field type of target
model's primary key, but `to_field` can refer to a different field type.
* Fixes
* More fixes
* Implement support for `<QuerySet>.as_manager()`
* fixup! Implement support for `<QuerySet>.as_manager()`
* fixup! fixup! Implement support for `<QuerySet>.as_manager()`
This fallback to value.__class__ seems to be doing more harm than
good; see #312 and #1162. Replace it with a clear error message that
suggests a way to fix the problem rather than incompletely papering
over it.
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
This fixes an error that occured during state serialization. Completely
unsure how to reproduce this in a test but it resolves a long-standing
prolem in our project at work at least.
* Broaden type annotation for verbose_name(_plural) to accept lazystr.
Fixes#1137.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
* Broaden type annotation for help_text to accept lazystr.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
* Broaden type annotation for ValidationError to accept lazystr.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
* Broaden type annotation for label to accept lazystr.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
* Add StrPromise and StrOrPromise aliases to django_stubs_ext.
We make StrPromise and StrOrPromise available via django_stubs_ext so
that conditional imports with TYPE_CHECKING is not required.
These aliases fall back to Promise or Union[str, Promise]
when not TYPE_CHECKING.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
Avoid getting stuck in an invariance pit. I don't think it makes sense
to mix two tuple with named group elements in same choices sequence(?).
This also changes the outermost container type to `Sequence` as e.g.
both `tuple` and `list` are supported.
* Reflect the deprecation of get_response being None.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
* Type get_response with a callback protocol.
Otherwise, calling `self.get_response(request)` in a subclass of
`MiddlewareMixin` runs into `Invalid self argument` error.
This is a workaround for https://github.com/python/mypy/issues/5485.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
The return type for calling `shorcuts.render` without providing a value
for the `permanent` kwarg was `HttpResponsePermanentRedirect`, while it
should be `HttpResponseRedirect`.
The reason is that the first two overloads of the type stub overlap for
the case of using the default argument. While `mypy` does issue an error
for this, it was previously ignored with the `# type: ignore` comment.
As the first overload annotates the function as having the return type
`HttpResponsePermanentRedirect`, this would make mypy assume that the
return type is that instead of `HttpResponseRedirect`.
Since calling `django.shortcuts.redirect` without providing an argument
for `permanent` is the same as calling it with a `Literal[False]`, as
the default value is a `False`, we can improve the stub by only
specifying the option to use the default argument (`= ...`) in the
second overload. This also removes the overlap in stub definitions,
meaning that the `# type: ignore` can now be removed.
This commit fixes#1138.
* Type the return value of lazy translation functions as Promise.
The return value of the lazy translation functions is a proxied
`Promise` object.
https://github.com/django/django/blob/3.2.6/django/utils/translation/__init__.py#L135-L221.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
* Mark unicode translation functions for deprecation.
https://docs.djangoproject.com/en/4.0/releases/4.0/#features-removed-in-4-0.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
* Add proxied functions for Promise.
Although there is nothing defined in `Promise` itself, the only
instances of `Promise` are created by the `lazy` function, with magic
methods defined on it.
https://github.com/django/django/blob/3.2.6/django/utils/functional.py#L84-L191.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
* Add _StrPromise as a special type for Promise objects for str.
This allows the user to access methods defined on lazy strings while
still letting mypy be aware of that they are not instances of `str`.
The definitions for some of the magic methods are pulled from typeshed. We need
those definitions in the stubs so that `_StrPromise` objects will work properly
with operators, as refining operator types is tricky with the mypy
plugins API.
The rest of the methods will be covered by an attribute hook.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
* Implement _StrPromise attribute hook.
This implements an attribute hook that provides type information for
methods that are available on `builtins.str` for `_StrPromise` except
the supported operators. This allows us to avoid copying stubs from the
builtins for all supported methods on `str`.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
* Allow message being a _StrPromise object for RegexValidator.
One intended usage of lazystr is to postpone the translation of the
error message of a validation error. It is possible that we pass a
Promise (specifically _StrPromise) and only evaluate it when a
ValidationError is raised.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
* Refactor _StrPromise attribtue hook with analyze_member_access.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
* Use inherited types from CsrfViewMiddleware.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
* Define decorators generated from middleware with TypeVars.
csrf_protect and etc. are created via the decorator_from_middleware
helper, which doesn't modify the original signature of the wrapped view
function. Using TypeVar helps preserve the original type of the
decorated callable.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
* Fix CI
* Fix CI
* Fix CI
* Fix CI
* APply black
* APply black
* Fix mypy
* Fix mypy errors in django-stubs
* Fix format
* Fix plugin
* Do not patch builtins by default
* Fix mypy
* Only run mypy on 3.10 for now
* Only run mypy on 3.10 for now
* WHAT THE HELL
* Enable strict mode in mypy
* Enable strict mode in mypy
* Fix tests
* Fix tests
* Debug
* Debug
* Fix tests
* Fix tests
* Add TYPE_CHECKING debug
* Caching maybe?
* Caching maybe?
* Try explicit `${{ matrix.python-version }}`
* Remove debug
* Fix typing
* Finally
* Allow passing heterogeneous list or tuple to RunSQL.
The sqls to be executed do not necessarily need to be a homogeneous list
or tuple containing only lists or tuples or strs. It can be a mix of
everything.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
* Support passing dict as a sql param.
The 2-item tuple for `sql` can have a `dict` as the second item
for parameters. This behavior is the same as using
`cursor.execute` for backends except SQLite.
Relevant implementation:
5f76002500/django/db/migrations/operations/special.py (L119-L133)
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
* Add a test case for RunSQL.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
This fixes the CI starting occur on #1086 and following PRs due to the release
of Django 4.1 (https://docs.djangoproject.com/en/4.1/releases/4.1/) which
shipped the change
# Even if this relation is not to pk, we require still pk value.
# The wish is that the instance has been already saved to DB,
# although having a pk value isn't a guarantee of that.
if self.instance.pk is None:
raise ValueError(
f"{instance.__class__.__name__!r} instance needs to have a primary "
f"key value before this relationship can be used."
)
in https://github.com/django/django/pull/15318.
Custom `Lookup` implementation will run into
'Missing type parameters for generic type "Lookup"' without having
`Lookup` monkey-patched with django-stubs-ext.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
* Fix overloads in finders
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
* Remove PathLike from finders
Django really requires these paths to be str. For example, in
FileSystemFinder, .find(path) calls .find_location(…, path, …) which
evaluates path.startswith(prefix) and path[len(prefix) :]; these don’t
work on arbitrary PathLike objects.
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
* Improve typing for unresolved managers
This changes the logic when encountering an unresolvable manager class.
Instead of adding it as a `Manager` we create a subclass of `Manager`
that has `fallback_to_any=True` set. Similarly a `QuerySet` class is
created that also has fallbacks to `Any`. This allows calling custom
methods on the manager and querysets without getting type errors.
* Fix manager created and improve a test
* Fix row type of FallbackQuerySet
Because this inherits from _QuerySet, not QuerySet, it needs to have two
parameters
* Add support for inline from_queryset in model classes
This adds support for calling <Manager>.from_queryset(<QuerySet>)()
inline in models, for example like this:
class MyModel(models.Model):
objects = MyManager.from_queryset(MyQuerySet)()
This is done by inspecting the class body in the transform_class_hook
* Fix missing methods on copied manager
* Add test and other minor tweaks
* Always create manager at module level
When the manager is added at the class level, which happened when it was
created inline in the model body, it's not possible to retrieve the
manager again based on fullname. That lead to problems with inheritance
and the default manager.
* Annotate the return type of as_sql for SpatialOperator.
Its subclasses inherits the type annotation from `SpatialOperator`, so
copying `as_sql` over is unnecessary.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
* Remove unnecessary as_sql definition.
`Query` inherits `as_sql` from `BaseExpression`, `GISLookup` inherits
`as_sql` from `Lookup`, and `BuiltinLookup` inherits `as_sql` from
`Lookup[_T]`. None is required to be redefined.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
* Unify return types of as_sql and friends as _AsSqlType.
`Tuple[str, _ParamsT]`, `Tuple[str, List[Union[str, int]]]` and other
similar type annotations are all replaced with the `_AsSqlType`
alias. Any as_sql definition that annotate the return type as `Any` is also
updated to use `_AsSqlType`.
Signed-off-by: Zixuan James Li <p359101898@gmail.com>
* Add generic monkeypatching for `FileProxyMixin`.
This fixes `TypeError: 'type' object is not subscriptable` for
`django.core.files.File` and `django.core.files.base.ContentFile`.
* Add generic monkeypatching for `ForeignKey`.
This matches the change coming in Django 4.1.
See https://github.com/django/django/pull/15571
* Add test case reproducing Sequence name not defined issue
* Resolve all manager methods as attribute
This changes to logic for resolving methods from the base QuerySet class
on managers from copying the methods to use the attribute approach
that's already used for methods from custom querysets. This resolves the
phantom type errors that stem from the copying.
* Disable cache in test case
Make sure the test will fail regardless of which mypy.ini file is being using.
Co-authored-by: Petter Friberg <petter@5monkeys.se>
* Update comments related to copying methods
* Use a predefined list of manager methods to update
The list of manager methods that returns a queryset, and thus need to
have it's return type changed, is small and well defined. Using a
predefined list of methods rather than trying to detect these at runtime
makes the code much more readable and probably faster as well.
Also add `extra()` to the methods tested in
from_queryset_includes_methods_returning_queryset, and sort the methods
alphabetically.
* Revert changes in .github/workflows/tests.yml
With cache_disable: true on the test case this is no longer needed to
reproduce the bug.
* Remove unsued imports and change type of constant
- Remove unused imports left behind
- Change MANAGER_METHODS_RETURNING_QUERYSET to Final[FrozenSet[str]]
* Import Final from typing_extensions
Was added in 3.8, we still support 3.7
* Sort imports properly
* Remove explicit typing of final frozenset
Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
* Add comment for test case
* Fix typo
* Rename variable
Co-authored-by: Petter Friberg <petter@5monkeys.se>
Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
In addition to str, PostgreSQL cursors accept the
psycopg2.sql.Composable type, which is useful for guarding against SQL
injections when building raw queries that can’t be parameterized in
the normal way (e.g. interpolating identifiers).
In order to avoid reintroducing a dependency on psycopg2, we define a
Protocol that matches psycopg2.sql.Composable.
Documentation: https://www.psycopg.org/docs/sql.html
Related: https://github.com/python/typeshed/pull/7494
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
Char fields with blank=True set should not be considered nullable in the
context of values() and values_list() querysets.
I'm also not a huge fan of the way these fields are made optional in the
constructur to the model classes, it feels like it would be better to
mark the arguments as having a default value, rather than allow sending
in None, but I'd rather keep this fix small and look at the overall
problem at a later point.
Pyright complains about `response.cookies` because the generic type isn't known. `str` may or may not be the correct type to use here. Something should be set here.
* Set type of default `django.core.cache` to `BaseCache`
- The previous type `ConnectionProxy` is just a proxy class, thus
revealing `Any` for _all_ cache methods
* fixup! Set type of default `django.core.cache` to `BaseCache`
If a django model has a Manager class that cannot be resolved statically
(if it is generated in a way where we cannot import it, like `objects =
my_manager_factory()`), we fallback to the default related manager, so
you at least get a base level of working type checking.
* Fix manager types scope
* Restore incremental mode and mention in developer docs
* Separate dev mypy config and regular one
* Document config files usage
* Move mypy version upper bound to a [compatible-mypy] extra
Due to a bug in mypy 0.940 (#870), we made two changes in #871:
• pinned mypy==0.931 in requirements.txt (for running our tests);
• bounded mypy<0.940 in setup.py (for downstream users).
After the mypy bug was quickly fixed upstream in 0.941, our setup.py
bound has been repeatedly raised but not removed (#886, #939, #973).
The only changes in those commits have been to the precise wording of
error messages expected in our tests. Those wording changes don’t
impact compatibility for downstream users, so it should be safe to go
back to allowing them to upgrade mypy independently.
Since mypy doesn’t yet guarantee backwards compatibility in the plugin
API (although in practice it has rarely been an issue), add a
django-stubs[compatible-mypy] extra for users who prefer a known-good
version of mypy even if it’s a little out of date.
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
* Update setup.py
Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
* Fix BaseModelFormSet.save_m2m: accept `self`
Before it would result in the following when calling it:
> Attribute function "save_m2m" with type "Callable[[], None]" does not accept self argument [misc]
* fixup! Fix BaseModelFormSet.save_m2m: accept `self`
- Updates test_model_field_classes_from_existing_locations to account
for the behaviour change in https://github.com/python/mypy/pull/12663
- Bumps the version of django-stubs for a new release
When fetching a related field in a values_list queryset Django will
return the object primary key, not model instances as was previously
what the mypy plugin assumed.
* Fix error when nesting OuterRef expressions
OuterRef(OuterRef("my_field")) is a valid expression in nested
subqueries. Mypy would complain that OuterRef was an incompatible type
because OuterRef is typed to only accept str.
* Only fix for OuterRef
* OuterRef is not guaranteed to be resolved to ResolvedOuterRef
* Fix type of min_value and max_value on DecimalField
These should at the very least allow Decimals. Technically you can send
in anything that's comparable to a Decimal, but I'm not sure if it makes
sense to allow floats. Could allow both ints and Decimals I guess?
* Allow ints and floats as well
* Update django-stubs/forms/fields.pyi
* Update django-stubs/forms/fields.pyi
Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
* Bump mypy to 0.95x
* Remove the * for inferred types
There was an upstream change (https://github.com/python/mypy/pull/12459)
to remove * from inferred types in the reveal_type output.
As we are asserting the * to exist, all the test cases are now failing
on the 0.950 release. Removing the expected * to mirror the upstream
behaviour change should resolve the test failures.
Since PR 909, SimpleTestCase.client.get() etc methods return a class that no longer derives from `HttpResponse`, but instead `HttpResponseBase`, the `assert*` methods taking response should be updated as well.
Discovered while trying to update djangorestframework-stubs to django-stubs as of master.
django-stubs still supports Python 3.7, but the `/` positional-only parameter syntax is supported only in Python 3.8+.
Not sure why this error wasn't caught in CI.
* Fix stubs related to `(Async)RequestFactory` and `(Async)Client`
* Revert incorrect removal.
* Allow set as `unique_together`, use shared type alias.
* Revert `Q.__init__` to use only `*args, **kwargs` to remove false-positive with `Q(**{...})`
* Add abstract methods to `HttpResponseBase` to create common interface.
* Remove monkey-patched attributes from `HttpResponseBase` subclasses.
* Add QueryDict mutability checks (+ plugin support)
* Fix lint
* Return back GenericForeignKey to `Options.get_fields`
* Minor fixup
* Make plugin code typecheck with `--warn-unreachable`, minor performance increase.
* Better types for `{unique, index}_together` and Options.
* Fix odd type of `URLResolver.urlconf_name` which isn't a str actually.
* Better types for field migration operations.
* Revert form.files to `MultiValueDict[str, UploadedFile]`
* Compatibility fix (#916)
* Do not assume that `Annotated` is always related to django-stubs (fixes#893)
* Restrict `FormView.get_form` return type to `_FormT` (class type argument). Now it is resolved to `form_class` argument if present, but also errors if it is not subclass of _FormT
* Fix CI (make test runnable on 3.8)
* Fix CI (make test runnable on 3.8 _again_)
* Add missing type for setup_databases
`django.test.utils` was seemingly missing the type for `setup_databases`.
This change resolves my issue locally. The type was copied directly from `django.test.runner`.
* Fix typecheck_tests runner
Co-authored-by: Xavier Francisco <xavier.n.francisco@gmail.com>
* Make module declaration precise.
* Make settings match real file.
* Replace `include` with import.
* Make types more specific.
* Replace `WSGIRequest` with `HttpRequest` where possible.
* Replace all `OrderedDict` occurrences with plain `Dict` (it is not used in Django 3.2 and later)
* Add fake datastructures for convenience: _PropertyDescriptor and _ListOrTuple now can live here. Added _IndexableCollection (often useful as alias for 'sequence or queryset')
* Actualize other datastructures.
* Rework MultiValueDict to reflect the fact that some methods can return empty list instead of value.
* Deprecate SafeText in favor of SafeString.
* Minor improvements to utils
* Disallow using str in TimeFormat and DateFormat, drop removed fmt `B`
* Do not let classproperty expect classmethod, make return value covariant.
* Sync with real file.
* Improve types for timezone.
* Sync deprecated, new and removed features in translation utils.
* Drop removed files, sync huge deprecations.
* Fix incompatible decorators (properties, contextmanagers)
* Rework pagination.
* Sync validators with real code. Add _ValidatorCallable for any external use (field validation etc.)
* Add shared type definitions (for fields of both forms and models). Actualize model fields. Mark keyword-only args explicitly in stubs (where code uses **kwargs). Disallow bytes for verbose_name.
* Make all checks return Sequence[CheckMessage] or subclass to be covariant.
* Add bidirectional references between backend.base and other files. Replace some Any's with specific types.
* Actualize db.migrations: remove removed methods, replace "None" annotations in wrong places, improve some wrong annotations.
* Actualize db.utils to match real file.
* Replace FileResponse and TemplateResponse with HttpResponse(Base) where needed: at least HttpResponseNotModified/HttpResponseRedirect can be returned instead of it, so annotation was wrong.
* Replace Any in forms where possible. Actualize class bases and method arguments.
* Improve typing of serializers.
* Actualize views, rename variable bound to Model to _M for consistency.
* Make types of file-related code consistent. Disallow using bytes as path, because many methods expect str-only paths. Make File inherit from IO[AnyStr] instead of IO[Any]: it makes impossible to instantiate file of union type, but allows precise types for some methods.
* Minor improvements: stop using None as annotation in wrong places, replace obvious Any's with precise types, actualize methods (missing/renamed/signature changed).
* Allow less specific containers, replace Any's with specific types.
* Improve types for requests and responses.
* Use AbstractBaseUser instead of User in auth.
* Use broader type for permission_required
* Use wider container types. Add 'type: ignore' to avoid issues with mypy.stubtest.
* Disallow using backend class as argument (it is passed to import_string).
* Add required methods to PasseordValidator.
* Allow using Path instance as argument.
* Actualize methods.
* Add 'type: ignore' to avoid issues with mypy.stubtest.
* Replace Any's with specific types and BaseForm with ModelForm.
* Actualize contrib.postgres
* Remove render_to_response, add 'get_absolute_url' to corresponding protocol.
* Actualize signers.
* Use precise types for handlers. Disallow str as stream type for LimitedStream.
* Exact types for ValidationError
* Replace wrong used Union with Sequence.
* Actualize static handlers.
* More specific types for admin. Fixes#874.
* Improve types and replace 'Tags' with str (it isn't Enum, so annotation was wrong).
* Replace Any with specific types, actualize signatures.
* Add async variants of handlers and clients. Use fake class to distinguish between request types in RequestFactory and AsyncRequestFactory.
* Fix signature, minor improvements.
* Actualize signatures and class names, replace Any with more specific types.
* Fix signature.
* Add some missing methods to Collector
* Combinable rarely returns Self type: almost always it's CombinedExpression.
* No Random in source anymore.
* Drop removed SimpleCol.
* Replace _OutputField with Field: nothing in docs about strings.
* Introduce reusable types, add missing methods. Remove strange types (probably created by stubgen). Remove RawQuery from Compiler: it obviously doesn't work with RawQuery.
* Use literal constants.
* Actualize base classes.
* Callable is not accepted by get_field.
* Add precise types.
* Use property and broader containers where possible. Add missing methods.
* Actualize indexes.
* More specific types for signals.
* Fix signatures, drop missing methods.
* Actualize window functions to match source.
* Actualize text functions, add missing methods, use type aliases for consistency.
* Add missing property decorators, methods and attributes. Use type aliases. Remove absent YearComparisonLookup and any SafeText references (they aren't related to lookups at all).
* Use bound TypeVar, mark all BuiltinLookup descendants as generic explicitly. Remove strange Union from Lookup.__init__
* Apply type alias, fix base class and argument name.
* Actualize BaseExpression methods.
* Fix imports.
* Add missing class and fix incompatible bases.
* Use same types in __init__ and attribute.
* OrderBy accepts F or Expression.
* Non-expressions are converted to Values.
* Add missing attributes.
* Add missing methods, fix 'None' argument type.
* Define properties where possible, remove 'None' argument annotations, remove inadequate type in make_immutable_fields_list.
* Remove absent QueryWrapper. Replace some Any with precise types.
* Fix wrong types and actualize signatures. Deny ManagerDescriptor.__get__ on model instances.
* Use more specific types.
* Arity can be None in subclasses.
* Reformat with black
* Make DeletionMixin generic.
* Fix wrong type variable in _RequestFactory.
* Fix variable name in signature.
* Disallow returning None from Form.clean()
* Allow again returning None from Form.clean
* Drop some unused imports.
* Add tests for MultiValueDict.
* Add tests for utils.timezone.
* Fix#834.
* Add more files to import_all test
* Allow None for `context_object_name`
* Fix CI
* Fix test to work on python 3.8
* Add reproducer for failing case
* Emit warning instead of crashing when encountering enum
* Remove prints, slightly tweak error message
* Remove unused import
* Run black and isort
* Run isort on .pyi file
* Remove unrelated issue from test case
* Fix missing related managers on some models
I was seeing an issue where some related managers were missing from some
models. Traced the issue down to this line, where it appears that if we
hit a relation with a non-default(?) reverse manager the iteration
stopped. I _think_ this is supposed to be a continue statement instead.
It appears to work in the project I'm working in at least.
* Add test case
* Add test case
* Set type parameters for Field in get_fields()
This fixes an issue with Pyright strict type checking where Pyright complains that the type parameters aren't known.
* Fix type parameters in other methods
* DatabaseClient: add missing class method `settings_to_cmd_args_env` and add missing arg to `runshell`
The `DatabaseClient.runshell()` was refactored in Django 3.2 to be more standardized
across the different database backends.
* DatabaseClient: make `settings_dict` dict type better by specifying key/value types
* tests: add missing db backend client files to `import_all_modules`
* _default_manager has more specific type for TypeVars
* remove unnecessary # type: ignore
* add test for _base_manager
* add overloads for classproperty.__get__
* readd # type: ignore for WSGIRequestHandler.connection, fails in github's pipeline
* fix _base_manager test: mypy reveals an inferred type
Co-authored-by: Michael Pöhle <michael.poehle@polyteia.de>
While `object_list` isn't defined at construction, `BaseListView.get()`
sets it when handling a request, so in practice it is defined whenever
a list view is doing its work.
The Django documentation describes `object_list` as "the list of
objects (usually, but not necessarily a queryset)", so I picked
`Sequence` as the type.
Closes#790
* Refactor to more easily support additional config options
* Notify when Manager.from_queryset happens inside model class body
- A warning will be emitted whenever `Manager.from_queryset` happens
inside of a model class body
* Resolve generated default manager types before final iteration
A default manager on a model should always exist, eventually. Although,
we extend to look through dynamically generated managers on each
iteration instead of deferring until the final iteration.
Instead of copying methods over from a QuerySet passed to a basemanager
when invoking '<BaseManager>.from_queryset', any QuerySet methods are
declared as attributes on the manager.
This allows us to properly lookup any QuerySet method types via a
'get_attribute_hook' and will thus remove disorienting phantom errors
occuring from mypy trying to resolve types only existing in the module
where the _original_ (and real) queryset method was declared.
The `extra_context` argument to `ModelAdmin.changeform_view`,
`add_view`, `change_view`, `changelist_view`, `delete_view`, and
`history_view` is used to pass extra context variables to a template, so
all of these arguments should have type `Optional[Dict[str, Any]]`.
Instead, these are currently typed as `Optional[Dict[str, bool]]`,
`Optional[Dict[str, str]]`, or `None`.
* Allow List[Tuple[Any]] as args_generator argument to format_html_join
format_html_join's args_generator argument can be anything that contains
tuples of things that can be coerced to strings or that have a
`__html__` method.
Fixes#721.
* Use `Iterable[Iterable[Any]]` as `args_generator` type
* Run linter
* Fix annotation of ModelAdmin.get_object
The type annotation in django-stubs indicated that the type of the
`from_field` argument to `ModelAdmin.get_object` should be `None`. In
fact, `None` is the default value of that argument. If the argument is
not `None`, [it is passed to a model's `_meta.get_field` method][impl], which
takes an argument of type `Union[Callable[..., Any], str`.
[impl]: ac5cc6cf01/django/contrib/admin/options.py (L767)
* Fix formatting
get_object's default implementation returns None but subclasses
are allowed to override this method and make it return anything.
The returned object would then be passed to other methods
to publish different data for different URL parameters.
https://docs.djangoproject.com/en/4.0/ref/contrib/syndication/
Django 3.2 introduced two new methods: `sign_object` and
`unsign_object` which can sign/unsign "complex data structures" such as
lists, tuples, dictionaries:
https://docs.djangoproject.com/en/3.2/topics/signing/#django.core.signing.TimestampSigner
Because the methods take an arbitrary serializer (a JSON serializer by
default, but not guaranteed), we cannot be sure of the type of `obj`.
* Correct the type of FileField.storage
This instance property can't be a callable. Although the FileField constructor
allows a callable, it is immediately resolved to an instance of Storage.
See: f5802a21c4/django/db/models/fields/files.py (L231-L235)
* Correct the type of FieldFile.storage
This instance property is copied directly from `FileField.storage` and should be
the same type.
See: f5802a21c4/django/db/models/fields/files.py (L21)
* Add failing test for relation to model inheriting `objects`
Fails with:
```
pytest_mypy_plugins.utils.TypecheckAssertionError: Invalid output:
Expected:
main:2: note: Revealed type is "myapp.models.MyUser*"
main:3: note: Revealed type is "myapp.models.MyUser*"
<45 (diff)
<45 (diff)
Actual:
main:2: note: Revealed type is "myapp.models.MyUser*"
main:3: note: Revealed type is "myapp.models.MyUser*"
main:6: error: "MyUser" has no attribute "book_set" (diff)
main:6: note: Revealed type is "Any" (diff)
main:7: error: "MyUser" has no attribute "article_set" (diff)
main:7: note: Revealed type is "Any" (diff)
```
* Make AddRelatedManagers look for "objects" on parent model
Previously, AddRelatedManagers would fail if a related model had inherited
its `objects` field from a parent class. This would result in missing
relation attributes. This is fixed by using `get()` instead of `names`;
the former searches the MRO for the symbol, whereas the latter only looks
for symbols declared directly on the class.
Needed, because `django-stubs-ext` generally has to specified as a
production dependency (to use the monkey patching). `django-stubs` does
have `typing-extensions` as a dependency, but it is often used only as a
dev dependency as it has not runtime functionality.
Resolves: https://github.com/typeddjango/django-stubs/issues/702
* Use `Sequence` instead of `Iterable` for `send_messages`.
According to the documentation
(https://docs.djangoproject.com/en/3.2/topics/email/#email-backends),
`email_messages` is a list. Using `Iterable` will make it hard for
subclasses to implement this method utilizing functions like `__len__`.
While this still allows subclasses to accept `Iterable`.
* Fix function signature of `authenticate` of `BaseBackend`.
1. BaseBackend no longer requires the username and password argument.
They were removed 3 years ago in the commit below when `BaseBackend` is added:
75337a6050
2. `request` is optional for `authenticate` method.
According to django documentation, the authenticate method does not
necessarily require the request object.
https://docs.djangoproject.com/en/3.2/topics/auth/default/#authenticating-users
* Tighten the type of `streaming_content` to `Iterator[bytes]`.
It is an iterator of a bytestring according to the documentation:
https://docs.djangoproject.com/en/3.2/ref/request-response/#django.http.StreamingHttpResponse.streaming_content
* Fix function signature of `django.contrib.staticfiles.serve`.
Since this `serve` function uses `django.views.static.serve` that
accepts `HttpRequest` as its first argument, it is more reasonable
to type it with `HttpRequest` instead of `WSGIRequest`.
Related:
https://github.com/django/django/blob/main/django/contrib/staticfiles/views.py#L39
* Fix `MyModel.objects.filter(...).my_method()`
* Fix regression: `MyModel.objects.filter(...).my_method()` no longer worked when using from_queryset
This also fixes the self-type of the copied-over methods of the manager generated by from_queryset.
Previously it was not parameterized by the model class, but used Any.
The handling of unbound types is not tested here as I have not been able to
find a way to create a test case for it. It has been manually tested
against an internal codebase.
* Remove unneeded defer.
This matches the actual implementation in Django, where it only attempts
to use the result of get_users() in a for loop, which allows for any
Iterable, and it provides a more flexible and idiomatic API for users
who subclass PasswordResetForm.
The `display` decorator is defined in `django.contrib.admin.decorators`, but
isn't included in `django.contrib.admin`, which is how the Django docs describe
its usage.
* Add accepts method to HttpRequest stubs
The accepts method (and dependencies) was missing in the stub for HttpRequest
* Change accepted_types to return correct type
* Fix Black formatting
* Add annotation for MediaType __init__ args
* Add datetime to set_type of DateTimeField
`DateTimeField` was missing `datetime` as a valid set type. But Django clearly accepts `datetime`.
* Fix test for DateTimeField type change
datetime is now a valid set type for DateTimeField
* QuerySet.annotate returns self-type. Attribute access falls back to Any.
- QuerySets that have an annotated model do not report errors during .filter() when called with invalid fields.
- QuerySets that have an annotated model return ordinary dict rather than TypedDict for .values()
- QuerySets that have an annotated model return Any rather than typed Tuple for .values_list()
* Fix .annotate so it reuses existing annotated types. Fixes error in typechecking Django testsuite.
* Fix self-typecheck error
* Fix flake8
* Fix case of .values/.values_list before .annotate.
* Extra ignores for Django 2.2 tests (false positives due to tests assuming QuerySet.first() won't return None)
Fix mypy self-check.
* More tests + more precise typing in case annotate called before values_list.
Cleanup tests.
* Test and fix annotate in combination with values/values_list with no params.
* Remove line that does nothing :)
* Formatting fixes
* Address code review
* Fix quoting in tests after mypy changed things
* Use Final
* Use typing_extensions.Final
* Fixes after ValuesQuerySet -> _ValuesQuerySet refactor. Still not passing tests yet.
* Fix inheritance of _ValuesQuerySet and remove unneeded type ignores.
This allows the test
"annotate_values_or_values_list_before_or_after_annotate_broadens_type"
to pass.
* Make it possible to annotate user code with "annotated models", using PEP 583 Annotated type.
* Add docs
* Make QuerySet[_T] an external alias to _QuerySet[_T, _T].
This currently has the drawback that error messages display the internal type _QuerySet, with both type arguments.
See also discussion on #661 and #608.
Fixes#635: QuerySet methods on Managers (like .all()) now return QuerySets rather than Managers.
Address code review by @sobolevn.
* Support passing TypedDicts to WithAnnotations
* Add an example of an error to README regarding WithAnnotations + TypedDict.
* Fix runtime behavior of ValuesQuerySet alias (you can't extend Any, for example).
Fix some edge case with from_queryset after QuerySet changed to be an
alias to _QuerySet. Can't make a minimal test case as this only occurred
on a large internal codebase.
* Fix issue when using from_queryset in some cases when having an argument with a type annotation on the QuerySet.
The mypy docstring on anal_type says not to call defer() after it.
* widen type of make_password's hasher
make_password will accept a subclass of BasePasswordHasher as a hasher
* widen get_hasher's algorithm type
get_hasher will accept (and immediately return) a BasePasswordHasher
Unlike `List`, which is invariant, `Sequence` is covariant, which lets
`path` accept lists of subsets of the `Union` as well.
I believe this is safe, as django doesn't mutate this input. I found
[this
comment](https://github.com/python/mypy/issues/3351#issuecomment-300447832)
helpful
Similar to the already patched `FormMixin`, the detail and list generic view classes are also missing __class_getitem__ and choke when you try to use their generics.
* Adds support for pyproject.toml files
Since mypy 0.900 the pyproject.toml files are supported.
This PR adds a support for it. It searchs for a `tool.django-stubs` section. This is an example configuration:
```
[tool.django-stubs]
django_settings_module = "config.settings.local"
```
Fixes#638
* Added TOML tests
* Use textwrap.dedent instead of trying to manually replace spaces
* Allow Collection for 'fields' and 'exclude' of form model helpers (#637)
There are several functions and classes in `django.forms.models` that
take a `fields` or `exclude` argument. Previously, `Sequence` was used
to annotate these, but the code of Django (I checked version 3.2.4)
doesn't require `__getitem__()` to be implemented, so requiring
`Collection` instead is sufficient.
The practical advantage of requiring `Collection` is that a set, such
as the key set of a dictionary, can be passed without first having to
convert it to a list or tuple.
* Pin mypy to below version 0.900
* Remove Callable for 'fields' and 'exclude' of form model helpers
I cannot find any support for callables for these two arguments in
the code or in the documentation.
* Update setup.py
Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
Add the missing attribute django.http.response.StreamingHttpResponse.streaming .
This is actually done by moving the attribute from HttpResponse to the base class HttpResponseBase.
The real Django source code declares this attribute on HttpResponse and StreamingHttpResponse, however that's only because Django doesn't have type hints. The right place for the type hint is on the base class HttpResponseBase, since all instances of that base class are actually instances of HttpResponse or StreamingHttpResponse or a subclass of those two classes. So it's guaranteed that every HttpResponseBase instance has the attribute.
Fixes bug #629.
* fix(ResolverMatch): Added _func_path
ResolverMatch class in Django contains _func_path variable and it will get initialized in init method whatever the condition, so it should be added in type stubs as well. https://github.com/django/django/blob/main/django/urls/resolvers.py#L48
* Update resolvers.pyi
Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
This monkey patching will only work when using Python 3.7+, which
introduced the `__class_getitem__` magic method. This tripped me up for
a while as I was on Python 3.6 and wondered why the monkey patching was
not working, therefore documenting this to point this out to future
readers.
* `django.db.{connection, connections, router}` are now hinted -- including `ConnectionHandler` and `ConnectionRouter` classes.
* Several improvements to `BaseDatabaseWrapper` attribute hints.
* In many places, database connections were hinted as `Any`, which I changed to `BaseDatabaseWrapper`.
* In a few places I added additional `SQLCompiler` hints.
* Minor tweaks to nearby code.
* Add type hints for the postgres CursorDebugWrapper, expand the BaseCursorDebugWrapper.
* Fix how Optinal gets applied.
* Fix optional handling further.
* Adjust postgres debugcursorwrapper to look more like the implementation.
* Apply review feedback.
* Use the more generic HttpResponseBase when appriopriate.
* Fix failing test and add new test.
* Remove the other test again, it was the wrong location. Add new tests in the correct location.
Co-authored-by: LanDinh <coding+sourcetree@khaleesi.ninja>
* Update decorators.pyi to match Django 3.1
This commit resembles the state of the file in Django 3.1. Unfortunately, this is not even compatible with Django 3.0 which misses the sync* and async* decorators.
* Update decorators.pyi
* Fixes lint
Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
* Ensure that all registered checks return a list of CheckMessage
This changes missing and Any return types on registered checks to always
return "List[CheckMessage]".
In many cases, check functions were already annotated to return in a more
specific type than CheckMessage (e.g. Error). In these cases, it's assumed
that the existing annotation is correct, and the more specific type is kept.
* Update model_checks.pyi
Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
* Replace models.Model annotations with type variables
* Adds generic type args to generic views
* Adds more tests
* Revert "Adds generic type args to generic views"
This reverts commit 6522f30cdb9027483f46d77167394c84eb7b7f4b.
* Adds Generic support for DetailView and ListView
Co-authored-by: sobolevn <mail@sobolevn.me>
This addresses an obscure crash we're getting when defining a GenericForeignKey
subclass on a model.
Not sure how this slipped through type checking since
`helpers.lookup_class_typeinfo -> Optional[TypeInfo]` while
`.get_private_descriptor_type(type_info: TypeInfo)` so this should be a clear
type violation.
* Add type hints for the postgres CursorDebugWrapper, expand the BaseCursorDebugWrapper.
* Fix how Optinal gets applied.
* Fix optional handling further.
* Adjust postgres debugcursorwrapper to look more like the implementation.
* Apply review feedback.
Co-authored-by: LanDinh <coding+sourcetree@khaleesi.ninja>
* Add URLPattern options to django.url.conf since they were missing.
* Fix some wording in the contribution guide & fix a reference to Django version 3.0, which has since been replaced by 3.1 as new stable version.
* My bad - I was misreading the type hints a bit here. Fix tests.
* We need to specify the List[Union[URLResolver, URLPattern]] upfront, since those don't accept List[URLResolver] as argument.
* Add test to ensure that path() accepts a mix of URLPatterns & URLResolvers.
Co-authored-by: LanDinh <coding+sourcetree@khaleesi.ninja>
Prior to this change, ManyToManyField was declared as being generic in
_ST and _GT, but also used the _T Typevar in its __init__ signature.
This caused mypy to add _T to the variables it was generic in when used
as an alias.
The symptom of this problem was that mypy would show an error with the
message "Type application has too few types (3 expected)" where a
ManyToManyField alias was declared, but adding an extra argument would
fail because the type only takes two arguments.
This change brings the signature of ManyToManyField in line with
ForeignKey and OneToOneField.
* Update static.pyi
Parameters document_root and show_indexes should be marked as Optional since they have a default value.
* Update static.pyi
Correct signature of serve function.
This incorporates all type information I could glean from loaddata at
django/django@adb40d217e.
- Remove `help` per review comment:
https://github.com/typeddjango/django-stubs/pull/536#discussion_r533179013
- Add `exclude_models` and `exclude_apps` based on the return type of
`..utils.parse_apps_and_model_labels`.
- Change `loaddata`'s `fixture_labels` to `Sequence` of `str` instead of
`Iterable` because in practice it's a tuple, but at a type level, the
important thing is that `loaddata` iterates over `fixture_labels` more than
once. General iterables (which include iterators) need not support iteration
more than once.
- Correct the return type of `parse_name` to account for the possibility that
the data and compression formats are `None`.
- Correct the return type of `find_fixtures` to be a list of the same type that
`parse_name` returns.
- Add a type annotation for `SingleZipReader.read`. Django implements the method
in a way that actually conflicts with `zipfile.ZipFile.read`'s type. This
necessitates a `type: ignore[override]` to keep the tests passing. Mypy is
correct that there is an override error, but Django's code is what it is.
(And that method's signature was introduced way back in Django version 1.1,
commit django/django@089ab18c025917f38a2e3731ae4024d4810df1ec.)
- Added some of the instance attributes from command arguments: ignore, using, app_label, verbosity, format.
- Added class attribute: help.
- Fixed return type of find_fixtures.
* run black
* create monkeypatching function for adding get_item dunder
* whoops i forgot the test
* change the name in INSTALLED_APPS to make test pass
* turn the whole thing into a proper package
* move django_stubs_ext to requirements.txt
* also install requirements.txt
* attempt to fix pre-commit
* numerous small code review fixes
* fix dependency issues
* small dependency fixes
* configure proper license file location
* add the rest of the monkeypatching
* use strict mypy
* update contributing with a note monkeypatching generics
* copy release script from parent package
* Add stubs for remaining commands in django.core.management.commands
* Tighten up stub definitions in django.core.management.commands
* Apply some missing declarations in django.core.management.commands
* change get_user to use a protocol requiring a session
define a "_HasSession" protocol, and update contrib.auth.get_user to use it
get_user only requires a session field, and idiomatic django testing frequently calls get_user with a TestClient
* run black
* use union for get_user instead of a protocol
* create tests for get_user typechecking
* properly import test client
* Add `is_active` field to `django.contrib.auth.AbstractBaseUser` model
* Favor defining type than setting concrete value
* Update type to reflect sub-class implementation
This also corrects the fact that "run_checks" only returns a concatenated list
of all registered check results, which may only contain CheckMessage:
302caa40e4/django/core/checks/registry.py (L60)
The Django API requires that registered checks take an "app_configs"
argument, which is a list of AppConfig. This is practically also passed by
keyword, so all parameters should be specified with a "= ..." to indicate
that they are keywords.
Django always passed "app_configs" as a list, but checks can accept and
use a more general more Sequence.
The Django API also requires that registered checks take "**kwargs".
This results in the canonical parameters of:
"app_configs: Optional[Sequence[AppConfig]] = ..., **kwargs: Any"
* make BaseModelAdmin generic to properly type the `obj` argument of ModelAdmin.delete_model
closes#482
* turn BaseModelAdmin into bound generic, run black
* add test for generic ModelAdmin
* Allow overridable checks to be CheckMessage
The checks framework expects return types to be "List[CheckMessage]". This
allows all overridable checks-returning methods to return the more general
"CheckMessage", instead of the "Error" subclass.
* Ignore an incorrect usage of the checks API in Django 2.2
These functions were added in Django 2.0, but the stubs have been
incomplete since commit 9a68263257
The implementation is almost identical to `url()` from
`conf/urls/__init__.pyi`
* Allows FileField storage to be a Callable
The `storage` parameter of `FileField` (and by extension `ImageField`)
is not limited to just taking an instance of `Storage`. It can also take
a no-args callable that returns an instance of `Storage`.
* correcting linting issue in forms.pyi
* Output a more clear configuration error
* Performance related improvements in config read handling
* Check python 3.6 with travis
* Revert the .travis.yml py36 inclusion
* Added tests for input error handling
* Thanks isort, isorted it out
* Make exit() function a bit more aesthetic
* Single quote -> double quote docstrings
* Whitespace removed
Sending in a single string leads to unexpected behavior and the method
accepts any iterable, not just sequences, of strings.
Technically sending in a single string is still allowed because a string
is an iterable of strings, but this way the intention of that argument
is clearer.
* additional defer() to offset the effect of using the type before declaring
* linter fix
* linter fix
* linter fix
* test case
Co-authored-by: Kacper Szmigiel <szmigielkacper@gmai.com>
* Don't change type of HttpRequest.user if type has been changed by subclassing
* Asserts for typing
* Add tests
* Add description of HttpRequest subclassing to README
* Dummy to rebuild travis
In addition to the meta properties added
to the Choices enums, value and label are
set for each choice.
This commit explicitly types those instead of the
tuple value and non-extant label types
* proper redirect return type annotations made with Literal
* Mapping instead of Dict type annotation for context in render() with test
* removed Union and Context
* typo
Co-authored-by: Kacper Szmigiel <szmigielkacper@gmai.com>
Add __init__ to OrderedSet (#381)
Issue 382 (#384)
* WIP fix, pushed for testing
* added _ prefix for internal types
Co-authored-by: Kacper Szmigiel <szmigielkacper@gmai.com>
Fix parameter types for assertJSONEqual/NotEqual (#385)
Add get_supported_language_variant (#386)
Issue 309 (#383)
* added tags for user models
* type test for HttpRequest.user
* test for User and AnonymousUser tags
* httrequest test fix
* checking python version fix for readibility
* Rewrite version check for readability
* Annotate is_authenticated/is_anonymous with Literal-type
* Add auth in INSTALLED_APPS in test
* Fix wrong type assertion in test
* Fix misconception of how branch-testing works
* Remove user from WSGIRequest
* Change HttpRequest-transformer to set user-type to include AnonymousUser
* Add check for anonymous_user_info=None to appease mypy
* Isort transformers/request
* Remove trailing whitespace
* Remove unused import
Co-authored-by: Kacper Szmigiel <szmigielkacper@gmai.com>
* fix formatting and unused import
* reformatted again
Co-authored-by: Kacper Szmigiel <szmigielkacper@gmai.com>
* added tags for user models
* type test for HttpRequest.user
* test for User and AnonymousUser tags
* httrequest test fix
* checking python version fix for readibility
* Rewrite version check for readability
* Annotate is_authenticated/is_anonymous with Literal-type
* Add auth in INSTALLED_APPS in test
* Fix wrong type assertion in test
* Fix misconception of how branch-testing works
* Remove user from WSGIRequest
* Change HttpRequest-transformer to set user-type to include AnonymousUser
* Add check for anonymous_user_info=None to appease mypy
* Isort transformers/request
* Remove trailing whitespace
* Remove unused import
Co-authored-by: Kacper Szmigiel <szmigielkacper@gmai.com>
* Mapping instead of Dict type annotation for context in render() with test
* removed Union and Context
* typo
Co-authored-by: Kacper Szmigiel <szmigielkacper@gmai.com>
This is valid Django, which failed to pass with the old type-defintion:
class MyForm(Form):
myparam = MultiFileField(...)
self.clean(self, *args, **kwargs):
self.files.getlist('myparam', [])
By declaring return type as -> Callable[[_C], _C], Mypy can infer that
the decorated function has also the same arguments and return type as
the original.
View functions are constrained to return HttpResponseBase (or any
subclass of it).
Also added typecheck test coverage to most of the cases.
* Updated gitpython dependency to fix error:
ModuleNotFoundError: No module named 'gitdb.utils.compat'
* Updated Django repository git refs because old 3.0.x commit hash gave error:
stderr: 'fatal: reference is not a tree: 6cb30414bc0f83b49afc4cae76d4af5656effe9a'
* Newer Django version also needs new ignores.
* Added missing `follow: bool` argument to Client request methods.
* Annotated return types as `HttpResponse` instead of `Any`.
* Made `Client` class inherit from `RequestFactory`, as it does in Django.
* Changed `json()` return type to Any, as it can also be a list.
Wrt (2), these return types were reverted from `HttpResponse` to `Any`
in commit 287c64d6fb. But I suspect that
was simply to silence mypy warnings about "incompatible with supertype
RequestFactory", not because there were any issues with the annotation.
Note that `Client.request()` monkey-patches the `HttpResponse` object
with some additional attributes. Those attributes were already annotated
before, I reordered and added additional comments to make it clear where
they come from.
- [Python official typing documentation](https://docs.python.org/3/library/typing.html)
- [Typing in Python](https://inventwithpython.com/blog/2019/11/24/type-hints-for-busy-python-programmers/) article
Additionally, the following resources might be useful:
- [How to write custom mypy plugins](https://mypy.readthedocs.io/en/stable/extending_mypy.html)
- [Typechecking Django and DRF](https://sobolevn.me/2019/08/typechecking-django-and-drf) guide
- [Testing mypy stubs, plugins, and types](https://sobolevn.me/2019/08/testing-mypy-types) guide
- [Awesome Python Typing](https://github.com/typeddjango/awesome-python-typing) list
## Dev setup
### Repository Setup
As a first step you will need to fork this repository and clone your fork locally.
In order to be able to continously sync your fork with the origin repository's master branch, you will need to set up an upstream master. To do so follow this [official github guide](https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/syncing-a-fork).
### Dependency Setup
After your repository is setup you will then need to create and activate a git ignored virtual env, e.g.:
```bash
python3 -m venv .venv
source .venv/bin/activate
```
Then install the dev requirements:
```bash
pip install -r ./requirements.txt
```
Finally, install the pre-commit hooks:
```bash
pre-commit install
```
### Testing and Linting
We use `mypy`, `pytest`, `flake8`, and `black` for quality control. All tools except pytest are executed using pre-commit when you make a commit.
To ensure there are not formatting or typing issues in the entire repository you can run:
```bash
pre-commit run --all-files
```
NOTE: This command will not only lint but also modify files - so make sure to commit whatever changes you've made before hand.
You can also run pre-commit per file or for a specific path, simply replace "--all-files" with a target (see [this guide](https://codeburst.io/tool-your-django-project-pre-commit-hooks-e1799d84551f) for more info).
To execute the unit tests, simply run:
```bash
pytest
```
If you get some unexpected results or want to be sure that tests run is not affected by previous one, remove `mypy` cache:
```bash
rm -r .mypy_cache
```
We also test the stubs against Django's own test suite. This is done in CI but you can also do this locally.
The stubs are based on auto-generated code created by Mypy's stubgen tool (see: [the stubgen docs](https://mypy.readthedocs.io/en/stable/stubgen.html)).
To make life easier we have a helper script that auto generates these stubs. To use it you can run:
The output for this is a gitignored folder called "stubgen" in the repo's root.
## Submission Guidelines
The workflow for contributions is fairly simple:
1. fork and setup the repository as in the previous step.
2. create a local branch.
3. make whatever changes you want to contribute.
4. ensure your contribution does not introduce linting issues or breaks the tests by linting and testing the code.
5. make a pull request with an adequate description.
## A Note About Generics
As Django uses a lot of the more dynamic features of Python (i.e. metaobjects), statically typing it requires heavy use of generics. Unfortunately, the syntax for generics is also valid python syntax. For instance, the statement `class SomeClass(SuperType[int])` implicitly translates to `class SomeClass(SuperType.__class_getitem__(int))`. If `SuperType` doesn't define the `__class_getitem__` method, this causes a runtime error, even if the code typechecks.
When adding a new generic class, or changing an existing class to use generics, run a quick test to see if it causes a runtime error. If it does, please add the new generic class to the `_need_generic` list in the [django_stubs_ext monkeypatch function](https://github.com/typeddjango/django-stubs/blob/master/django_stubs_ext/django_stubs_ext/patch.py)
This package contains type stubs and mypy plugin to provide more precise static types and type inference for Django framework. Django uses some Python "magic" that makes having precise types for some code patterns problematic. This is why we need to accompany the stubs with mypy plugins. The final goal is to be able to get precise types for most common patterns.
Could be run on earlier versions of Django, but expect some missing imports warnings.
This package contains [type stubs](https://www.python.org/dev/peps/pep-0561/) and a custom mypy plugin to provide more precise static types and type inference for Django framework. Django uses some Python "magic" that makes having precise types for some code patterns problematic. This is why we need this project. The final goal is to be able to get precise types for most common patterns.
## Installation
```bash
pip install django-stubs
pip install django-stubs[compatible-mypy]
```
## Mypy compatibility
| django-stubs | mypy version | django version | python version
| ------------ | ---- | ---- | ---- |
| 1.3.0 | 0.750 | 2.2.x | ^3.6
| 1.2.0 | 0.730 | 2.2.x | ^3.6
| 1.1.0 | 0.720 | 2.2.x | ^3.6
| 0.12.x | old semantic analyzer (<0.711), dmypy support | 2.1.x | ^3.6
## Configuration
To make mypy aware of the plugin, you need to add
```ini
[mypy]
plugins=
mypy_django_plugin.main
[mypy.plugins.django-stubs]
django_settings_module="myproject.settings"
```
in your `mypy.ini` or `setup.cfg` [file](https://mypy.readthedocs.io/en/latest/config_file.html).
Plugin also requires Django settings module (what you put into `DJANGO_SETTINGS_MODULE` variable) to be specified.
[pyproject.toml](https://mypy.readthedocs.io/en/stable/config_file.html#using-a-pyproject-toml-file) configurations are also supported:
```ini
[mypy]
strict_optional=True
```toml
[tool.mypy]
plugins=["mypy_django_plugin.main"]
# This one is new:
[mypy.plugins.django-stubs]
django_settings_module=mysettings
[tool.django-stubs]
django_settings_module="myproject.settings"
```
Where `mysettings` is a value of `DJANGO_SETTINGS_MODULE` (with or without quotes)
Two things happening here:
Current implementation uses Django runtime to extract models information, so it will crash, if your installed apps `models.py` is not correct. For this same reason, you cannot use `reveal_type` inside global scope of any Python file that will be executed for `django.setup()`.
In other words, if your `manage.py runserver` crashes, mypy will crash too.
1. We need to explicitly list our plugin to be loaded by `mypy`
2. Our plugin also requires `django` settings module (what you put into `DJANGO_SETTINGS_MODULE` variable) to be specified
This fully working [typed boilerplate](https://github.com/wemake-services/wemake-django-template) can serve you as an example.
## Version compatibility
## Notes
We rely on different `django` and `mypy` versions:
Type implementation monkey-patches Django to add `__class_getitem__` to the `Manager` class.
If you would use Python3.7 and do that too in your code, you can make things like
| django-stubs | mypy version | django version | python version
|--------------| ---- | ---- | ---- |
| 1.13.0 | 0.980+ | 3.2.x or 4.0.x or 4.1.x | ^3.7
| 1.12.0 | 0.931+ | 3.2.x or 4.0.x | ^3.7
| 1.11.0 | 0.931+ | 3.2.x | ^3.7
| 1.10.0 | 0.931+ | 3.2.x | ^3.7
| 1.9.0 | 0.910 | 3.2.x | ^3.6
| 1.8.0 | 0.812 | 3.1.x | ^3.6
| 1.7.0 | 0.790 | 2.2.x \|\| 3.x | ^3.6
| 1.6.0 | 0.780 | 2.2.x \|\| 3.x | ^3.6
| 1.5.0 | 0.770 | 2.2.x \|\| 3.x | ^3.6
| 1.4.0 | 0.760 | 2.2.x \|\| 3.x | ^3.6
| 1.3.0 | 0.750 | 2.2.x \|\| 3.x | ^3.6
| 1.2.0 | 0.730 | 2.2.x | ^3.6
| 1.1.0 | 0.720 | 2.2.x | ^3.6
| 0.12.x | old semantic analyzer (<0.711), dmypy support | 2.1.x | ^3.6
## FAQ
### Is this an official Django project?
No, it is not. We are independent from Django at the moment.
There's a [proposal](https://github.com/django/deps/pull/65) to merge our project into the Django itself.
You can show your support by liking the PR.
### Is it safe to use this in production?
Yes, it is! This project does not affect your runtime at all.
It only affects `mypy` type checking process.
But, it does not make any sense to use this project without `mypy`.
### mypy crashes when I run it with this plugin installed
The current implementation uses Django's runtime to extract information about models, so it might crash if your installed apps or `models.py` are broken.
In other words, if your `manage.py runserver` crashes, mypy will crash too.
You can also run `mypy` with [`--tb`](https://mypy.readthedocs.io/en/stable/command_line.html#cmdoption-mypy-show-traceback)
option to get extra information about the error.
### I cannot use QuerySet or Manager with type annotations
You can get a `TypeError: 'type' object is not subscriptable`
when you will try to use `QuerySet[MyModel]`, `Manager[MyModel]` or some other Django-based Generic types.
This happens because these Django classes do not support [`__class_getitem__`](https://www.python.org/dev/peps/pep-0560/#class-getitem) magic method in runtime.
1. You can go with our [`django_stubs_ext`](https://github.com/typeddjango/django-stubs/tree/master/django_stubs_ext) helper, that patches all the types we use as Generic in django.
Install it:
```bash
pip install django-stubs-ext # as a production dependency
```
And then place in your top-level settings:
```python
import django_stubs_ext
django_stubs_ext.monkeypatch()
```
Note: This monkey patching approach will only work when using Python 3.7 and higher, when the `__class_getitem__` magic method was introduced.
You can add extra types to patch with `django_stubs_ext.monkeypatch(extra_classes=[YourDesiredType])`
2. You can use strings instead: `'QuerySet[MyModel]'` and `'Manager[MyModel]'`, this way it will work as a type for `mypy` and as a regular `str` in runtime.
### How can I create a HttpRequest that's guaranteed to have an authenticated user?
Django's built in [`HttpRequest`](https://docs.djangoproject.com/en/4.0/ref/request-response/#django.http.HttpRequest) has the attribute `user` that resolves to the type
```python
classMyUserManager(models.Manager['MyUser']):
pass
Union[User, AnonymousUser]
```
where `User` is the user model specified by the `AUTH_USER_MODEL` setting.
classMyUser(models.Model):
objects=MyUserManager()
If you want a `HttpRequest` that you can type-annotate with where you know that the user is authenticated you can subclass the normal `HttpRequest` class like so:
```python
from django.http import HttpRequest
from my_user_app.models import MyUser
class AuthenticatedHttpRequest(HttpRequest):
user: MyUser
```
work, which should make a error messages a bit better.
And then use `AuthenticatedHttpRequest` instead of the standard `HttpRequest` for when you know that the user is authenticated. For example in views using the `@login_required` decorator.
### My QuerySet methods are returning Any rather than my Model
If you are using `MyQuerySet.as_manager()`:
Example:
```python
from django.db import models
class MyModelQuerySet(models.QuerySet):
pass
class MyModel(models.Model):
bar = models.IntegerField()
objects = MyModelQuerySet.as_manager()
def use_my_model() -> int:
foo = MyModel.objects.get(id=1) # Should now be `MyModel`
- [`awesome-python-typing`](https://github.com/typeddjango/awesome-python-typing) - Awesome list of all typing-related things in Python.
- [`djangorestframework-stubs`](https://github.com/typeddjango/djangorestframework-stubs) - Stubs for Django REST Framework.
- [`pytest-mypy-plugins`](https://github.com/typeddjango/pytest-mypy-plugins) - `pytest` plugin that we use for testing `mypy` stubs and plugins.
- [`wemake-django-template`](https://github.com/wemake-services/wemake-django-template) - Create new typed Django projects in seconds.
Otherwise, custom type will be created in mypy, named `MyUser__MyUserManager`, which will rewrite base manager as `models.Manager[User]` to make methods like `get_queryset()` and others return properly typed `QuerySet`.
## To get help
We have Gitter here: <https://gitter.im/mypy-django/Lobby>
If you think you have more generic typing issue, please refer to <https://github.com/python/mypy> and their Gitter.
If you think you have more generic typing issue, please refer to https://github.com/python/mypy and their Gitter.
## Contributing
This project is open source and community driven. As such we encourage contributions big and small. You can contribute by doing any of the following:
1. Contribute code (e.g. improve stubs, add plugin capabilities, write tests etc) - to do so please follow the [contribution guide](./CONTRIBUTING.md).
2. Assist in code reviews and discussions in issues.
3. Identify bugs and issues and report these
4. Ask and answer questions on [StackOverflow](https://stackoverflow.com/questions/tagged/django-stubs)
You can always also reach out in gitter to discuss your contributions!
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.