-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add an optional arg deadline
to dev.deprecated
to raise warning after deadline
#631
Changes from 15 commits
36131f7
05d77e0
a51fb8d
2956082
a39ca06
4bdc371
2088f8d
cb91417
e97cfe9
783a982
d5b463b
5cca0dc
2901b9d
bb4af84
59458a2
a37e12c
0a13730
a247764
247b297
5d62012
80bfea5
de31119
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,21 +5,33 @@ | |
|
||
import functools | ||
import logging | ||
import os | ||
import sys | ||
import subprocess | ||
import warnings | ||
from datetime import datetime | ||
from typing import Callable, Optional, Type | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
def deprecated(replacement=None, message=None, category=FutureWarning): | ||
def deprecated( | ||
replacement: Optional[Callable] = None, | ||
message: str = "", | ||
deadline: Optional[tuple[int, int, int]] = None, | ||
category: Type[Warning] = FutureWarning, | ||
): | ||
""" | ||
Decorator to mark classes or functions as deprecated, with a possible replacement. | ||
|
||
Args: | ||
replacement (callable): A replacement class or method. | ||
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. | ||
category (Warning): Choose the category of the warning to issue. Defaults | ||
to FutureWarning. Another choice can be DeprecationWarning. NOte that | ||
to FutureWarning. Another choice can be DeprecationWarning. Note that | ||
FutureWarning is meant for end users and is always shown unless silenced. | ||
DeprecationWarning is meant for developers and is never shown unless | ||
python is run in developmental mode or the filter is changed. Make | ||
|
@@ -29,8 +41,60 @@ def deprecated(replacement=None, message=None, category=FutureWarning): | |
Original function, but with a warning to use the updated class. | ||
""" | ||
|
||
def craft_message(old, replacement, message): | ||
def _convert_date(date: tuple[int, int, int]) -> datetime: | ||
DanielYang59 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"""Convert date as int tuple (yyyy, MM, dd) to datetime type.""" | ||
|
||
return datetime(*date) | ||
|
||
def 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"], | ||
DanielYang59 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
stdout=subprocess.PIPE, | ||
) | ||
owner_repo = ( | ||
result.stdout.decode("utf-8") | ||
.strip() | ||
.lstrip("[email protected]:") | ||
.rstrip(".git") | ||
) | ||
|
||
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") | ||
and datetime.now() > _deadline | ||
and _is_in_owner_repo() | ||
): | ||
raise DeprecationWarning( | ||
"This function should have been removed on {deadline:%Y-%m-%d}." | ||
) | ||
|
||
def craft_message( | ||
old: Callable, | ||
replacement: Callable, | ||
message: str, | ||
deadline: datetime, | ||
): | ||
msg = f"{old.__name__} is deprecated" | ||
|
||
if deadline is not None: | ||
msg += f", and will be removed on {deadline:%Y-%m-%d}\n" | ||
|
||
if replacement is not None: | ||
if isinstance(replacement, property): | ||
r = replacement.fget | ||
|
@@ -39,18 +103,25 @@ def craft_message(old, replacement, message): | |
else: | ||
r = replacement | ||
msg += f"; use {r.__name__} in {r.__module__} instead." | ||
if message is not None: | ||
|
||
if message: | ||
msg += "\n" + message | ||
return msg | ||
|
||
def deprecated_decorator(old): | ||
def deprecated_decorator(old: Callable): | ||
def wrapped(*args, **kwargs): | ||
msg = craft_message(old, replacement, message) | ||
msg = craft_message(old, replacement, message, _deadline) | ||
warnings.warn(msg, category=category, stacklevel=2) | ||
return old(*args, **kwargs) | ||
|
||
return wrapped | ||
|
||
# Convert deadline to datetime | ||
_deadline = _convert_date(deadline) if deadline is not None else None | ||
|
||
# Raise a CI warning after removal deadline | ||
deadline_warning() | ||
|
||
return deprecated_decorator | ||
|
||
|
||
|
@@ -101,7 +172,7 @@ def decorated(*args, **kwargs): | |
return decorated | ||
|
||
|
||
def install_excepthook(hook_type="color", **kwargs): | ||
def install_excepthook(hook_type: str = "color", **kwargs): | ||
""" | ||
This function replaces the original python traceback with an improved | ||
version from Ipython. Use `color` for colourful traceback formatting, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -328,7 +328,7 @@ def __get_pydantic_core_schema__(cls, source_type, handler): | |
if core_schema is None: | ||
raise RuntimeError("Pydantic >= 2.0 is required for validation") | ||
|
||
s = core_schema.general_plain_validator_function(cls.validate_monty_v2) | ||
s = core_schema.with_info_plain_validator_function(cls.validate_monty_v2) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replaced from: test_json.py::TestJson::test_pydantic_integrations
/home/yang/Developers/monty/monty/json.py:331: DeprecationWarning: `general_plain_validator_function` is deprecated, use `with_info_plain_validator_function` instead.
s = core_schema.general_plain_validator_function(cls.validate_monty_v2) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should fix #598. |
||
|
||
return core_schema.json_or_python_schema(json_schema=s, python_schema=s) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,9 @@ | ||
pytest | ||
pytest-cov | ||
coverage | ||
coveralls | ||
pycodestyle | ||
mypy | ||
pydocstyle | ||
pydantic | ||
flake8 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let me know if they're still needed anywhere. Thanks! |
||
black | ||
pylint | ||
torch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the docs automatically generated? It seems this method doesn't exist anymore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, the docs are auto-generated from doc strings. possible that this needs to be rerun @shyuep?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the input.