如何将运行时对象类型用作泛型类型提示参数?

Jar*_*rad 10 python type-hinting python-3.5

介绍

使用Python/MyPy类型提示,可以使用.pyi存根将注释保存在单独的文件中以实现.我正在使用此功能来提供SQLAlchemy的ORM(更具体地说,flask_sqlalchemy插件)的基本提示.

模型定义如下:

class MyModel(db.Model):
    id = db.Column()
    ...
...
Run Code Online (Sandbox Code Playgroud)

其中db.Model直接包含在SQLAlchemy中.例如,可以通过以下方式查询它们:

MyModel.query.filter({options: options}).one_or_none()
Run Code Online (Sandbox Code Playgroud)

其中filter()返回另一个Query,one_or_none()返回MyModel的实例(显然是None).

下面的.pyi文件成功提示上面的构造,虽然它不完整 - 没有办法提示返回类型one_or_none().

class _SQLAlchemy(sqlalchemy.orm.session.Session):
    class Model:
       query = ... # type: _Query

class _Query(sqlalchemy.orm.query.Query):
    def filter(self, *args) -> query.Query: ...
    def one_or_none(self) -> Any: ...

db = ... # type: _SQLAlchemy
Run Code Online (Sandbox Code Playgroud)

问题

如何完全和一般地暗示上述内容,并提示one_or_none()的返回类型?我的第一次尝试是使用泛型,但看起来我无法访问所讨论的子类型(在给定的示例中,MyModel).为了说明一种非工作方法:

from typing import Generic, TypeVar

_T = TypeVar('_T')

class _SQLAlchemy(sqlalchemy.orm.session.Session):
    class Model:
       def __init__(self, *args, **kwargs):
           self.query = ... # type: _Query[self.__class__]

class _Query(Generic[_T], sqlalchemy.orm.query.Query):
    def filter(self, *args) -> _Query[_T]: ...
    def one_or_none(self) -> _T: ...

db = ... # type: _SQLAlchemy
Run Code Online (Sandbox Code Playgroud)

有没有办法让这个工作?

对于具体和示例的道歉,但我试着用一个通用的例子简洁地写出这一点,它从来没有像现在那样清晰(可能仍然不多!)

编辑

另一个非工作方法(我知道这将限制必须调用myModelInstance.query ...而不是静态MyModel.query,但即使这不起作用):

from typing import Generic, TypeVar

_T = TypeVar('_T')

class _SQLAlchemy(sqlalchemy.orm.session.Session):
    class Model:

       @property
       def query(self: _T) -> _Query[_T]: ...

class _Query(Generic[_T], sqlalchemy.orm.query.Query):
    def filter(self, *args) -> _Query[_T]: ...
    def one_or_none(self) -> _T: ...

db = ... # type: _SQLAlchemy
Run Code Online (Sandbox Code Playgroud)

mic*_*del 2

幸运的是,类型注释存根现在可用于该特定问题https://github.com/dropbox/sqlalchemy-stubs

类型注释的确切实现Query可以在这里: https: //github.com/dropbox/sqlalchemy-stubs/blob/master/sqlalchemy-stubs/orm/query.pyi存档