Skip to content

Confusing behaviour for sentinel constructed from string subclass #149549

@Dutcho

Description

@Dutcho

Bug report

Bug description:

Constructing a sentinel (new in 3.15 beta 1) from a str subclass works:

class MyStr(str):
    def __str__(self) -> str:
        return f'str {super().__str__()}'

    def __repr__(self) -> str:
        return f'repr {super().__repr__()}'


MISSING = sentinel(MyStr('MISSING'))

As per spec, the sentinel's name is the constructor's argument, i.e. MyStr:

print(type(MISSING.__name__), MISSING.__name__, repr(MISSING.__name__))
# <class '__main__.MyStr'> str MISSING repr 'MISSING'

However, the resulting sentinel's representation is confusing:

print(MISSING, [MISSING], {MISSING}, str(MISSING), repr(MISSING))
# MISSING [MISSING] {MISSING} str MISSING str MISSING
  • straight output (MISSING) gives the __name__'s super(): MISSING
  • same for embedded ([MISSING], {MISSING})
  • but str() and repr() return MyStr __name__, which then becomes 'str MISSING' in both cases

I don't know whether using a MyStr subclass is out of sentinel's scope (the PEP doesn't exclude AFAIK, but if so, then I suggest it should reject at construction), or that the output (different for MISSING and MISSING.__name__) can even be considered a bug. But it sure confused me!

CPython versions tested on:

3.15

Operating systems tested on:

Windows

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.15pre-release feature fixes, bugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions