枚举功能集#

新Python枚举的开发采取了补丁的形式。虽然我们投入了很多精力来支持旧枚举(而不推荐它们),但仍然有可能有人使用了无法像现在这样使用Python枚举的情况。为了避免人们设置环境标志来完全禁用这个功能,我们实现了一种逐步选择每个枚举函数组合,并以一组特定的标志的方式。

可能的枚举标志#

这是控制创建Python枚举时所使用的所有标志的表。

标志名称

ENOPT_OLD_ENUM

0x00

(False) 6.6版PySide后不再可能

ENOPT_NEW_ENUM

0x01

(True) PySide 6.4的默认值,完整实现

ENOPT_INHERIT_INT

0x02

将所有枚举转为IntEnum,并将标志转为IntFlag

ENOPT_GLOBAL_SHORTCUT

0x04

重新添加全局枚举的快捷方式

ENOPT_SCOPED_SHORTCUT

0x08

重新添加作用域枚举的快捷方式

ENOPT_NO_FAKESHORTCUT

0x10

不要伪造重命名(宽恕模式)

ENOPT_NO_FAKERENAMES

0x20

不要伪造快捷方式(宽恕模式)

ENOPT_NO_ZERODEFAULT

0x40

不要使用零默认值(宽恕模式)

ENOPT_NO_MISSING

0x80

不允许枚举中缺少值

可以定义这样的标志集,无论是通过环境变量PYSIDE6_OPTION_PYTHON_ENUM还是通过Python变量sys.pyside6_option_python_enum在导入PySide6之前设置。环境变量也支持使用ast.literal_eval通过任意整数表达式。

ENOPT_OLD_ENUM (0x00)#

此选项完全禁用新枚举实现。尽管这是一个有效的选项,但我们想尽可能避免它。目标是最终删除旧实现。为此,我们已经将枚举实现的单个功能作为标志可供访问。这样,如果用户报告问题,我们可能能够在相应扩展枚举支持之前提供临时解决方案。

ENOPT_NEW_ENUM (0x01)#

在完美的世界中,没有人会选择除了这个默认设置之外的任何东西。不幸的是,现实并不总是这样。这就是为什么存在以下标志。

最可能需要的标志#

如果存在错误,它们可能是以下情况之一:存在需要IntEnum的隐含假设,或者使用了无法用技巧替换的全局枚举。

ENOPT_INHERIT_INT (0x02)#

当此标志被设置时,所有 enum.Enum/enum.Flag 类将被转换为 enum.IntEnum/enum.IntFlag。这解决了在切换到Python枚举时最可能出现的兼容性问题。旧的Shiboken枚举始终继承自int,但大多数Python枚举并不如此。

Python开发者做出的决定是不让枚举默认继承自int,因为没有顺序应该被暗示。在大多数情况下,可以通过使用值属性或更优的升级方式来避免继承自int:在需要整型参数的函数中使用 AnEnum.AnInstance.value 之前,你可以通过 AnEnum(int_arg) 将整数转换为枚举实例,并在比较中使用该实例。

但是,存在一些情况下这是不可能的,并且PySide中也没有显式的支持。在这种情况下,你可以使用这个标志作为替代方案,直到我们有实现替代方案为止。

ENOPT_GLOBAL_SHORTCUT (0x04)#

在Python枚举实现之初,我们继续支持Shiboken枚举的快捷行为:枚举常量被映射到封装作用域中。这一行为后来在容错模式下被模拟。对于PySide类的枚举类来说这很正常,但对于直接在模块级别上的枚举类来说,没有好的方法来实现容错。

对于全局枚举,不太可能隐藏错误,因为它们在导入时应该已经产生错误。但如果你无法接触到源代码,这个标志可以帮助你。

0x6的标志值可能会解决大多数问题。

为了完整性而设置的标志#

以下标志补充了Python枚举的描述。它们本质上服务于更好地理解实现,并使其完全透明和可定制。

ENOPT_SCOPED_SHORTCUT (0x08)#

为了完整性,我们也支持映射作用域枚举,尽管这一行为已经被容错模式所替代。如果您想尝试此功能,请也使用ENOPT_NO_FAKESHORTCUT标志(0x10),否则此标志的效果将保持不可见。

ENOPT_NO_FAKERENAMES (0x10)#

容错模式模仿将 Enum.Flag 类重命名回Shiboken的QFlags结构,这些结构具有略微不同的名称。因此,当使用这样的废弃名称时,系统会在内部用新的 enum.Flag 结构替换它。除非引发了特殊的边界问题,这种替换应该可以正常工作。

要查看重命名的效果,可以使用此标志将其关闭。

ENOPT_NO_ZERODEFAULT (0x40)#

作为容错模式的一部分,Python枚举可以通过无参数调用创建,尽管Python枚举在调用时实际上强制使用参数。

如果设置此标志以禁用它,可以检查此效果。

ENOPT_NO_MISSING (0x80)#

在某些情况下,Shiboken枚举会使用缺失值。在 enum.Flag 结构中,这已经是允许的,因为我们已经设置了 FlagBoundary.KEEP 标志(请参阅 enum.py)。

正常的 enum.Enum 结构没有这项功能,但 enum 模块允许传递一个 _missing_ 函数来自定义。

我们处理这种情况的方法是创建一个与初始名称相同且没有名称的新 enum.Enum 类实例,并使用属性设置来模拟它具有相同的类型。以这种方式创建的额外实例将被记录在类字典 _sbk_missing_ 中,以保持其唯一性。

如果您设置了此标志,您将看到未定义 _missing_ 函数的效果。