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

add deprecation warnings for moved objects #654

Merged
merged 1 commit into from
Oct 29, 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
6 changes: 6 additions & 0 deletions mapchete/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import os
from typing import Union

from mapchete.bounds import Bounds
from mapchete.config import MapcheteConfig
from mapchete.errors import Empty, MapcheteNodataTile
from mapchete.executor import Executor, MFuture
Expand All @@ -12,14 +13,18 @@
VectorInput,
VectorInputGroup,
)
from mapchete.grid import Grid
from mapchete.path import MPath
from mapchete.processing import Mapchete, MapcheteProcess
from mapchete.tile import count_tiles
from mapchete.timer import Timer
from mapchete.types import MPathLike
from mapchete.zoom_levels import ZoomLevels

__all__ = [
"Bounds",
"count_tiles",
"Grid",
"Mapchete",
"MapcheteProcess",
"Timer",
Expand All @@ -31,6 +36,7 @@
"RasterInputGroup",
"VectorInput",
"VectorInputGroup",
"ZoomLevels",
]
__version__ = "2024.10.0"

Expand Down
47 changes: 47 additions & 0 deletions mapchete/_deprecated.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import warnings
from functools import wraps
from typing import Callable, TypeVar, Any, cast, Type, Union

# Define a generic type for functions and classes
F = TypeVar("F", bound=Callable[..., Any])
C = TypeVar("C", bound=Type[Any])


def deprecated(reason: str = "") -> Callable[[Union[F, C]], Union[F, C]]:
"""Decorator to mark functions or classes as deprecated.

Args:
reason (str): Optional reason or guidance for deprecation.
Returns:
Callable[[Union[F, C]], Union[F, C]]: The decorated function or class that issues a DeprecationWarning.
"""

def decorator(obj: Union[F, C]) -> Union[F, C]:
message = f"{obj.__name__} is deprecated."
if reason:
message += f" {reason}"

if isinstance(obj, type): # Check if obj is a class
# Decorate a class to show warning on instantiation
original_init = obj.__init__

@wraps(original_init)
def new_init(self, *args: Any, **kwargs: Any) -> None: # pragma: no cover
warnings.warn(message, category=DeprecationWarning, stacklevel=2)
original_init(self, *args, **kwargs)

obj.__init__ = new_init # Replace the original __init__ with new_init
obj.__doc__ = f"DEPRECATED: {reason}\n\n{obj.__doc__}" # Update docstring
return cast(C, obj)

else:
# Decorate a function to show warning on call
@wraps(obj)
def wrapper(*args: Any, **kwargs: Any) -> Any: # pragma: no cover
warnings.warn(message, category=DeprecationWarning, stacklevel=2)
return obj(*args, **kwargs)

wrapper.__doc__ = f"DEPRECATED: {reason}\n\n{obj.__doc__}"
return cast(F, wrapper)

return decorator
6 changes: 6 additions & 0 deletions mapchete/bounds.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,3 +224,9 @@ def intersects(self, other: BoundsLike) -> bool:
or self.bottom <= other.bottom < other.top <= self.top
)
return horizontal and vertical


def bounds_intersect(
bounds1: BoundsLike, bounds2: BoundsLike
) -> bool: # pragma: no cover
return Bounds.from_inp(bounds1).intersects(bounds2)
59 changes: 59 additions & 0 deletions mapchete/io/vector/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from typing import Any, Optional

from mapchete._deprecated import deprecated
from mapchete.io.vector.convert import convert_vector
from mapchete.io.vector.indexed_features import (
IndexedFeatures,
Expand All @@ -10,6 +13,7 @@
read_vector_window,
)
from mapchete.io.vector.write import fiona_write, write_vector_window
from mapchete.types import Geometry, GeometryLike, CRSLike, BoundsLike

__all__ = [
"fiona_read",
Expand All @@ -22,3 +26,58 @@
"read_vector",
"read_union_geometry",
]


@deprecated(
reason="mapchete.vector.io.to_shape has moved to mapchete.geometry.to_shape"
)
def to_shape(geometry: Any) -> Geometry: # pragma: no cover
from mapchete.geometry import to_shape

return to_shape(geometry)


@deprecated(
reason="mapchete.vector.io.reproject_geometry has moved to mapchete.geometry.reproject_geometry"
)
def reproject_geometry(
geometry: GeometryLike,
src_crs: CRSLike,
dst_crs: CRSLike,
clip_to_crs_bounds: bool = True,
error_on_clip: bool = False,
segmentize_on_clip: bool = False,
segmentize: bool = False,
segmentize_fraction: float = 100.0,
validity_check: bool = True,
antimeridian_cutting: bool = False,
retry_with_clip: bool = True,
fiona_env: Optional[dict] = None,
) -> Geometry: # pragma: no cover
from mapchete.geometry import reproject_geometry

return reproject_geometry(
geometry=geometry,
src_crs=src_crs,
dst_crs=dst_crs,
clip_to_crs_bounds=clip_to_crs_bounds,
error_on_clip=error_on_clip,
segmentize_on_clip=segmentize_on_clip,
segmentize=segmentize,
segmentize_fraction=segmentize_fraction,
validity_check=validity_check,
antimeridian_cutting=antimeridian_cutting,
retry_with_clip=retry_with_clip,
fiona_env=fiona_env,
)


@deprecated(
reason="mapchete.io.vector.bounds_intersect was removed, use the Bounds.intersect(other) method instead."
)
def bounds_intersect(
bounds1: BoundsLike, bounds2: BoundsLike
) -> bool: # pragma: no cover
from mapchete.bounds import bounds_intersect

return bounds_intersect(bounds1, bounds2)
84 changes: 84 additions & 0 deletions mapchete/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
runtime_checkable,
)

from mapchete._deprecated import deprecated

from fiona.crs import CRS as FionaCRS # type: ignore
from geojson_pydantic import Feature, FeatureCollection as GeoJSONGeometryType
from pydantic import BaseModel
Expand Down Expand Up @@ -86,3 +88,85 @@ def to_resampling(resampling: ResamplingLike) -> Resampling:
class Progress(BaseModel):
current: int = 0
total: Optional[int] = None


# below are deprecated classes once sitting in this module:
@deprecated("mapchete.types.Bounds has been moved to mapchete.bounds.Bounds")
class Bounds: # pragma: no cover
def __new__(cls, *args, **kwargs):
from mapchete.bounds import Bounds

# Redirect instantiation to the new class
return Bounds(*args, **kwargs)

@staticmethod
def from_inp(
inp: BoundsLike, strict: bool = True, crs: Optional[CRSLike] = None
): # pragma: no cover
from mapchete.bounds import Bounds

return Bounds.from_inp(inp=inp, strict=strict, crs=crs)

@staticmethod
def from_dict(
inp: dict, strict: bool = True, crs: Optional[CRSLike] = None
): # pragma: no cover
return Bounds(**inp, strict=strict, crs=crs)


@deprecated("mapchete.types.Grid has been moved to mapchete.grid.Grid")
class Grid: # pragma: no cover
def __new__(cls, *args, **kwargs):
from mapchete.grid import Grid

return Grid(*args, **kwargs)

@staticmethod
def from_obj(obj): # pragma: no cover
from mapchete.grid import Grid

return Grid.from_obj(obj)

@staticmethod
def from_bounds(
bounds: BoundsLike, shape: ShapeLike, crs: CRSLike
): # pragma: no cover
from mapchete.grid import Grid

return Grid.from_bounds(bounds=bounds, shape=shape, crs=crs)


@deprecated(
"mapchete.types.ZoomLevels has been moved to mapchete.zoom_levels.ZoomLevels"
)
class ZoomLevels: # pragma: no cover
def __new__(cls, *args, **kwargs): # pragma: no cover
from mapchete.zoom_levels import ZoomLevels

return ZoomLevels(*args, **kwargs)

@staticmethod
def from_inp(
min: ZoomLevelsLike, max: Optional[int] = None, descending: bool = False
): # pragma: no cover
from mapchete.zoom_levels import ZoomLevels

return ZoomLevels.from_inp(min=min, max=max, descending=descending)

@staticmethod
def from_int(inp: int, **kwargs): # pragma: no cover
from mapchete.zoom_levels import ZoomLevels

return ZoomLevels.from_int(inp=inp, **kwargs)

@staticmethod
def from_list(inp: List[int], **kwargs): # pragma: no cover
from mapchete.zoom_levels import ZoomLevels

return ZoomLevels.from_list(inp=inp, **kwargs)

@staticmethod
def from_dict(inp: dict, **kwargs): # pragma: no cover
from mapchete.zoom_levels import ZoomLevels

return ZoomLevels.from_dict(inp=inp, **kwargs)
Loading