Skip to content

Behavioral differences between the with-statement and ExitStack.enter_context #144386

@gottadiveintopython

Description

@gottadiveintopython

Bug report

Bug description:

I noticed a behavioral difference between the (async) with statement and (Async)ExitStack. The with statement correctly recognizes context manager methods (__enter__, __exit__, __aenter__, and __aexit__) even when they are defined via __slots__, whereas (Async)ExitStack does not.

class SlotsCM:
    __slots__ = ("__enter__", "__exit__", )

    def __init__(self):
        self.__enter__ = self.__exit__ = lambda *__: None


# This works
with SlotsCM():
    pass


# This doesn't.
from contextllib import ExitStack
with ExitStack() as stack:
    stack.enter_context(SlotsCM())
Traceback (most recent call last):
  File "xxxx.py", line 16, in <module>
    stack.enter_context(SlotsCM())
    ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
  File "......../contextlib.py", line 530, in enter_context
    result = _enter(cm)
TypeError: 'member_descriptor' object is not callable

Furthermore, both (async) with-statement and (Async)ExitStack don't suppot those special dunder methods stored in __dict__. You can verify from this repository:
https://github.com/gottadiveintopython/invest-context-manager

CPython versions tested on:

3.13

Operating systems tested on:

Linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions