Skip to content

Commit

Permalink
drop repo check and warn instead of raise
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielYang59 committed Jan 3, 2025
1 parent 26acf0b commit 65931ce
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 107 deletions.
58 changes: 11 additions & 47 deletions src/monty/dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
import functools
import inspect
import logging
import os
import subprocess
import sys
import warnings
from dataclasses import is_dataclass
Expand All @@ -35,8 +33,8 @@ def deprecated(
replacement (Callable | str): A replacement class or function.
message (str): A warning message to be displayed.
deadline (Optional[tuple[int, int, int]]): Optional deadline for removal
of the old function/class, in format (yyyy, MM, dd). A CI warning would
be raised after this date if is running in code owner' repo.
of the old function/class, in format (yyyy, MM, dd). DeprecationWarning
would be emitted after this date.
category (Warning): Choose the category of the warning to issue. Defaults
to FutureWarning. Another choice can be DeprecationWarning. Note that
FutureWarning is meant for end users and is always shown unless silenced.
Expand All @@ -48,45 +46,6 @@ def deprecated(
Original function, but with a warning to use the updated function.
"""

def raise_deadline_warning() -> None:
"""Raise CI warning after removal deadline in code owner's repo."""

def _is_in_owner_repo() -> bool:
"""Check if is running in code owner's repo.
Only generate reliable check when `git` is installed and remote name
is "origin".
"""

try:
# Get current running repo
result = subprocess.run(
["git", "config", "--get", "remote.origin.url"],
stdout=subprocess.PIPE,
)
owner_repo = (
result.stdout.decode("utf-8")
.strip()
.lstrip("https://github.com/") # HTTPS clone
.lstrip("[email protected]:") # SSH clone
.rstrip(".git") # SSH clone
)

return owner_repo == os.getenv("GITHUB_REPOSITORY")

except (subprocess.CalledProcessError, FileNotFoundError):
return False

# Only raise warning in code owner's repo CI
if (
_deadline is not None
and os.getenv("CI") is not None
and datetime.now() > _deadline
and _is_in_owner_repo()
):
raise DeprecationWarning(
f"This function should have been removed on {_deadline:%Y-%m-%d}."
)

def craft_message(
old: Callable,
replacement: Callable | str,
Expand Down Expand Up @@ -151,10 +110,15 @@ def new_init(self, *args, **kwargs):
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()
_deadline: datetime | None = datetime(*deadline) if deadline is not None else None

# Emit DeprecationWarning after removal deadline
if _deadline is not None and datetime.now() > _deadline:
warnings.warn(
f"This function should have been removed on {_deadline:%Y-%m-%d}.",
DeprecationWarning,
stacklevel=2,
)

def decorator(target: Callable) -> Callable:
if inspect.isfunction(target):
Expand Down
74 changes: 14 additions & 60 deletions tests/test_dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,71 +169,25 @@ def method_b(self):
assert old_class.__doc__ == "A dummy old class for tests."
assert old_class.class_attrib_old == "OLD_ATTRIB"

def test_deprecated_deadline(self, monkeypatch):
with pytest.raises(DeprecationWarning):
with patch("subprocess.run") as mock_run:
monkeypatch.setenv("CI", "true") # mock CI env

# Mock "GITHUB_REPOSITORY"
monkeypatch.setenv("GITHUB_REPOSITORY", "TESTOWNER/TESTREPO")
mock_run.return_value.stdout.decode.return_value = (
"[email protected]:TESTOWNER/TESTREPO.git"
)

@deprecated(deadline=(2000, 1, 1))
def func_old():
pass

@pytest.fixture()
def test_deprecated_deadline_no_warn(self, monkeypatch):
"""Test cases where no warning should be raised."""

# No warn case 1: date before deadline
with warnings.catch_warnings():
with patch("subprocess.run") as mock_run:
monkeypatch.setenv("CI", "true") # mock CI env

# Mock date to 1999-01-01
monkeypatch.setattr(
datetime.datetime, "now", datetime.datetime(1999, 1, 1)
)

# Mock "GITHUB_REPOSITORY"
monkeypatch.setenv("GITHUB_REPOSITORY", "TESTOWNER/TESTREPO")
mock_run.return_value.stdout.decode.return_value = (
"[email protected]:TESTOWNER/TESTREPO.git"
)
def test_deprecated_deadline(self):
with pytest.warns(
DeprecationWarning, match="This function should have been removed"
):

@deprecated(deadline=(2000, 1, 1))
def func_old():
pass

monkeypatch.undo()

# No warn case 2: not in CI env
with warnings.catch_warnings():
with patch("subprocess.run") as mock_run:
monkeypatch.delenv("CI", raising=False)

# Mock "GITHUB_REPOSITORY"
monkeypatch.setenv("GITHUB_REPOSITORY", "TESTOWNER/TESTREPO")
mock_run.return_value.stdout.decode.return_value = (
"[email protected]:TESTOWNER/TESTREPO.git"
)

@deprecated(deadline=(2000, 1, 1))
def func_old_1():
pass
@deprecated(deadline=(2000, 1, 1))
def func_old():
pass

monkeypatch.undo()
def test_deprecated_deadline_no_warn(self):
"""No warning should be raised before deadline."""

# No warn case 3: not in code owner repo
with warnings.catch_warnings():
monkeypatch.setenv("CI", "true")
monkeypatch.delenv("GITHUB_REPOSITORY", raising=False)
warnings.filterwarnings(
"error", "function should have been removed", DeprecationWarning
)

@deprecated(deadline=(2000, 1, 1))
def func_old_2():
@deprecated(deadline=(9999, 1, 1))
def func_old():
pass

def test_requires(self):
Expand Down

0 comments on commit 65931ce

Please sign in to comment.