Fix miscellaneous type annotation issues - #371
paveltsialnou wants to merge 4 commits into
Conversation
|
This can also be a class derived from the declarative base. I'd love to add typing everywhere, is there a reason this parameter in particular gave you a problem? |
|
I dug into how Right now if manager.user_cls:
user_cls = manager.user_cls
Base = manager.declarative_base
registry = Base.registry._class_registry
if isinstance(user_cls, str):
try:
user_cls = registry[user_cls]
except KeyError:
raise ImproperlyConfigured(
'Could not build relationship between Transaction'
f' and {user_cls}. {user_cls} was not found in declarative class '
'registry. Either configure VersioningManager to '
'use different user class or disable this '
'relationship '
)
user_id = sa.Column(
sa.inspect(user_cls).primary_key[0].type,
sa.ForeignKey(sa.inspect(user_cls).primary_key[0]),
index=True,
)
user = sa.orm.relationship(user_cls)So effectively, when it’s not
Given that, the “ideal” type annotation would be something like “class from this declarative registry or a string name of such a class”, but Python’s type system can’t express “class from this particular registry”. Because of that, I see three options:
from sqlalchemy.orm import DeclarativeBase
UserCls = type[DeclarativeBase] | str | None
def make_versioned(
...,
user_cls: UserCls = "User",
) -> None:
...That would be the most precise for new-style declarative users, but it would be wrong for older
from typing import Any
UserCls = type[Any] | str | None
def make_versioned(
...,
user_cls: UserCls = "User",
) -> None:
...This matches what the code actually does (any mapped class that
Let me know which direction you’d prefer and I can adjust the annotation (or drop it) accordingly. |
Small fix for type annotations of
make_versionedfunction