Skip to content

Commit

Permalink
Merge pull request #676 from DanielYang59/deprecation-msg
Browse files Browse the repository at this point in the history
Extend `dev.deprecated` to decorate classes and improve message
  • Loading branch information
shyuep committed May 24, 2024
2 parents b90b3b0 + 37fdad7 commit 25f82b3
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 6 deletions.
39 changes: 33 additions & 6 deletions monty/dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from __future__ import annotations

import functools
import inspect
import logging
import os
import subprocess
Expand Down Expand Up @@ -64,9 +65,9 @@ def _is_in_owner_repo() -> bool:
owner_repo = (
result.stdout.decode("utf-8")
.strip()
.lstrip("https://github.com/") # https clone
.lstrip("git@github.com:") # ssh clone
.rstrip(".git") # ssh clone
.lstrip("https://github.com/") # HTTPS clone
.lstrip("git@github.com:") # SSH clone
.rstrip(".git") # SSH clone
)

return owner_repo == os.getenv("GITHUB_REPOSITORY")
Expand Down Expand Up @@ -103,27 +104,53 @@ def craft_message(
r = replacement.__func__
else:
r = replacement
msg += f"; use {r.__name__} in {r.__module__} instead."

if deadline is None:
msg += "; use " # for better formatting
else:
msg += "Use "
msg += f"{r.__name__} in {r.__module__} instead."

if message:
msg += "\n" + message
return msg

def deprecated_decorator(old: Callable) -> Callable:
def deprecated_function_decorator(old: Callable) -> Callable:
def wrapped(*args, **kwargs):
msg = craft_message(old, replacement, message, _deadline)
warnings.warn(msg, category=category, stacklevel=2)
return old(*args, **kwargs)

return wrapped

def deprecated_class_decorator(cls: Type) -> Type:
original_init = cls.__init__

def new_init(self, *args, **kwargs):
msg = craft_message(cls, replacement, message, _deadline)
warnings.warn(msg, category=category, stacklevel=2)
original_init(self, *args, **kwargs)

cls.__init__ = new_init
return cls

# Convert deadline to datetime type
_deadline = datetime(*deadline) if deadline is not None else None

# Raise CI warning after removal deadline
raise_deadline_warning()

return deprecated_decorator
def decorator(target: Callable) -> Callable:
if inspect.isfunction(target):
return deprecated_function_decorator(target)
elif inspect.isclass(target):
return deprecated_class_decorator(target)
else:
raise TypeError(
"The @deprecated decorator can only be applied to classes or functions"
)

return decorator


class requires:
Expand Down
17 changes: 17 additions & 0 deletions tests/test_dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,23 @@ def classmethod_b(cls):
with pytest.warns(DeprecationWarning):
assert TestClass_deprecationwarning().classmethod_b() == "b"

def test_deprecated_class(self):
class TestClassNew:
"""A dummy class for tests."""

def method_a(self):
pass

@deprecated(replacement=TestClassNew)
class TestClassOld:
"""A dummy class for tests."""

def method_b(self):
pass

with pytest.warns(FutureWarning, match="TestClassOld is deprecated"):
TestClassOld()

def test_deprecated_deadline(self, monkeypatch):
with pytest.raises(DeprecationWarning):
with patch("subprocess.run") as mock_run:
Expand Down

0 comments on commit 25f82b3

Please sign in to comment.