Skip to content

Commit

Permalink
Fix class decorator for classmethod overrides (#404)
Browse files Browse the repository at this point in the history
Co-authored-by: Adam Johnson <[email protected]>
  • Loading branch information
bp72 and adamchainz authored Mar 1, 2024
1 parent 46c66af commit 3fbd386
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ Changelog

Thanks to Konstantin Baikov in `PR #424 <https://github.com/adamchainz/time-machine/pull/424>`__.

* Fix class decorator for classmethod overrides.

Thanks to Pavel Bitiukov for the reproducer in `PR #404 <https://github.com/adamchainz/time-machine/pull/404>`__.

* Avoid calling deprecated ``uuid._load_system_functions()`` on Python 3.9+.

Thanks to Nikita Sobolev for the ping in `CPython Issue #113308 <https://github.com/python/cpython/issues/113308>`__.
Expand Down
10 changes: 6 additions & 4 deletions src/time_machine/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,24 +293,26 @@ def __call__(
raise TypeError("Can only decorate unittest.TestCase subclasses.")

# Modify the setUpClass method
orig_setUpClass = wrapped.setUpClass
orig_setUpClass = wrapped.setUpClass.__func__ # type: ignore[attr-defined]

@functools.wraps(orig_setUpClass)
def setUpClass(cls: type[TestCase]) -> None:
self.__enter__()
try:
orig_setUpClass()
orig_setUpClass(cls)
except Exception:
self.__exit__(*sys.exc_info())
raise

wrapped.setUpClass = classmethod(setUpClass) # type: ignore[assignment]

orig_tearDownClass = wrapped.tearDownClass
orig_tearDownClass = (
wrapped.tearDownClass.__func__ # type: ignore[attr-defined]
)

@functools.wraps(orig_tearDownClass)
def tearDownClass(cls: type[TestCase]) -> None:
orig_tearDownClass()
orig_tearDownClass(cls)
self.__exit__(None, None, None)

wrapped.tearDownClass = classmethod( # type: ignore[assignment]
Expand Down
24 changes: 24 additions & 0 deletions tests/test_time_machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,30 @@ class Something:
assert excinfo.value.args == ("Can only decorate unittest.TestCase subclasses.",)


@time_machine.travel(EPOCH)
class ClassDecoratorInheritanceBase(TestCase):
prop: bool

@classmethod
def setUpClass(cls):
super().setUpClass()
cls.setUpTestData()

@classmethod
def setUpTestData(cls) -> None:
cls.prop = True


class ClassDecoratorInheritanceTests(ClassDecoratorInheritanceBase):
@classmethod
def setUpTestData(cls) -> None:
super().setUpTestData()
cls.prop = False

def test_ineheritance_correctly_rebound(self):
assert self.prop is False


class TestMethodDecorator:
@time_machine.travel(EPOCH + 95.0)
def test_method_decorator(self):
Expand Down

0 comments on commit 3fbd386

Please sign in to comment.