-
Notifications
You must be signed in to change notification settings - Fork 76
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 task to check for deprecations #1044
Closed
Closed
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
b9f073d
Add the deprecated decorator
1117f07
Use decorator with already deprecated Dummy
bc248da
Add script to list deprecations
d603722
Add task to Makefile
7175396
Remove leftover
29c8de6
Move to publish submake
b32161d
Add test to find deprecated
77626a5
Raise an error when a deprecation expired
4741a89
Test deprecation in isolation
3f8c523
Move check to the tasks package
049f2e8
Deprecate Dummy
9651bfa
Add the attr rst directive
a39b8c7
Do not use print
42444f8
Add typing_extensions
dbbc29f
Add the task protocol
345cedc
Type-check the deprecation check
09a636f
Document the deprecation check
5c63310
Add task to circleci
c96d04d
Use literals for exit codes
f7a1c7f
Add progress bar
84d3d5a
Colorise
16dde3c
Split check/progress
6f44c29
Fix check deprecated test
3b4c7d0
Bump major to 36.0.0
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import functools | ||
import warnings | ||
import typing | ||
from typing import Any, Callable, Sequence, TypeVar | ||
|
||
T = Callable[..., Any] | ||
F = TypeVar("F", bound = T) | ||
|
||
|
||
class deprecated: | ||
"""Allows (soft) deprecating a functionality of OpenFisca. | ||
|
||
Attributes: | ||
since: | ||
Since when the functionality is deprecated. | ||
expires: | ||
When will it be removed forever? | ||
|
||
Args: | ||
since: | ||
Since when the functionality is deprecated. | ||
expires: | ||
When will it be removed forever? Note that this value, if set to a | ||
valid semantic version, it has to be a major one. | ||
|
||
Raises: | ||
ValueError: | ||
When :attr:`expires` is set to a version, but not to a major one. | ||
|
||
|
||
Examples: | ||
>>> @deprecated(since = "35.5.0", expires = "in the future") | ||
... def obsolete(): | ||
... return "I'm obsolete!" | ||
|
||
>>> repr(obsolete) | ||
'<function obsolete ...>' | ||
|
||
>>> str(obsolete) | ||
'<function obsolete ...>' | ||
|
||
.. versionadded:: 36.0.0 | ||
|
||
""" | ||
|
||
since: str | ||
expires: str | ||
|
||
def __init__(self, *, since: str, expires: str) -> None: | ||
self.since = since | ||
self.expires = self._parse(expires) | ||
|
||
def __call__(self, function: F) -> F: | ||
"""Wraps a function to return another one, decorated. | ||
|
||
Args: | ||
function: The function or method to decorate. | ||
|
||
Returns: | ||
:obj:`callable`: The decorated function. | ||
|
||
Examples: | ||
>>> def obsolete(): | ||
... return "I'm obsolete!" | ||
|
||
>>> decorator = deprecated( | ||
... since = "35.5.0", | ||
... expires = "in the future", | ||
... ) | ||
|
||
>>> decorator(obsolete) | ||
<function obsolete ...> | ||
|
||
""" | ||
|
||
def wrapper(*args: Any, **kwds: Any) -> Any: | ||
message: Sequence[str] | ||
message = [ | ||
f"{function.__qualname__} has been deprecated since", | ||
f"version {self.since}, and will be removed in", | ||
f"{self.expires}.", | ||
] | ||
|
||
warnings.warn(" ".join(message), DeprecationWarning) | ||
return function(*args, **kwds) | ||
|
||
functools.update_wrapper(wrapper, function) | ||
return typing.cast(F, wrapper) | ||
|
||
@staticmethod | ||
def _parse(expires: str) -> str: | ||
minor: str | ||
patch: str | ||
message: Sequence[str] | ||
|
||
if expires.find(".") == -1: | ||
return expires | ||
|
||
_, minor, patch, *_ = expires.split(".") | ||
|
||
if minor != "0" or patch != "0": | ||
message = [ | ||
"Deprecations can only expire on major releases.", | ||
f"Or, {expires} is not a major one.", | ||
"To learn more about semantic versioning:", | ||
"https://semver.org/" | ||
] | ||
|
||
raise ValueError(" ".join(message)) | ||
|
||
return expires |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,18 @@ | ||
import warnings | ||
from .decorators import deprecated | ||
|
||
|
||
class Dummy: | ||
"""A class that does nothing.""" | ||
"""A class that did nothing. | ||
|
||
Examples: | ||
>>> Dummy() | ||
<openfisca_core.commons.dummy.Dummy object... | ||
|
||
.. deprecated:: 34.7.0 | ||
:class:`.Dummy` has been deprecated and it will be removed in 36.0.0. | ||
|
||
""" | ||
|
||
@deprecated(since = "34.7.0", expires = "36.0.0") | ||
def __init__(self) -> None: | ||
message = [ | ||
"The 'Dummy' class has been deprecated since version 34.7.0,", | ||
"and will be removed in the future.", | ||
] | ||
warnings.warn(" ".join(message), DeprecationWarning) | ||
pass | ||
... |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import re | ||
|
||
import pytest | ||
|
||
from openfisca_core.commons import deprecated | ||
|
||
|
||
def test_deprecated(): | ||
"""The decorated function throws a deprecation warning when used.""" | ||
|
||
since = "yesterday" | ||
expires = "tomorrow" | ||
message = re.compile(f"^.*{since}.*{expires}.*$") | ||
|
||
@deprecated(since = since, expires = expires) | ||
def function(a: int, b: float) -> float: | ||
return a + b | ||
|
||
with pytest.warns(DeprecationWarning, match = message): | ||
assert function(1, 2.) == 3. | ||
|
||
|
||
def test_deprecated_when_illegal(): | ||
"""Raises an error when the deprecation expiration is not a major.""" | ||
|
||
since = "yesterday" | ||
expires = "1.2.3" | ||
message = "Deprecations can only expire on major releases" | ||
|
||
with pytest.raises(ValueError, match = message): | ||
deprecated(since = since, expires = expires) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import pytest | ||
|
||
from openfisca_core.commons import Dummy | ||
|
||
|
||
def test_dummy_deprecation(): | ||
"""Dummy throws a deprecation warning when instantiated.""" | ||
|
||
with pytest.warns(DeprecationWarning): | ||
assert Dummy() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from ._check_deprecated import CheckDeprecated # noqa: F401 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
from __future__ import annotations | ||
|
||
import sys | ||
|
||
import openfisca_tasks as tasks | ||
|
||
from ._progress_bar import ProgressBar | ||
from ._protocols import HasExit, SupportsProgress | ||
|
||
|
||
if __name__ == "__main__": | ||
task: HasExit | ||
task = tasks.__getattribute__(sys.argv[1])() | ||
|
||
progress: SupportsProgress | ||
progress = ProgressBar() | ||
|
||
task(progress) | ||
sys.exit(task.exit) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Not necessary in the CHANGELOG.