-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add aliases function for backward compatibility
- Loading branch information
Showing
3 changed files
with
109 additions
and
0 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
# (C) Copyright 2024 Anemoi contributors. | ||
# | ||
# This software is licensed under the terms of the Apache Licence Version 2.0 | ||
# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. | ||
# | ||
# In applying this licence, ECMWF does not waive the privileges and immunities | ||
# granted to it by virtue of its status as an intergovernmental organisation | ||
# nor does it submit to any jurisdiction. | ||
|
||
from __future__ import annotations | ||
|
||
import functools | ||
from typing import Any | ||
from typing import Callable | ||
|
||
|
||
def aliases( | ||
aliases: dict[str, str | list[str]] | None = None, **kwargs: str | list[str] | ||
) -> Callable[[Callable], Callable]: | ||
"""Alias keyword arguments in a function call. | ||
Allows for dynamically renaming keyword arguments in a function call. | ||
Parameters | ||
---------- | ||
aliases : dict[str, str | list[str]] | None, optional | ||
Key, value pair of aliases, with keys being the true name, and value being a str or list of aliases, | ||
by default None | ||
**kwargs : str | list[str] | ||
Kwargs form of aliases | ||
Returns | ||
------- | ||
Callable | ||
Decorator function that renames keyword arguments in a function call. | ||
Raises | ||
------ | ||
ValueError | ||
If the aliasing would result in duplicate keys. | ||
Examples | ||
-------- | ||
```python | ||
@aliases(a="b", c=["d", "e"]) | ||
def func(a, c): | ||
return a, c | ||
func(a=1, c=2) # (1, 2) | ||
func(b=1, d=2) # (1, 2) | ||
``` | ||
""" | ||
|
||
if aliases is None: | ||
aliases = {} | ||
aliases.update(kwargs) | ||
|
||
aliases = {v: k for k, vs in aliases.items() for v in (vs if isinstance(vs, list) else [vs])} | ||
|
||
def decorator(func: Callable) -> Callable: | ||
@functools.wraps(func) | ||
def wrapper(*args, **kwargs) -> Any: | ||
keys = kwargs.keys() | ||
for k in set(keys).intersection(set(aliases.keys())): | ||
if aliases[k] in keys: | ||
raise ValueError( | ||
f"When aliasing {k} with {aliases[k]} duplicate keys were present. Cannot include both." | ||
) | ||
kwargs[aliases[k]] = kwargs.pop(k) | ||
|
||
return func(*args, **kwargs) | ||
|
||
return wrapper | ||
|
||
return decorator |
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,32 @@ | ||
# (C) Copyright 2024 Anemoi contributors. | ||
# | ||
# This software is licensed under the terms of the Apache Licence Version 2.0 | ||
# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. | ||
# | ||
# In applying this licence, ECMWF does not waive the privileges and immunities | ||
# granted to it by virtue of its status as an intergovernmental organisation | ||
# nor does it submit to any jurisdiction. | ||
|
||
import pytest | ||
|
||
from anemoi.utils.compatibility import aliases | ||
|
||
|
||
def test_aliases() -> None: | ||
|
||
@aliases(a="b", c=["d", "e"]) | ||
def func(a, c): | ||
return a, c | ||
|
||
assert func(a=1, c=2) == (1, 2) | ||
assert func(a=1, d=2) == (1, 2) | ||
assert func(b=1, d=2) == (1, 2) | ||
|
||
|
||
def test_duplicate_values() -> None: | ||
@aliases(a="b", c=["d", "e"]) | ||
def func(a, c): | ||
return a, c | ||
|
||
with pytest.raises(ValueError): | ||
func(a=1, b=2) |