-
-
Notifications
You must be signed in to change notification settings - Fork 453
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Restore ability to instantiate, access objects
manager, of abstract models
#1653
Comments
A possible work-around is using " Example: class Cat(Animal):
pass
class Dog(Animal):
pass
T = TypeVar("T", Cat, Dog) # <-- must list all possible Animal subclasses
def create_animal_generic(klass: type[T], name: str) -> T:
return klass.objects.create(name=name) This code checks succesfully even after changes in #1649. |
I vote -1 on any |
I will submit a PR with a testcase as well, so we don't regress it in the future. |
Welp, the proposed fix would cause other issues to appear (when overriding |
mypy is correct to complain about your create_animal(Animal, "Twilight Sparkle")
create_animal_generic(Animal, "Princess Celestia") How about rewriting them to accept a manager rather than a type object? T = TypeVar("T", bound=Animal)
def create_animal_by_manager(objects: models.Manager[T], name: str) -> T:
return objects.create(name=name)
create_animal_by_manager(Cat.objects, "Grumpy") |
I think andersk conclusion is correct. I don't think it's possible to restrain a A slightly different attempt could be to declare a protocol, describing an expected Though I haven't had the best experience using models with protocols.. |
Hm, would it work to declare a protocol that describes the inheritance and use that as bound? I.e. class XYZ(Animal, Protocol):
...
T = TypeVar("T", bound=XYZ) Or am I completely off here? Edit: Might not even be needed with a TypeVar |
I've tried to dig around a bit into what mypy does for abstract base classes (
See the following playground link for how to trigger the error: https://mypy-play.net/?mypy=latest&python=3.11&gist=e68d5eeca6994812788f81ae69a3967a Essentially there's an additional case which yields errors on corresponding calls mentioned by andersk, if we assume create_animal(Animal, "Twilight Sparkle") # E: Only concrete class can be given where "type[Animal]" is expected [type-abstract]
create_animal_generic(Animal, "Princess Celestia") # E: Only concrete class can be given where "type[Animal]" is expected [type-abstract] Now, Django also guards abstract models by raising a: So, perhaps we could attempt to mimic what mypy does with an |
Forgot to mention that if the guard I mention is introduced, we could safely try to exclude yielding an error for |
Yes, I've also experimented with mimicin abstract models to be abstract classes, but something didn't work for me :) Oh, I remember: Please, feel free to experiment - I would love to see this feature. |
I've opened #1663, including some kind of attempt to mimic abstract base classes |
I think I got it to work by adding 2 "abstract attributes" I found, from Django's model meta class: We should probably only add those 2 attributes to concrete models, with the plugin.. |
Continuing the discussion started at #1649 (comment)
There are two similar use cases affected by two different PRs:
Since the changes in #1393, django-stubs will raise errors on some kinds of generic code that handles abstract models. For example:
These two functions are allowed and work with django-stubs 4.2.3. Function
create_animal
causes errors in git master version of django-stubs:But after the unmerged changes in PR #1649, the second function
create_animal_generic
will also start failing:System information
python
version: 3.11.4mypy
version: 1.4.1django-stubs
version: 4.2.3 / gitThe text was updated successfully, but these errors were encountered: