枚举功能集

新Python枚举的开发以一系列补丁的形式进行。虽然我们投入了大量精力来支持旧枚举(而不推广它们),但仍然有可能存在某些情况下无法使用当前的Python枚举。为了避免人们设置环境标志完全禁用此功能,我们实现了一种方法,通过一组特定的标志逐步选择每个枚举函数的组合。

可能的枚举标志

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

标志名称

ENOPT_OLD_ENUM

0x00

(错误) 自 PySide 6.6 起不再可能

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定义,或者在导入PySide6之前通过Python变量sys.pyside6_option_python_enum设置。环境变量还支持通过使用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继承,因为不应该暗示任何顺序。在大多数情况下,可以通过使用value属性或更好的提升来避免从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_函数的效果。