* 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.
* 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>
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.
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>
* 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
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.