Skip to content

Commit a533f4c

Browse files
committed
Add deprecation decorators
1 parent 93cc635 commit a533f4c

File tree

3 files changed

+109
-0
lines changed

3 files changed

+109
-0
lines changed

parcels/util/_helpers.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
"""Internal helpers for Parcels."""
2+
3+
import functools
4+
import warnings
5+
from typing import Callable
6+
7+
PACKAGE = "Parcels"
8+
9+
10+
def deprecated(msg: str = "") -> Callable:
11+
"""Decorator marking a function as being deprecated
12+
13+
Parameters
14+
----------
15+
msg : str, optional
16+
Custom message to append to the deprecation warning.
17+
18+
Examples
19+
--------
20+
```
21+
@deprecated("Please use `another_function` instead")
22+
def some_old_function(x, y):
23+
return x + y
24+
25+
@deprecated()
26+
def some_other_old_function(x, y):
27+
return x + y
28+
```
29+
"""
30+
if msg:
31+
msg = " " + msg
32+
33+
def decorator(func):
34+
@functools.wraps(func)
35+
def wrapper(*args, **kwargs):
36+
msg_formatted = (
37+
f"`{func.__qualname__}` is deprecated and will be removed in a future release of {PACKAGE}.{msg}"
38+
)
39+
40+
warnings.warn(msg_formatted, category=DeprecationWarning, stacklevel=2)
41+
return func(*args, **kwargs)
42+
43+
return wrapper
44+
45+
return decorator
46+
47+
48+
def deprecated_made_private(func: Callable) -> Callable:
49+
return deprecated(
50+
"It was identified as part of the internal API as it is not expected to be directly used by "
51+
"the end-user. If you feel that you use this code directly in your scripts, please "
52+
"comment on our tracking issue at <>." # TODO: Add tracking issue
53+
)(func)

tests/util/__init__.py

Whitespace-only changes.

tests/util/test_helpers.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import pytest
2+
3+
from parcels.util._helpers import deprecated, deprecated_made_private
4+
5+
# Write me tests to test deprecated and depreacted_made_private decorators
6+
# They should raise a DeprecationWarning, and also have the function name (or in the case of a method, {class_name}.{method_name}) in the warning message
7+
8+
9+
def test_deprecated():
10+
class SomeClass:
11+
@deprecated()
12+
def some_method(self, x, y):
13+
return x + y
14+
15+
@staticmethod
16+
@deprecated()
17+
def some_static_method(x, y):
18+
return x + y
19+
20+
@property
21+
@deprecated()
22+
def some_property(self):
23+
return 2
24+
25+
@deprecated()
26+
def some_function(x, y):
27+
return x + y
28+
29+
with pytest.warns(DeprecationWarning) as record:
30+
SomeClass().some_method(1, 2)
31+
assert "SomeClass.some_method" in record[0].message.args[0]
32+
33+
with pytest.warns(DeprecationWarning) as record:
34+
SomeClass.some_static_method(1, 2)
35+
assert "SomeClass.some_static_method" in record[0].message.args[0]
36+
37+
with pytest.warns(DeprecationWarning) as record:
38+
_ = SomeClass().some_property
39+
assert "SomeClass.some_property" in record[0].message.args[0]
40+
41+
with pytest.warns(DeprecationWarning) as record:
42+
some_function(1, 2)
43+
assert "some_function" in record[0].message.args[0]
44+
45+
with pytest.warns(DeprecationWarning) as record:
46+
some_function(1, 2)
47+
assert "some_function" in record[0].message.args[0]
48+
49+
50+
def test_deprecated_made_private():
51+
@deprecated_made_private
52+
def some_function(x, y):
53+
return x + y
54+
55+
with pytest.warns(DeprecationWarning):
56+
some_function(1, 2)

0 commit comments

Comments
 (0)