Skip to content
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

updated deprecation_alias #562

Merged
merged 4 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/spatialdata/_core/spatialdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from spatialdata._core._elements import Images, Labels, Points, Shapes, Tables
from spatialdata._logging import logger
from spatialdata._types import ArrayLike, Raster_T
from spatialdata._utils import _error_message_add_element, deprecation_alias
from spatialdata._utils import _deprecation_alias, _error_message_add_element
from spatialdata.models import (
Image2DModel,
Image3DModel,
Expand Down Expand Up @@ -108,7 +108,7 @@ class SpatialData:
annotation directly.
"""

@deprecation_alias(table="tables")
@_deprecation_alias(table="tables", version="0.1.0")
def __init__(
self,
images: dict[str, Raster_T] | None = None,
Expand Down Expand Up @@ -684,7 +684,7 @@ def _write_transformations_to_disk(self, element: SpatialElement) -> None:
" not found in Zarr storage"
)

@deprecation_alias(filter_table="filter_tables")
@_deprecation_alias(filter_table="filter_tables", version="0.1.0")
def filter_by_coordinate_system(
self, coordinate_system: str | list[str], filter_tables: bool = True, include_orphan_tables: bool = False
) -> SpatialData:
Expand Down Expand Up @@ -1572,7 +1572,7 @@ def _find_element(self, element_name: str) -> tuple[str, str, SpatialElement | A
raise KeyError(f"Could not find element with name {element_name!r}")

@classmethod
@deprecation_alias(table="tables")
@_deprecation_alias(table="tables", version="0.1.0")
def init_from_elements(
cls, elements: dict[str, SpatialElement], tables: AnnData | dict[str, AnnData] | None = None
) -> SpatialData:
Expand Down
24 changes: 16 additions & 8 deletions src/spatialdata/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,14 +215,15 @@ def _inplace_fix_subset_categorical_obs(subset_adata: AnnData, original_adata: A


# TODO: change to paramspec as soon as we drop support for python 3.9, see https://stackoverflow.com/a/68290080
def deprecation_alias(**aliases: str) -> Callable[[Callable[..., RT]], Callable[..., RT]]:
def _deprecation_alias(**aliases: str) -> Callable[[Callable[..., RT]], Callable[..., RT]]:
"""
Decorate a function to warn user of use of arguments set for deprecation.

Parameters
----------
aliases
Deprecation argument aliases to be mapped to the new arguments.
Deprecation argument aliases to be mapped to the new arguments. Must include version with as value a string
indicating the version from which the old argument will be deprecated.

Returns
-------
Expand All @@ -238,7 +239,7 @@ def deprecation_alias(**aliases: str) -> Callable[[Callable[..., RT]], Callable[
Assuming we have an argument 'table' set for deprecation and we want to warn the user and substitute with 'tables':

```python
@deprecation_alias(table="tables")
@_deprecation_alias(table="tables", version="0.1.0")
def my_function(tables: AnnData | dict[str, AnnData]):
pass
```
Expand All @@ -248,28 +249,35 @@ def deprecation_decorator(f: Callable[..., RT]) -> Callable[..., RT]:
@functools.wraps(f)
def wrapper(*args: Any, **kwargs: Any) -> RT:
class_name = f.__qualname__
rename_kwargs(f.__name__, kwargs, aliases, class_name)
library = f.__module__.split(".")[0]
alias_copy = aliases.copy()
version = alias_copy.pop("version") if alias_copy.get("version") is not None else None
if version is None:
raise ValueError("version for deprecation must be specified")
rename_kwargs(f.__name__, kwargs, alias_copy, class_name, library, version)
return f(*args, **kwargs)

return wrapper

return deprecation_decorator


def rename_kwargs(func_name: str, kwargs: dict[str, Any], aliases: dict[str, str], class_name: None | str) -> None:
def rename_kwargs(
func_name: str, kwargs: dict[str, Any], aliases: dict[str, str], class_name: None | str, library: str, version: str
) -> None:
"""Rename function arguments set for deprecation and gives warning in case of usage of these arguments."""
for alias, new in aliases.items():
if alias in kwargs:
class_name = class_name + "." if class_name else ""
if new in kwargs:
raise TypeError(
f"{class_name}{func_name} received both {alias} and {new} as arguments!"
f" {alias} is being deprecated in SpatialData version 0.1, only use {new} instead."
f" {alias} is being deprecated in {library} {version}, only use {new} instead."
)
warnings.warn(
message=(
f"`{alias}` is being deprecated as an argument to `{class_name}{func_name}` in SpatialData "
f"version 0.1, switch to `{new}` instead."
f"`{alias}` is being deprecated as an argument to `{class_name}{func_name}` in {library} version "
f"{version}, switch to `{new}` instead."
),
category=DeprecationWarning,
stacklevel=3,
Expand Down
Loading