I really like the proposed Sentinel
class because when using an Enum
for a singleton type it always annoyingly shows up in type signatures and autogenerated documentation.
However I think not supporting Literal
as mentioned in Specific type signatures for each sentinel value is a big mistake, since it would mean Sentinel
could not actually replace Enum
if you require the ability to use the type in Literal
... which I think is a very common requirement.
Python notably does not support algebraic data types. For example in Rust you could just define:
enum Submodule {
Specific(String),
All,
AllRecursively,
}
the closest you can do in Python is to use the Union
type, for example Union[str, Literal[DirectSubmodules, AllSubmodules]]
, now instead of having to abuse Enum
for this as follows:
class _ModuleSpec(Enum):
DirectSubmodules = 'DirectSubmodules'
AllSubmodules = 'AllSubmodules'
DirectSubmodules = _ModuleSpec.DirectSubmodules
AllSubmodules = _ModuleSpec.AllSubmodules
(which would result in _ModuleSpec
showing up in IDE tooltips and autogenerated API documentation and thus potentially confuse users), it would be great if you could instead just do:
DirectSubmodules = Sentinel('DirectSubmodules')
AllSubmodules = Sentinel('AllSubmodules')
and still be able to use Literal[DirectSubmodules, AllSubmodules]
.
The PEP mentions that Literal
support has been dropped from the PEP due to concerns voiced on the mailing list. While I cannot really comment on the challenges of special casing Literal
, I think this additional complexity would definitely be worth it to make Sentinel
as useful as Enum
and allow it to replace it for cases where you do not actually want to introduce an enum type.