Pycharm 使用自定义元类指定类的类型

Pycharm 使用自定义元类指定类的类型,pycharm,metaclass,python-typing,Pycharm,Metaclass,Python Typing,继一个使用类似枚举的Django选项替换的伟大系统()之后,我有一个项目,该项目使用一个带有自定义元类的类,该类允许我执行list(MyChoices)(在类本身上)以获得所有枚举选项的列表。代码的相关部分如下所示: 类元选择(类型): @类方法 定义准备(mcs、名称、基础、**kwargs): 退货订单日期() 定义新(mcs、名称、基础、属性): _choices=OrderedDict() 对于属性名称,列表中的值(attrs.items()): …做事。。。 返回类型。\uuuuu新的

继一个使用类似枚举的Django选项替换的伟大系统()之后,我有一个项目,该项目使用一个带有自定义元类的类,该类允许我执行
list(MyChoices)
(在类本身上)以获得所有枚举选项的列表。代码的相关部分如下所示:

类元选择(类型):
@类方法
定义准备(mcs、名称、基础、**kwargs):
退货订单日期()
定义新(mcs、名称、基础、属性):
_choices=OrderedDict()
对于属性名称,列表中的值(attrs.items()):
…做事。。。
返回类型。\uuuuu新的\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
定义(cls):
返回iter(cls.\u choices.items())
类选择(元类=元选择):
通过
冰淇淋类风味(可选):
草莓味=(‘草莓味’、‘水果味’)
巧克力=‘巧克力’
清单(冰淇淋口味)
#[(‘草莓’、‘水果’)、(‘巧克力’、‘巧克力’)

这段代码已经运行了一段时间,但现在我已经打开了键入功能(在本例中,使用PyCharm的类型检查器,但也在寻找通用解决方案),而且,
IceCreamFlavor
没有标记为iterable,尽管它是从一个类派生出来的,而该类的元类将
cls
定义为具有一个
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
方法(首先添加注释文件*.pyi的Pytype更容易检查)

方法
\uuu iter\uuuu()
中存在一个键入问题,即属性
\u choices
对于检查器来说似乎未定义,因为它的分配不是透明的,仅由
属性['']=…
指定

可以通过添加一行对其进行注释:

类元选择(类型):
_choices=None#type:dict#作为Python的注释编写>=3.5
#_choices:dict#如果Python>=3.6,则此行可以取消注释
当然,MyPY也会检查它的注释是否有效

可能是
\uuuu iter\uuuu()
中的键入问题导致元类方法在检查器中被忽略


如果修复没有帮助,则可以通过以下简化示例报告问题:

类元选择(类型):
_选项={0:'a'}
定义(cls):
返回iter(cls.\u choices.items())
类选择(元类=元选择):
通过
断言列表(选项)=[(0,'a')]


我在原始文章中报告了另一个小错误。该错误与此问题无关。

这是PyCharm类型检查器中的错误,请您提交一个问题好吗?@user2235698:我认为PyCharm可能不是“提交”的正确位置它可能是另一个包的上游问题,但是PyCharm的人可以很容易地说是哪个包负责。如果该包的文档(MyPy?)指定了一个元类支持有限的边界,那么这也不是一个bug。这通常首先通过get_元类_hook()解决,以后可能会采用,最后可能会默认启用。@hynekcer PyCharm不使用mypy,它有自己的类型checker@user2235698:存在一个用Java编写的PyCharm插件,它调用一个
mypy
可执行文件。是的,PyCharm有自己的检查程序,但这并不意味着它在任何情况下都不使用mypy进行键入。@hynekc呃这个插件不是捆绑的,使用它的唯一方法是通过
文件-设置-插件
类选择(Iterable,metaclass=MetaChoices)手动安装
不起作用,因为
Choices
对象实际上是不可编辑的,但只有类本身是可编辑的。你是对的。我简化了答案。如果没有帮助,那么标记“mypy”与这个问题无关。你的版本通过了mypy,@hynekcer,所以我将删除mypy标记。