summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/decl_api.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/orm/decl_api.py')
-rw-r--r--lib/sqlalchemy/orm/decl_api.py34
1 files changed, 24 insertions, 10 deletions
diff --git a/lib/sqlalchemy/orm/decl_api.py b/lib/sqlalchemy/orm/decl_api.py
index 7249698c0..500f2786e 100644
--- a/lib/sqlalchemy/orm/decl_api.py
+++ b/lib/sqlalchemy/orm/decl_api.py
@@ -522,7 +522,7 @@ def declarative_mixin(cls: Type[_T]) -> Type[_T]:
def _setup_declarative_base(cls: Type[Any]) -> None:
if "metadata" in cls.__dict__:
- metadata = cls.metadata # type: ignore
+ metadata = cls.__dict__["metadata"]
else:
metadata = None
@@ -688,11 +688,27 @@ class DeclarativeBase(
def __init_subclass__(cls) -> None:
if DeclarativeBase in cls.__bases__:
+ _check_not_declarative(cls, DeclarativeBase)
_setup_declarative_base(cls)
else:
_as_declarative(cls._sa_registry, cls, cls.__dict__)
+def _check_not_declarative(cls: Type[Any], base: Type[Any]) -> None:
+ cls_dict = cls.__dict__
+ if (
+ "__table__" in cls_dict
+ and not (
+ callable(cls_dict["__table__"])
+ or hasattr(cls_dict["__table__"], "__get__")
+ )
+ ) or isinstance(cls_dict.get("__tablename__", None), str):
+ raise exc.InvalidRequestError(
+ f"Cannot use {base.__name__!r} directly as a declarative base "
+ "class. Create a Base by creating a subclass of it."
+ )
+
+
class DeclarativeBaseNoMeta(inspection.Inspectable[Mapper[Any]]):
"""Same as :class:`_orm.DeclarativeBase`, but does not use a metaclass
to intercept new attributes.
@@ -705,22 +721,20 @@ class DeclarativeBaseNoMeta(inspection.Inspectable[Mapper[Any]]):
"""
- if typing.TYPE_CHECKING:
- registry: ClassVar[_RegistryType]
- _sa_registry: ClassVar[_RegistryType]
- metadata: ClassVar[MetaData]
-
- __name__: ClassVar[str]
- __mapper__: ClassVar[Mapper[Any]]
- __table__: ClassVar[Optional[FromClause]]
+ registry: ClassVar[_RegistryType]
+ _sa_registry: ClassVar[_RegistryType]
+ metadata: ClassVar[MetaData]
+ __mapper__: ClassVar[Mapper[Any]]
+ __table__: Optional[FromClause]
- __tablename__: ClassVar[Any]
+ if typing.TYPE_CHECKING:
def __init__(self, **kw: Any):
...
def __init_subclass__(cls) -> None:
if DeclarativeBaseNoMeta in cls.__bases__:
+ _check_not_declarative(cls, DeclarativeBaseNoMeta)
_setup_declarative_base(cls)
else:
cls._sa_registry.map_declaratively(cls)