How to use contextlib.contextmanager with a classmethod?
Asked Answered
A

1

7

See the below Python 3.10 snippet:

import contextlib

class Foo:
    @contextlib.contextmanager
    @classmethod
    def state(cls):
        try:
            yield
        finally:
            pass

with Foo.state():
    pass

It throws a TypeError:

Traceback (most recent call last):
  File "/path/to/code/play/quick_play.py", line 12, in <module>
    with Foo.state():
  File "/path/to/.pyenv/versions/3.10.5/lib/python3.10/contextlib.py", line 281, in helper
    return _GeneratorContextManager(func, args, kwds)
  File "/path/to/.pyenv/versions/3.10.5/lib/python3.10/contextlib.py", line 103, in __init__
    self.gen = func(*args, **kwds)
TypeError: 'classmethod' object is not callable

Is it possible to decorate a classmethod with contextlib.contextmanager? And if yes, how can it be done?

Adulterine answered 4/10, 2022 at 17:47 Comment(2)
Just reverse the two decorators.Haimes
Related: #4732311Astrodome
A
9

This should work:

import contextlib

class Foo:
    @classmethod
    @contextlib.contextmanager
    def state(cls):
        try:
            print("A")
            yield
            print("C")
        finally:
            pass

with Foo.state():
    print("B")

This prints A B C.

Astrodome answered 22/2, 2023 at 19:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.