From 45467540327f5c4985c02626dd88a3008e4c3a6d Mon Sep 17 00:00:00 2001 From: Remi Cresson <remi.cresson@inrae.fr> Date: Wed, 5 Jul 2023 22:20:00 +0200 Subject: [PATCH 01/17] WIP: depreciation --- pyotb/__init__.py | 12 ++++- pyotb/core.py | 65 ++++++++++++++++++++++++ pyotb/depreciation.py | 114 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 pyotb/depreciation.py diff --git a/pyotb/__init__.py b/pyotb/__init__.py index 3e09a63..e6d3a97 100644 --- a/pyotb/__init__.py +++ b/pyotb/__init__.py @@ -4,7 +4,17 @@ __version__ = "2.0.0.dev4" from .helpers import logger, set_logger_level from .apps import * -from .core import App, Input, Output, get_nbchannels, get_pixel_type, summarize +from .core import ( + App, + Input, + Output, + get_nbchannels, + get_pixel_type, + summarize, + OTBObject, + otbObject, +) + from .functions import ( # pylint: disable=redefined-builtin all, any, diff --git a/pyotb/core.py b/pyotb/core.py index 94da09b..08c9fb5 100644 --- a/pyotb/core.py +++ b/pyotb/core.py @@ -11,7 +11,9 @@ from typing import Any import numpy as np import otbApplication as otb # pylint: disable=import-error +import pyotb from .helpers import logger +from .depreciation import deprecated_alias, warning_msg, deprecated_attr class OTBObject(ABC): @@ -32,6 +34,14 @@ class OTBObject(ABC): def output_image_key(self) -> str: """Return the name of a parameter key associated to the main output image of the object.""" + @property + @deprecated_attr(replacement="output_image_key") + def output_param(self) -> str: + """ + Return the name of a parameter key associated to the main output image + of the object (deprecated). + """ + @property @abstractmethod def exports_dic(self) -> dict[str, dict]: @@ -109,6 +119,21 @@ class OTBObject(ABC): origin_x, origin_y = origin_x - spacing_x / 2, origin_y - spacing_y / 2 return spacing_x, 0.0, origin_x, 0.0, spacing_y, origin_y + + def summarize(self, *args, **kwargs): + """Summarize the app with `pyotb.summarize()`. + + Args: + *args: args + **kwargs: keyword args + + Returns: + app summary + + """ + return pyotb.summarize(self, *args, **kwargs) + + def get_info(self) -> dict[str, (str, float, list[float])]: """Return a dict output of ReadImageInfo for the first image output.""" return App("ReadImageInfo", self, quiet=True).data @@ -393,6 +418,30 @@ class OTBObject(ABC): """ return id(self) + def __getattr__(self, item: str): + """ + Provides depreciation of old methods to access the OTB application + values. + ``` + + Args: + item: attribute name + + Returns: + attribute from self.app + + """ + getattr(self.app, item) + raise DeprecationWarning( + "Since pyotb 2.0.0, OTBObject instances have stopped to " + "forward attributes to their own internal otbApplication " + "instance. `App.app` can be used to call otbApplications " + f"methods. Attribute was: \"{item}\". Hint: maybe try " + f"`pyotb_app.app.{item}` instead of `pyotb_app.{item}`?" + ) + + + def __getitem__(self, key) -> Any | list[float] | float | Slicer: """Override the default __getitem__ behaviour. @@ -436,6 +485,14 @@ class OTBObject(ABC): return f"<pyotb.{self.__class__.__name__} object, id {id(self)}>" +class otbObject(OTBObject): # pylint: noqa + def __init_subclass__(cls): + warning_msg( + "Since pyotb 2.0.0, otbObject has been renamed OTBObject. " + "otbObject will be removed definitively in future releases." + ) + + class App(OTBObject): """Base class that gathers common operations for any OTB application.""" @@ -757,6 +814,7 @@ class App(OTBObject): self.frozen = False self._time_end = perf_counter() + @deprecated_alias(filename_extension="ext_fname") def write( self, path: str | Path | dict[str, str] = None, @@ -1431,6 +1489,8 @@ class Output(OTBObject): _filepath: str | Path = None + + @deprecated_alias(app="pyotb_app", output_parameter_key="param_key") def __init__( self, pyotb_app: App, @@ -1463,6 +1523,11 @@ class Output(OTBObject): """Reference to the parent pyotb otb.Application instance.""" return self.parent_pyotb_app.app + @property + @deprecated_attr(replacement="parent_pyotb_app") + def pyotb_app(self) -> App: + """Reference to the parent pyotb App (deprecated).""" + @property def exports_dic(self) -> dict[str, dict]: """Returns internal _exports_dic object that contains numpy array exports.""" diff --git a/pyotb/depreciation.py b/pyotb/depreciation.py new file mode 100644 index 0000000..87d1d77 --- /dev/null +++ b/pyotb/depreciation.py @@ -0,0 +1,114 @@ +"""Helps with deprecated classes and methods. + +Taken from https://stackoverflow.com/questions/49802412/how-to-implement- +deprecation-in-python-with-argument-alias +""" +from typing import Callable, Dict, Any +import functools +import warnings + + +WARN = '\033[91m' +ENDC = '\033[0m' +OKAY = '\033[92m' + +def warning_msg(message: str): + """ + Shows a warning message. + + Args: + message: message + + """ + warnings.warn( + message=message, + category=DeprecationWarning, + stacklevel=3, + ) +def deprecated_alias(**aliases: str) -> Callable: + """ + Decorator for deprecated function and method arguments. + + Use as follows: + + @deprecated_alias(old_arg='new_arg') + def myfunc(new_arg): + ... + + Args: + **aliases: aliases + + Returns: + wrapped function + + """ + def deco(f: Callable): + @functools.wraps(f) + def wrapper(*args, **kwargs): + rename_kwargs(f.__name__, kwargs, aliases) + return f(*args, **kwargs) + + return wrapper + + return deco + + +def rename_kwargs( + func_name: str, + kwargs: Dict[str, Any], + aliases: Dict[str, str] +): + """ + Helper function for deprecating function arguments. + + Args: + func_name: function + kwargs: keyword args + aliases: aliases + + """ + for alias, new in aliases.items(): + if alias in kwargs: + if new in kwargs: + raise TypeError( + f"{func_name} received both {alias} and {new} as arguments!" + f" {alias} is deprecated, use {new} instead." + ) + message = ( + f"{WARN}`{alias}`{ENDC} is deprecated as an argument to " + f"`{func_name}`; use {OKAY}`{new}`{ENDC} instead." + ) + warning_msg(message) + kwargs[new] = kwargs.pop(alias) + +def deprecated_attr(replacement: str) -> Callable: + """ + Decorator for deprecated attr. + + Use as follows: + + @deprecated_attr(replacement='new_attr') + def old_attr(...): + ... + + Args: + replacement: name of the new attr (method or attribute) + + Returns: + wrapped function + + """ + def deco(attr: Any): + @functools.wraps(attr) + def wrapper(self, *args, **kwargs): + warning_msg( + f"{WARN}`{attr.__name__}`{ENDC} will be removed in future " + f"releases. Please replace {WARN}`{attr.__name__}`{ENDC} with " + f"{OKAY}`{replacement}`{ENDC}." + ) + g = getattr(self, replacement) + return g(*args, **kwargs) if isinstance(g, Callable) else g + + return wrapper + + return deco -- GitLab From 09920054c29588786a7a0b6db0b5bc55b775118f Mon Sep 17 00:00:00 2001 From: Remi Cresson <remi.cresson@inrae.fr> Date: Wed, 5 Jul 2023 22:31:23 +0200 Subject: [PATCH 02/17] WIP: depreciation --- pyotb/core.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pyotb/core.py b/pyotb/core.py index 08c9fb5..298389d 100644 --- a/pyotb/core.py +++ b/pyotb/core.py @@ -11,7 +11,6 @@ from typing import Any import numpy as np import otbApplication as otb # pylint: disable=import-error -import pyotb from .helpers import logger from .depreciation import deprecated_alias, warning_msg, deprecated_attr @@ -124,14 +123,14 @@ class OTBObject(ABC): """Summarize the app with `pyotb.summarize()`. Args: - *args: args - **kwargs: keyword args + *args: args for `pyotb.summarize()` + **kwargs: keyword args for `pyotb.summarize()` Returns: - app summary + app summary, same as `pyotb.summarize()` """ - return pyotb.summarize(self, *args, **kwargs) + return summarize(self, *args, **kwargs) def get_info(self) -> dict[str, (str, float, list[float])]: -- GitLab From 7ef93cd298da8d26280ffaf3ea710641cbeb9c70 Mon Sep 17 00:00:00 2001 From: Remi Cresson <remi.cresson@inrae.fr> Date: Wed, 5 Jul 2023 22:42:13 +0200 Subject: [PATCH 03/17] WIP: depreciation --- pyotb/core.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pyotb/core.py b/pyotb/core.py index 298389d..9ceab97 100644 --- a/pyotb/core.py +++ b/pyotb/core.py @@ -431,12 +431,19 @@ class OTBObject(ABC): """ getattr(self.app, item) + note = "" + if item.startswith("GetParameter"): + note = ( + "Note: `pyotb_app.app.GetParameterValue('paramname')` can be " + "shorten with `pyotb_app['paramname']` to access parameters " + "values." + ) raise DeprecationWarning( "Since pyotb 2.0.0, OTBObject instances have stopped to " "forward attributes to their own internal otbApplication " "instance. `App.app` can be used to call otbApplications " f"methods. Attribute was: \"{item}\". Hint: maybe try " - f"`pyotb_app.app.{item}` instead of `pyotb_app.{item}`?" + f"`pyotb_app.app.{item}` instead of `pyotb_app.{item}`? {note}" ) -- GitLab From 64d2dc7d83f7dcdd964ee760b83f629e808f6d0c Mon Sep 17 00:00:00 2001 From: Remi Cresson <remi.cresson@inrae.fr> Date: Thu, 6 Jul 2023 11:07:10 +0200 Subject: [PATCH 04/17] WIP: depreciation --- pyotb/core.py | 57 ++++++++++++++++++++++++++----------------- pyotb/depreciation.py | 12 +++------ 2 files changed, 39 insertions(+), 30 deletions(-) diff --git a/pyotb/core.py b/pyotb/core.py index 9ceab97..3a284bc 100644 --- a/pyotb/core.py +++ b/pyotb/core.py @@ -36,10 +36,7 @@ class OTBObject(ABC): @property @deprecated_attr(replacement="output_image_key") def output_param(self) -> str: - """ - Return the name of a parameter key associated to the main output image - of the object (deprecated). - """ + """Return the name of a parameter key associated to the main output image of the object (deprecated).""" @property @abstractmethod @@ -120,7 +117,7 @@ class OTBObject(ABC): def summarize(self, *args, **kwargs): - """Summarize the app with `pyotb.summarize()`. + """Call `pyotb.summarize()` on itself. Args: *args: args for `pyotb.summarize()` @@ -418,33 +415,47 @@ class OTBObject(ABC): return id(self) def __getattr__(self, item: str): - """ - Provides depreciation of old methods to access the OTB application - values. - ``` + """Provides depreciation of old methods to access the OTB application values. + + This function will be removed completely in future releases. Args: item: attribute name - Returns: - attribute from self.app """ - getattr(self.app, item) - note = "" + note = ( + "Since pyotb 2.0.0, OTBObject instances have stopped to forward " + "attributes to their own internal otbApplication instance. " + "`App.app` can be used to call otbApplications methods. " + ) + + if item[0].isupper(): + # Because otbApplication instances methods names start with an + # upper case + note += ( + f"Maybe try `pyotb_app.app.{item}` instead of " + f"`pyotb_app.{item}`? " + ) + + if item[0].islower(): + # Because in pyotb 1.5.4, applications outputs were added as + # attributes of the instance + note += ( + "Note: `pyotb_app.paramname` is no longer supported. Starting " + "from pytob 2.0.0, `pyotb_app['paramname']` can be used to " + "access parameters values. " + ) + if item.startswith("GetParameter"): - note = ( + note += ( "Note: `pyotb_app.app.GetParameterValue('paramname')` can be " "shorten with `pyotb_app['paramname']` to access parameters " "values." ) - raise DeprecationWarning( - "Since pyotb 2.0.0, OTBObject instances have stopped to " - "forward attributes to their own internal otbApplication " - "instance. `App.app` can be used to call otbApplications " - f"methods. Attribute was: \"{item}\". Hint: maybe try " - f"`pyotb_app.app.{item}` instead of `pyotb_app.{item}`? {note}" - ) + warning_msg(note) + raise AttributeError + @@ -491,8 +502,10 @@ class OTBObject(ABC): return f"<pyotb.{self.__class__.__name__} object, id {id(self)}>" -class otbObject(OTBObject): # pylint: noqa +class otbObject(OTBObject): # noqa + """Class for depreciation of otbObject since pyotb 2.0.0. Will be removed in future releases.""" def __init_subclass__(cls): + """Show a warning for depreciation.""" warning_msg( "Since pyotb 2.0.0, otbObject has been renamed OTBObject. " "otbObject will be removed definitively in future releases." diff --git a/pyotb/depreciation.py b/pyotb/depreciation.py index 87d1d77..213aa56 100644 --- a/pyotb/depreciation.py +++ b/pyotb/depreciation.py @@ -13,8 +13,7 @@ ENDC = '\033[0m' OKAY = '\033[92m' def warning_msg(message: str): - """ - Shows a warning message. + """Shows a warning message. Args: message: message @@ -26,8 +25,7 @@ def warning_msg(message: str): stacklevel=3, ) def deprecated_alias(**aliases: str) -> Callable: - """ - Decorator for deprecated function and method arguments. + """Decorator for deprecated function and method arguments. Use as follows: @@ -58,8 +56,7 @@ def rename_kwargs( kwargs: Dict[str, Any], aliases: Dict[str, str] ): - """ - Helper function for deprecating function arguments. + """Helper function for deprecating function arguments. Args: func_name: function @@ -82,8 +79,7 @@ def rename_kwargs( kwargs[new] = kwargs.pop(alias) def deprecated_attr(replacement: str) -> Callable: - """ - Decorator for deprecated attr. + """Decorator for deprecated attr. Use as follows: -- GitLab From 240ce351b146b7b7ee0cfd43415a95ccafaff22c Mon Sep 17 00:00:00 2001 From: Remi Cresson <remi.cresson@inrae.fr> Date: Thu, 6 Jul 2023 11:15:14 +0200 Subject: [PATCH 05/17] WIP: depreciation --- pyotb/core.py | 4 ++-- pyotb/depreciation.py | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pyotb/core.py b/pyotb/core.py index 3a284bc..e35c564 100644 --- a/pyotb/core.py +++ b/pyotb/core.py @@ -117,7 +117,7 @@ class OTBObject(ABC): def summarize(self, *args, **kwargs): - """Call `pyotb.summarize()` on itself. + """Recursively summarize parameters and parents. Args: *args: args for `pyotb.summarize()` @@ -502,7 +502,7 @@ class OTBObject(ABC): return f"<pyotb.{self.__class__.__name__} object, id {id(self)}>" -class otbObject(OTBObject): # noqa +class otbObject(OTBObject): # noqa, pylint: disable=invalid-name """Class for depreciation of otbObject since pyotb 2.0.0. Will be removed in future releases.""" def __init_subclass__(cls): """Show a warning for depreciation.""" diff --git a/pyotb/depreciation.py b/pyotb/depreciation.py index 213aa56..0234249 100644 --- a/pyotb/depreciation.py +++ b/pyotb/depreciation.py @@ -40,11 +40,11 @@ def deprecated_alias(**aliases: str) -> Callable: wrapped function """ - def deco(f: Callable): - @functools.wraps(f) + def deco(func: Callable): + @functools.wraps(func) def wrapper(*args, **kwargs): - rename_kwargs(f.__name__, kwargs, aliases) - return f(*args, **kwargs) + rename_kwargs(func.__name__, kwargs, aliases) + return func(*args, **kwargs) return wrapper @@ -102,8 +102,8 @@ def deprecated_attr(replacement: str) -> Callable: f"releases. Please replace {WARN}`{attr.__name__}`{ENDC} with " f"{OKAY}`{replacement}`{ENDC}." ) - g = getattr(self, replacement) - return g(*args, **kwargs) if isinstance(g, Callable) else g + out = getattr(self, replacement) + return out(*args, **kwargs) if isinstance(out, Callable) else out return wrapper -- GitLab From 82c93bdb6e8ff537460ad123f1feb7338520afff Mon Sep 17 00:00:00 2001 From: Remi Cresson <remi.cresson@inrae.fr> Date: Thu, 6 Jul 2023 11:58:06 +0200 Subject: [PATCH 06/17] REFAC: rename warning_msg --> depreciation_warning --- pyotb/__init__.py | 11 +---------- pyotb/core.py | 6 +++--- pyotb/depreciation.py | 6 +++--- 3 files changed, 7 insertions(+), 16 deletions(-) diff --git a/pyotb/__init__.py b/pyotb/__init__.py index e6d3a97..62508f5 100644 --- a/pyotb/__init__.py +++ b/pyotb/__init__.py @@ -4,16 +4,7 @@ __version__ = "2.0.0.dev4" from .helpers import logger, set_logger_level from .apps import * -from .core import ( - App, - Input, - Output, - get_nbchannels, - get_pixel_type, - summarize, - OTBObject, - otbObject, -) +from .core import App, Input, Output, get_nbchannels, get_pixel_type, summarize, OTBObject, otbObject from .functions import ( # pylint: disable=redefined-builtin all, diff --git a/pyotb/core.py b/pyotb/core.py index e35c564..b7ee57a 100644 --- a/pyotb/core.py +++ b/pyotb/core.py @@ -12,7 +12,7 @@ import numpy as np import otbApplication as otb # pylint: disable=import-error from .helpers import logger -from .depreciation import deprecated_alias, warning_msg, deprecated_attr +from .depreciation import deprecated_alias, depreciation_warning, deprecated_attr class OTBObject(ABC): @@ -453,7 +453,7 @@ class OTBObject(ABC): "shorten with `pyotb_app['paramname']` to access parameters " "values." ) - warning_msg(note) + depreciation_warning(note) raise AttributeError @@ -506,7 +506,7 @@ class otbObject(OTBObject): # noqa, pylint: disable=invalid-name """Class for depreciation of otbObject since pyotb 2.0.0. Will be removed in future releases.""" def __init_subclass__(cls): """Show a warning for depreciation.""" - warning_msg( + depreciation_warning( "Since pyotb 2.0.0, otbObject has been renamed OTBObject. " "otbObject will be removed definitively in future releases." ) diff --git a/pyotb/depreciation.py b/pyotb/depreciation.py index 0234249..859ba60 100644 --- a/pyotb/depreciation.py +++ b/pyotb/depreciation.py @@ -12,7 +12,7 @@ WARN = '\033[91m' ENDC = '\033[0m' OKAY = '\033[92m' -def warning_msg(message: str): +def depreciation_warning(message: str): """Shows a warning message. Args: @@ -75,7 +75,7 @@ def rename_kwargs( f"{WARN}`{alias}`{ENDC} is deprecated as an argument to " f"`{func_name}`; use {OKAY}`{new}`{ENDC} instead." ) - warning_msg(message) + depreciation_warning(message) kwargs[new] = kwargs.pop(alias) def deprecated_attr(replacement: str) -> Callable: @@ -97,7 +97,7 @@ def deprecated_attr(replacement: str) -> Callable: def deco(attr: Any): @functools.wraps(attr) def wrapper(self, *args, **kwargs): - warning_msg( + depreciation_warning( f"{WARN}`{attr.__name__}`{ENDC} will be removed in future " f"releases. Please replace {WARN}`{attr.__name__}`{ENDC} with " f"{OKAY}`{replacement}`{ENDC}." -- GitLab From e4d9a3e42092cd6d004f80ec4412c6037799d6f8 Mon Sep 17 00:00:00 2001 From: Vincent Delbar <vincent.delbar@latelescop.fr> Date: Fri, 7 Jul 2023 07:20:16 +0000 Subject: [PATCH 07/17] Apply 1 suggestion(s) to 1 file(s) --- pyotb/core.py | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/pyotb/core.py b/pyotb/core.py index b7ee57a..ab6b620 100644 --- a/pyotb/core.py +++ b/pyotb/core.py @@ -430,34 +430,30 @@ class OTBObject(ABC): "`App.app` can be used to call otbApplications methods. " ) - if item[0].isupper(): + if item in dir(self.app): # Because otbApplication instances methods names start with an # upper case note += ( f"Maybe try `pyotb_app.app.{item}` instead of " f"`pyotb_app.{item}`? " ) + if item.startswith("GetParameter"): + note += ( + "Note: `pyotb_app.app.GetParameterValue('paramname')` can be " + "shorten with `pyotb_app['paramname']` to access parameters " + "values." + ) - if item[0].islower(): + elif item in self.parameters_keys: # Because in pyotb 1.5.4, applications outputs were added as # attributes of the instance note += ( "Note: `pyotb_app.paramname` is no longer supported. Starting " - "from pytob 2.0.0, `pyotb_app['paramname']` can be used to " + "from pyotb 2.0.0, `pyotb_app['paramname']` can be used to " "access parameters values. " ) - - if item.startswith("GetParameter"): - note += ( - "Note: `pyotb_app.app.GetParameterValue('paramname')` can be " - "shorten with `pyotb_app['paramname']` to access parameters " - "values." - ) depreciation_warning(note) - raise AttributeError - - - + raise AttributeError(f"'{type(self)}' object has no attribute '{item}'") def __getitem__(self, key) -> Any | list[float] | float | Slicer: """Override the default __getitem__ behaviour. -- GitLab From 0e49fec8ce3c6f61c91e4f2713c58d32f793ad43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Cresson?= <remi.cresson@inrae.fr> Date: Fri, 7 Jul 2023 07:23:37 +0000 Subject: [PATCH 08/17] Apply 1 suggestion(s) to 1 file(s) --- pyotb/core.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/pyotb/core.py b/pyotb/core.py index ab6b620..573929a 100644 --- a/pyotb/core.py +++ b/pyotb/core.py @@ -427,18 +427,19 @@ class OTBObject(ABC): note = ( "Since pyotb 2.0.0, OTBObject instances have stopped to forward " "attributes to their own internal otbApplication instance. " - "`App.app` can be used to call otbApplications methods. " + "`App.app` can be used to call otbApplications methods." ) + hint = None if item in dir(self.app): # Because otbApplication instances methods names start with an # upper case - note += ( + hint = ( f"Maybe try `pyotb_app.app.{item}` instead of " f"`pyotb_app.{item}`? " ) if item.startswith("GetParameter"): - note += ( + hint += ( "Note: `pyotb_app.app.GetParameterValue('paramname')` can be " "shorten with `pyotb_app['paramname']` to access parameters " "values." @@ -447,13 +448,14 @@ class OTBObject(ABC): elif item in self.parameters_keys: # Because in pyotb 1.5.4, applications outputs were added as # attributes of the instance - note += ( + hint = ( "Note: `pyotb_app.paramname` is no longer supported. Starting " "from pyotb 2.0.0, `pyotb_app['paramname']` can be used to " "access parameters values. " ) - depreciation_warning(note) - raise AttributeError(f"'{type(self)}' object has no attribute '{item}'") + if hint: + depreciation_warning(f"{note} {hint}") + raise AttributeError def __getitem__(self, key) -> Any | list[float] | float | Slicer: """Override the default __getitem__ behaviour. -- GitLab From 8b8389aae60ed8a5cb15c67ac1b01956391e9be1 Mon Sep 17 00:00:00 2001 From: Remi Cresson <remi.cresson@inrae.fr> Date: Fri, 7 Jul 2023 17:34:53 +0200 Subject: [PATCH 09/17] DOC: fix summarize api doc --- pyotb/core.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/pyotb/core.py b/pyotb/core.py index b7ee57a..f6e3060 100644 --- a/pyotb/core.py +++ b/pyotb/core.py @@ -502,14 +502,20 @@ class OTBObject(ABC): return f"<pyotb.{self.__class__.__name__} object, id {id(self)}>" +def old_otbobj_warn(): + depreciation_warning( + "Since pyotb 2.0.0, otbObject has been renamed OTBObject. " + "otbObject will be removed definitively in future releases." + ) + class otbObject(OTBObject): # noqa, pylint: disable=invalid-name """Class for depreciation of otbObject since pyotb 2.0.0. Will be removed in future releases.""" def __init_subclass__(cls): """Show a warning for depreciation.""" - depreciation_warning( - "Since pyotb 2.0.0, otbObject has been renamed OTBObject. " - "otbObject will be removed definitively in future releases." - ) + old_otbobj_warn() + def __class__(self): + old_otbobj_warn() + return super().__class__ class App(OTBObject): @@ -1744,8 +1750,7 @@ def summarize( useful to remove extended filenames. Returns: - nested dictionary with serialized App(s) containing name and - parameters of an app and its parents + nested dictionary with serialized App(s) containing name and parameters of an app and its parents """ -- GitLab From cabb7f0a7a987b358ad8bfe9fe6af119f7d8c994 Mon Sep 17 00:00:00 2001 From: Remi Cresson <remi.cresson@inrae.fr> Date: Fri, 7 Jul 2023 18:31:54 +0200 Subject: [PATCH 10/17] FIX: AttributeError message --- pyotb/core.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyotb/core.py b/pyotb/core.py index d5cca0e..f095125 100644 --- a/pyotb/core.py +++ b/pyotb/core.py @@ -455,7 +455,9 @@ class OTBObject(ABC): ) if hint: depreciation_warning(f"{note} {hint}") - raise AttributeError + raise AttributeError( + f"'{type(self).__name__}' object has no attribute '{item}'" + ) def __getitem__(self, key) -> Any | list[float] | float | Slicer: """Override the default __getitem__ behaviour. -- GitLab From 62bc96a99137467c53d3d6acec44c9d992489a66 Mon Sep 17 00:00:00 2001 From: Remi Cresson <remi.cresson@inrae.fr> Date: Fri, 7 Jul 2023 18:47:21 +0200 Subject: [PATCH 11/17] FIX: AttributeError message --- pyotb/core.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/pyotb/core.py b/pyotb/core.py index f095125..1a5859c 100644 --- a/pyotb/core.py +++ b/pyotb/core.py @@ -502,22 +502,6 @@ class OTBObject(ABC): return f"<pyotb.{self.__class__.__name__} object, id {id(self)}>" -def old_otbobj_warn(): - depreciation_warning( - "Since pyotb 2.0.0, otbObject has been renamed OTBObject. " - "otbObject will be removed definitively in future releases." - ) - -class otbObject(OTBObject): # noqa, pylint: disable=invalid-name - """Class for depreciation of otbObject since pyotb 2.0.0. Will be removed in future releases.""" - def __init_subclass__(cls): - """Show a warning for depreciation.""" - old_otbobj_warn() - def __class__(self): - old_otbobj_warn() - return super().__class__ - - class App(OTBObject): """Base class that gathers common operations for any OTB application.""" -- GitLab From 56dea1ac019db8c6db47dd26bf2a3c16f0d6f2cd Mon Sep 17 00:00:00 2001 From: Remi Cresson <remi.cresson@inrae.fr> Date: Fri, 7 Jul 2023 18:48:00 +0200 Subject: [PATCH 12/17] FIX: remove otbObject --- pyotb/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyotb/__init__.py b/pyotb/__init__.py index 62508f5..bf55392 100644 --- a/pyotb/__init__.py +++ b/pyotb/__init__.py @@ -4,7 +4,7 @@ __version__ = "2.0.0.dev4" from .helpers import logger, set_logger_level from .apps import * -from .core import App, Input, Output, get_nbchannels, get_pixel_type, summarize, OTBObject, otbObject +from .core import App, Input, Output, get_nbchannels, get_pixel_type, summarize, OTBObject from .functions import ( # pylint: disable=redefined-builtin all, -- GitLab From 3bedecfc229257cc3908417bf044a25ebcb579ec Mon Sep 17 00:00:00 2001 From: Vincent Delbar <vincent.delbar@latelescop.fr> Date: Fri, 7 Jul 2023 19:19:01 +0200 Subject: [PATCH 13/17] STYLE: run black --- pyotb/depreciation.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/pyotb/depreciation.py b/pyotb/depreciation.py index 859ba60..687e6ca 100644 --- a/pyotb/depreciation.py +++ b/pyotb/depreciation.py @@ -8,9 +8,10 @@ import functools import warnings -WARN = '\033[91m' -ENDC = '\033[0m' -OKAY = '\033[92m' +WARN = "\033[91m" +ENDC = "\033[0m" +OKAY = "\033[92m" + def depreciation_warning(message: str): """Shows a warning message. @@ -24,6 +25,8 @@ def depreciation_warning(message: str): category=DeprecationWarning, stacklevel=3, ) + + def deprecated_alias(**aliases: str) -> Callable: """Decorator for deprecated function and method arguments. @@ -40,6 +43,7 @@ def deprecated_alias(**aliases: str) -> Callable: wrapped function """ + def deco(func: Callable): @functools.wraps(func) def wrapper(*args, **kwargs): @@ -51,11 +55,7 @@ def deprecated_alias(**aliases: str) -> Callable: return deco -def rename_kwargs( - func_name: str, - kwargs: Dict[str, Any], - aliases: Dict[str, str] -): +def rename_kwargs(func_name: str, kwargs: Dict[str, Any], aliases: Dict[str, str]): """Helper function for deprecating function arguments. Args: @@ -78,6 +78,7 @@ def rename_kwargs( depreciation_warning(message) kwargs[new] = kwargs.pop(alias) + def deprecated_attr(replacement: str) -> Callable: """Decorator for deprecated attr. @@ -94,6 +95,7 @@ def deprecated_attr(replacement: str) -> Callable: wrapped function """ + def deco(attr: Any): @functools.wraps(attr) def wrapper(self, *args, **kwargs): -- GitLab From 0d7dc0c4fd47f25d8c7a002f64f4cb085b1556cd Mon Sep 17 00:00:00 2001 From: Vincent Delbar <vincent.delbar@latelescop.fr> Date: Fri, 7 Jul 2023 19:20:36 +0200 Subject: [PATCH 14/17] STYLE: run black on core.py --- pyotb/core.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pyotb/core.py b/pyotb/core.py index 1a5859c..d49581f 100644 --- a/pyotb/core.py +++ b/pyotb/core.py @@ -115,7 +115,6 @@ class OTBObject(ABC): origin_x, origin_y = origin_x - spacing_x / 2, origin_y - spacing_y / 2 return spacing_x, 0.0, origin_x, 0.0, spacing_y, origin_y - def summarize(self, *args, **kwargs): """Recursively summarize parameters and parents. @@ -129,7 +128,6 @@ class OTBObject(ABC): """ return summarize(self, *args, **kwargs) - def get_info(self) -> dict[str, (str, float, list[float])]: """Return a dict output of ReadImageInfo for the first image output.""" return App("ReadImageInfo", self, quiet=True).data @@ -435,8 +433,7 @@ class OTBObject(ABC): # Because otbApplication instances methods names start with an # upper case hint = ( - f"Maybe try `pyotb_app.app.{item}` instead of " - f"`pyotb_app.{item}`? " + f"Maybe try `pyotb_app.app.{item}` instead of " f"`pyotb_app.{item}`? " ) if item.startswith("GetParameter"): hint += ( @@ -1498,7 +1495,6 @@ class Output(OTBObject): _filepath: str | Path = None - @deprecated_alias(app="pyotb_app", output_parameter_key="param_key") def __init__( self, -- GitLab From 9d27acfa592f927c443edc63a896e42125db1a79 Mon Sep 17 00:00:00 2001 From: Vincent Delbar <vincent.delbar@latelescop.fr> Date: Sat, 8 Jul 2023 07:16:06 +0000 Subject: [PATCH 15/17] Apply 1 suggestion(s) to 1 file(s) --- pyotb/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyotb/core.py b/pyotb/core.py index d49581f..c8e98a7 100644 --- a/pyotb/core.py +++ b/pyotb/core.py @@ -433,7 +433,7 @@ class OTBObject(ABC): # Because otbApplication instances methods names start with an # upper case hint = ( - f"Maybe try `pyotb_app.app.{item}` instead of " f"`pyotb_app.{item}`? " + f"Maybe try `pyotb_app.app.{item}` instead of `pyotb_app.{item}`? " ) if item.startswith("GetParameter"): hint += ( -- GitLab From b5a3c8097bfc463694ccca9bb58e3a491b837585 Mon Sep 17 00:00:00 2001 From: Remi Cresson <remi.cresson@inrae.fr> Date: Mon, 10 Jul 2023 09:08:31 +0200 Subject: [PATCH 16/17] DOC: add a note for migration in troubleshooting --- doc/troubleshooting.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/doc/troubleshooting.md b/doc/troubleshooting.md index 0025913..ee3bdf4 100644 --- a/doc/troubleshooting.md +++ b/doc/troubleshooting.md @@ -1,4 +1,16 @@ -## Troubleshooting: known limitations with old versions +# Troubleshooting + +## Migration from pyotb 1.5.4 (oct 2022) to 2.x.y + +- `otbObject` has ben renamed `OTBObject` +- use `pyotb_app['paramname']` or `pyotb_app.app.GetParameterValue('paramname')` instead of `pyotb_app.GetParameterValue('paramname')` to access parameter `paramname` value +- use `pyotb_app['paramname']` instead of `pyotb_app.paramname` to access parameter `paramname` value +- `App.output_param` has been replaced with `App.output_image_key` +- `App.write()` argument `filename_extension` has been renamed `ext_fname` +- `Output.__init__()` arguments `app` and `output_parameter_key` have been renamed `pyotb_app` and `param_key` +- `Output.pyotb_app` has been renamed `Output.parent_pyotb_app` + +## Known limitations with old versions !!! note -- GitLab From 19d682d854045f3ac16ff8e7a7a5cb1390ebdc19 Mon Sep 17 00:00:00 2001 From: Remi Cresson <remi.cresson@inrae.fr> Date: Mon, 10 Jul 2023 09:20:04 +0200 Subject: [PATCH 17/17] DOC: add a note for migration in troubleshooting --- doc/troubleshooting.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/doc/troubleshooting.md b/doc/troubleshooting.md index ee3bdf4..9cf5b84 100644 --- a/doc/troubleshooting.md +++ b/doc/troubleshooting.md @@ -2,13 +2,22 @@ ## Migration from pyotb 1.5.4 (oct 2022) to 2.x.y +List of breaking changes: + - `otbObject` has ben renamed `OTBObject` -- use `pyotb_app['paramname']` or `pyotb_app.app.GetParameterValue('paramname')` instead of `pyotb_app.GetParameterValue('paramname')` to access parameter `paramname` value -- use `pyotb_app['paramname']` instead of `pyotb_app.paramname` to access parameter `paramname` value +- `otbObject.get_infos()` has been renamed `OTBObject.get_info()` +- `otbObject.key_output_image` has been renamed `OTBObject.output_image_key` +- `otbObject.key_input_image` has been renamed `OTBObject.input_image_key` +- `otbObject.read_values_at_coords()` has been renamed `OTBObject.get_values_at_coords()` +- `otbObject.xy_to_rowcol()` has been renamed `OTBObject.get_rowcol_from_xy()` - `App.output_param` has been replaced with `App.output_image_key` - `App.write()` argument `filename_extension` has been renamed `ext_fname` +- `App.save_objects()` has been renamed `App.__sync_parameters()` +- use `pyotb_app['paramname']` or `pyotb_app.app.GetParameterValue('paramname')` instead of `pyotb_app.GetParameterValue('paramname')` to access parameter `paramname` value +- use `pyotb_app['paramname']` instead of `pyotb_app.paramname` to access parameter `paramname` value - `Output.__init__()` arguments `app` and `output_parameter_key` have been renamed `pyotb_app` and `param_key` - `Output.pyotb_app` has been renamed `Output.parent_pyotb_app` +- `logicalOperation` has been renamed `LogicalOperation` ## Known limitations with old versions -- GitLab