Repository navigation
Bad error message: mypy reports 'Name is not defined' when using an object member as super class of another class #8603
Description
Activity
This is an incorrect error message, certainly. We're not going to support this code, though.
- changed the title
[-]Mypy reports 'Name is not defined' when using an object member as super class of another class[/-][+]Bad error message: mypy reports 'Name is not defined' when using an object member as super class of another class[/+]on Apr 3, 2020 @msullivan Should the error message be changed?
We'd be likely to accept a PR that improves the error message (something like "object member cannot be used as base class", I suppose).
Reacted by Peter Schutt@JelleZijlstra This is my first time contributing. Can I pick this up?
``I would like to contribute to this issue. Can I pull this up?
Can I look into this, seems like I can handle this one
@msullivan @JelleZijlstra I looked through the codebase where I can set up a check for this, I think I have to implement something around
semanal/analyze base classorsemanal/expr to analyzed typeand have to check if the base class is a object member, I tried everything but I don't seem to know how to do this, could anybody guide me through this, I'm kind of a newbie.Using per line comment as # type: ignore[name-defined] at less silence this error message
Reacted by savchenko and Ivan FedorovIf this issue is not solved, I would like to be assigned this @msullivan @JelleZijlstra
Have similar issue:
from typing import Type class A: ... class SomeMixin: ... class some_framework_app: ... def subclass_a(something): class A1(A): attr = something return A1 class B(some_framework_app): C: Type[A] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.C = subclass_a(self) app = B() class D(app.C, SomeMixin): ... # <=== Name "app.C " is not definedI'm currently adding annotations to Flask-SQLAlchemy. If this is not supported, I will never be able to enable type checking, as it breaks one of the major features of Flask-SQLAlchemy. If I do enable it, every project would have to add an ignore rule for
name-definedto every model, or to their config, which is not ideal.The extension creates a
self.Modelclass that is used to register SQLAlchemy models with the extension instance. However, due to this issue, mypy shows an error forclass User(db.Model).Here's a minimal example without any SQLAlchemy-specific code:
import typing as t class Example: Model: t.Type[object] def __init__(self): self.Model = object db = Example() reveal_type(db.Model) class User(db.Model): pass
$ mypy --show-error-codes example.py example.py:12: note: Revealed type is "Type[builtins.object]" example.py:14: error: Name "db.Model" is not defined [name-defined]I don't understand why this won't be supported. Mypy already understands that the name is a
Type, it should be possible to inherit from it.Reacted by Ricardo Madriz, Zeyi (Rice) Fan, Bart Van Loon, Greg Kaleka, Stevan Milic, Pavel Rybkin, Ige, Mattias Lindvall, Tim Weber, Nikita Andrusov and 28 moreFlask-SQLAlchemy has blown up for me after the 3.0 release. As I can see from pallets-eco/flask-sqlalchemy#1118, the fix is to litter my code with
# type: ignorecomments. This is an unhappy state.Reacted by David Lord and Adam Chidlow3 remaining items
- added 2 commits that reference this issue
on Feb 6, 2023 (via python/typeshed#9860)
Here’s an example of a seemingly innocuous usage of the multiprocessing module that triggers this error:
import multiprocessing context = multiprocessing.get_context() class MyProcess(context.Process): # error: Name "context.Process" is not defined [name-defined]. pass
It would be great to hear why the restriction is in place. Is this just hard to solve technically or would it cause other issues were it allowed?
Reacted by Adam Chidlow, Christopher Wrogg, Daniel Robert, Peter Cock and martinsandhalle@jace above expresses eloquently the frustration a lot of us share.
Mypy and Flask-SQLAlchemy are both popular packages. Would it be possible for the teams from each to talk to each other and find a better way forwards than either dropping
type ignoreeverywhere or re-implementing the functionality offered by Flask-SQLAlchemy?Reacted by Aleksandre (Alex) C.Happy to review a PR to Flask-SQLAlchemy that fixes the issue while retaining compatibility with its existing interface. But there's nothing more to do on my end than what I've already commented here. Note that even if MyPy fixes it, you have to separately convince pyright (vscode) to fix it, and they've already declined.
I've replaced
db.Modelwith a custom base class and have full typing support now. It supports__bind_key__too, but I chose to not implement the automatic__tablename__construction as it felt a bit magical.Reacted by Keith Edmunds, Adam Verner and Jingchen YeReacted by David LordThat looks very interesting @jace, thank you. I will look into migrating to your solution.
@davidism I'm sorry this is not drop-in compatible with Flask-SQLAlchemy or I'd have made a PR. I had to move all namespacing and base class config out of the
SQLAlchemyinstance to get typing to work, and there's a somewhat ugly two-line init to get Flask-SQLAlchemy's session management. My typing-fu only goes so far.At best, I can think of a cleaner but backward-incompatible integration.
This has been helpful discussion - thanks in particular to @davidism and @jace.
I think Flask-SQLAlchemy is a great extension for proof of concept code and for those less experienced with Flask and/or SQLAlchemy. As a project grows and the team become more experienced, tools such as mypy become more important and valuable. At some point the value of mypy takes precedent over the convenience of wrappers such as Flask-SQLAlchemy, particularly such wrappers don't sit well with mypy.
For now, we've adapted an approach outlined in this post, seemingly (and worryingly) only available on Wayback Machine. The approach is to define a declarative base outside of Flask-SQLAlchemy and then pass that to the extension, which not only avoids the mypy problems but also makes the declarative base available independently of Flask which, as it happens, is also helpful for us.
Some code changes were needed from those given in the post referenced above, and I'm happy to make them available on request.
For future projects, I suspect we'll choose not to use Flask-SQLAlchemy and just code SQLAlchemy access natively as documented on the Flask pages.
If Flask-SQLAlchemy were to take the approach of using a predefined declarative base then I suspect that would increase the utility of that extension. However, that would be backward incompatible and may not align with the future goals of Flask-SQLAlchemy.
Reacted by David Lord, Markus Unterwaditzer, kabell, Théo Guérin and Christopher WroggThe reason I keep voting these comments down is because they're orthogonal to this issue and don't help fix the problem in MyPy or in Flask-SQLAlchemy. And it really, really sucks to be a maintainer that has poured countless hours into it to then be told "Flask-SQLAlchemy isn't good because it doesn't work with typing in this one case", or "Just rip out Flask-SQLAlchemy and replace it", or "I'm going to tell everyone not to use Flask-SQLAlchemy", or "Flask-SQLalchemy is only good for proofs of concept" etc. It really, really sucks. I am not happy with the fact that I keep hearing these things just because I need to watch this issue for actual resolutions to the issue.
I'd suggest not replying along these lines further, it's off topic here, sorry MyPy maintainers. But I couldn't remain silent in the face of being told my work isn't good over and over again, especially after being completely open to fixing the issue. And if you're response is "that wasn't my intention" it doesn't matter, that's how it came off anyway.
Reacted by Adam Chidlow, Pradyun Gedam, Subham Agarwal, Matt Richards, Diogo, Sebastian Atlántico, DH, Will Lynas, Guido Iaquinti, kabell and 18 moreThe
db.Modelis created dynamically for some reason, but Mypy need static type. I don't think it's either side's fault.
I like Flask-SQLAlchemy. The dynamic feature of python is definitely one of features that I much like. I don't want to sacrifice dynamic capability for static type.
I don't expect Mypy to support all popular dynamic patterns, but can we provide more actual use cases for those dynamic patterns?Here is an example for Flask-SQLAlchemy, which works for me, but I'm just not sure if it's good practice:
from typing import TYPE_CHECKING from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() if TYPE_CHECKING: from flask_sqlalchemy.model import Model else: Model = db.Model class ExampleModel(Model): pass reveal_type(ExampleModel) reveal_type(ExampleModel.query) # note: Revealed type is "def () -> app.graphql.base.ExampleModel" # note: Revealed type is "flask_sqlalchemy.query.Query"
Reacted by Gustavo J. A. M. Carneiro, Jian Yu, theo court and Samuel CarlssonReacted by Gustavo J. A. M. Carneiro, Jian Yu, Adam Verner and Lawrence GonzálezJust writing the stub files for PonyORM. Actually I got the same error. In PonyORM all database models are subclasses from
db.Entitywhich is an attribute of the Database class.
Similar as in the Issue description but using a metaclass:class EntityMeta(type): pass class Entity(metaclass=EntityMeta): pass class Database: def __init__(self): self.Entity = type.__new__(EntityMeta, 'Entity', (Entity,), {}) self.Entity._database_ = self db = Database() class ExampleModel(db.Entity): pass
And I get the MyPy error:
error: Name "db.Entity" is not defined [name-defined]I tried to add the Entity as an instance attribute to
core.pyi, but it doesn't help:class Database: Entity: EntityMeta # or Entity: type[Entity] def __init__(self, *args, **kwargs) -> None: ...
- added a commit that references this issue
on Jun 10, 2025
Consider the following valid Python 3 code:
Actual behavior:
Mypy will report
Name 'b.a' is not definedon the lineclass C(b.a):.Expected behavior:
No error reported by Mypy.
Python version: 3.8.2
Mypy version: 0.770 (master not checked)
Flags: no flags