From 38bb32bd96e659a78cb26540368061a513141ea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi?= <remi.cresson@inrae.fr> Date: Tue, 8 Oct 2024 20:19:13 +0200 Subject: [PATCH 01/15] wip: fix #130 --- pyotb/__init__.py | 1 - pyotb/core.py | 118 +--------------------------------------------- 2 files changed, 1 insertion(+), 118 deletions(-) diff --git a/pyotb/__init__.py b/pyotb/__init__.py index 594272b..d112031 100644 --- a/pyotb/__init__.py +++ b/pyotb/__init__.py @@ -8,7 +8,6 @@ from .core import ( OTBObject, App, Input, - Output, get_nbchannels, get_pixel_type, summarize, diff --git a/pyotb/core.py b/pyotb/core.py index b78efd4..3bd4c3c 100644 --- a/pyotb/core.py +++ b/pyotb/core.py @@ -601,13 +601,6 @@ class App(OTBObject): # Init, execute and write (auto flush only when output param was provided) if args or kwargs: self.set_parameters(*args, **kwargs) - # Create Output image objects - for key in ( - key - for key, param in self._out_param_types.items() - if param == otb.ParameterType_OutputImage - ): - self.outputs[key] = Output(self, key, self._settings.get(key)) if not self.frozen: self.execute() @@ -1516,113 +1509,6 @@ class Input(App): return f"<pyotb.Input object, from {self.filepath}>" -class Output(OTBObject): - """Object that behave like a pointer to a specific application in-memory output or file. - - Args: - pyotb_app: The pyotb App to store reference from - param_key: Output parameter key of the target app - filepath: path of the output file (if not memory) - mkdir: create missing parent directories - - """ - - _filepath: str | Path = None - - @deprecated_alias(app="pyotb_app", output_parameter_key="param_key") - def __init__( - self, - pyotb_app: App, - param_key: str = None, - filepath: str = None, - mkdir: bool = True, - ): - """Constructor for an Output object, initialized during App.__init__.""" - self.parent_pyotb_app = pyotb_app # keep trace of parent app - self.param_key = param_key - self.filepath = filepath - if mkdir and filepath is not None: - self.make_parent_dirs() - - @property - def name(self) -> str: - """Return Output name containing filepath.""" - return f"Output {self.param_key} from {self.parent_pyotb_app.name}" - - @property - def app(self) -> otb.Application: - """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]: - """Reference to parent _exports_dic object that contains np array exports.""" - return self.parent_pyotb_app.exports_dic - - @property - def output_image_key(self) -> str: - """Force the right key to be used when accessing the OTBObject.""" - return self.param_key - - @property - def filepath(self) -> str | Path: - """Property to manage output URL.""" - if self._filepath is None: - raise ValueError("Filepath is not set") - return self._filepath - - @filepath.setter - def filepath(self, path: str): - if isinstance(path, str): - if path and not path.startswith(("/vsi", "http://", "https://", "ftp://")): - path = Path(path.split("?")[0]) - self._filepath = path - - def exists(self) -> bool: - """Check if the output file exist on disk. - - Raises: - ValueError: if filepath is not set or is remote URL - - """ - if not isinstance(self.filepath, Path): - raise ValueError("Filepath is not set or points to a remote URL") - return self.filepath.exists() - - def make_parent_dirs(self): - """Create missing parent directories. - - Raises: - ValueError: if filepath is not set or is remote URL - - """ - if not isinstance(self.filepath, Path): - raise ValueError("Filepath is not set or points to a remote URL") - self.filepath.parent.mkdir(parents=True, exist_ok=True) - - def write(self, filepath: None | str | Path = None, **kwargs) -> bool: - """Write output to disk, filepath is not required if it was provided to parent App during init. - - Args: - filepath: path of the output file, can be None if a value was passed during app init - - """ - if filepath is None: - return self.parent_pyotb_app.write( - {self.output_image_key: self.filepath}, **kwargs - ) - return self.parent_pyotb_app.write({self.output_image_key: filepath}, **kwargs) - - def __str__(self) -> str: - """Return string representation of Output filepath.""" - return str(self.filepath) - - def get_nbchannels(inp: str | Path | OTBObject) -> int: """Get the nb of bands of input image. @@ -1733,7 +1619,7 @@ def get_out_images_param_keys(otb_app: otb.Application) -> list[str]: def summarize( - obj: App | Output | str | float | list, + obj: App | str | float | list, strip_inpath: bool = False, strip_outpath: bool = False, ) -> dict[str, dict | Any] | str | float | list: @@ -1756,8 +1642,6 @@ def summarize( """ if isinstance(obj, list): return [summarize(o) for o in obj] - if isinstance(obj, Output): - return summarize(obj.parent_pyotb_app) # => This is the deepest recursion level if not isinstance(obj, App): return obj -- GitLab From d6266957f455b561df9fcf8bda4ff7de95157032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi?= <remi.cresson@inrae.fr> Date: Tue, 8 Oct 2024 20:27:37 +0200 Subject: [PATCH 02/15] wip: fix #130 --- pyotb/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyotb/__init__.py b/pyotb/__init__.py index d112031..99c4555 100644 --- a/pyotb/__init__.py +++ b/pyotb/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """This module provides convenient python wrapping of otbApplications.""" -__version__ = "2.0.3.dev2" +__version__ = "2.1.0" from .install import install_otb from .helpers import logger -- GitLab From b83f5278a551c844e58f8105693a6a6c302b29dd Mon Sep 17 00:00:00 2001 From: Vincent Delbar <vincent.delbar@latelescop.fr> Date: Wed, 9 Oct 2024 14:09:25 +0200 Subject: [PATCH 03/15] Revert "wip: fix #130" This reverts commit d6266957f455b561df9fcf8bda4ff7de95157032. --- pyotb/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyotb/__init__.py b/pyotb/__init__.py index 99c4555..d112031 100644 --- a/pyotb/__init__.py +++ b/pyotb/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """This module provides convenient python wrapping of otbApplications.""" -__version__ = "2.1.0" +__version__ = "2.0.3.dev2" from .install import install_otb from .helpers import logger -- GitLab From ed45b39ee3d530b82d48aae098c503bed8e6f5c7 Mon Sep 17 00:00:00 2001 From: Vincent Delbar <vincent.delbar@latelescop.fr> Date: Wed, 9 Oct 2024 14:09:36 +0200 Subject: [PATCH 04/15] Revert "wip: fix #130" This reverts commit 38bb32bd96e659a78cb26540368061a513141ea5. --- pyotb/__init__.py | 1 + pyotb/core.py | 118 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 118 insertions(+), 1 deletion(-) diff --git a/pyotb/__init__.py b/pyotb/__init__.py index d112031..594272b 100644 --- a/pyotb/__init__.py +++ b/pyotb/__init__.py @@ -8,6 +8,7 @@ from .core import ( OTBObject, App, Input, + Output, get_nbchannels, get_pixel_type, summarize, diff --git a/pyotb/core.py b/pyotb/core.py index 3bd4c3c..b78efd4 100644 --- a/pyotb/core.py +++ b/pyotb/core.py @@ -601,6 +601,13 @@ class App(OTBObject): # Init, execute and write (auto flush only when output param was provided) if args or kwargs: self.set_parameters(*args, **kwargs) + # Create Output image objects + for key in ( + key + for key, param in self._out_param_types.items() + if param == otb.ParameterType_OutputImage + ): + self.outputs[key] = Output(self, key, self._settings.get(key)) if not self.frozen: self.execute() @@ -1509,6 +1516,113 @@ class Input(App): return f"<pyotb.Input object, from {self.filepath}>" +class Output(OTBObject): + """Object that behave like a pointer to a specific application in-memory output or file. + + Args: + pyotb_app: The pyotb App to store reference from + param_key: Output parameter key of the target app + filepath: path of the output file (if not memory) + mkdir: create missing parent directories + + """ + + _filepath: str | Path = None + + @deprecated_alias(app="pyotb_app", output_parameter_key="param_key") + def __init__( + self, + pyotb_app: App, + param_key: str = None, + filepath: str = None, + mkdir: bool = True, + ): + """Constructor for an Output object, initialized during App.__init__.""" + self.parent_pyotb_app = pyotb_app # keep trace of parent app + self.param_key = param_key + self.filepath = filepath + if mkdir and filepath is not None: + self.make_parent_dirs() + + @property + def name(self) -> str: + """Return Output name containing filepath.""" + return f"Output {self.param_key} from {self.parent_pyotb_app.name}" + + @property + def app(self) -> otb.Application: + """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]: + """Reference to parent _exports_dic object that contains np array exports.""" + return self.parent_pyotb_app.exports_dic + + @property + def output_image_key(self) -> str: + """Force the right key to be used when accessing the OTBObject.""" + return self.param_key + + @property + def filepath(self) -> str | Path: + """Property to manage output URL.""" + if self._filepath is None: + raise ValueError("Filepath is not set") + return self._filepath + + @filepath.setter + def filepath(self, path: str): + if isinstance(path, str): + if path and not path.startswith(("/vsi", "http://", "https://", "ftp://")): + path = Path(path.split("?")[0]) + self._filepath = path + + def exists(self) -> bool: + """Check if the output file exist on disk. + + Raises: + ValueError: if filepath is not set or is remote URL + + """ + if not isinstance(self.filepath, Path): + raise ValueError("Filepath is not set or points to a remote URL") + return self.filepath.exists() + + def make_parent_dirs(self): + """Create missing parent directories. + + Raises: + ValueError: if filepath is not set or is remote URL + + """ + if not isinstance(self.filepath, Path): + raise ValueError("Filepath is not set or points to a remote URL") + self.filepath.parent.mkdir(parents=True, exist_ok=True) + + def write(self, filepath: None | str | Path = None, **kwargs) -> bool: + """Write output to disk, filepath is not required if it was provided to parent App during init. + + Args: + filepath: path of the output file, can be None if a value was passed during app init + + """ + if filepath is None: + return self.parent_pyotb_app.write( + {self.output_image_key: self.filepath}, **kwargs + ) + return self.parent_pyotb_app.write({self.output_image_key: filepath}, **kwargs) + + def __str__(self) -> str: + """Return string representation of Output filepath.""" + return str(self.filepath) + + def get_nbchannels(inp: str | Path | OTBObject) -> int: """Get the nb of bands of input image. @@ -1619,7 +1733,7 @@ def get_out_images_param_keys(otb_app: otb.Application) -> list[str]: def summarize( - obj: App | str | float | list, + obj: App | Output | str | float | list, strip_inpath: bool = False, strip_outpath: bool = False, ) -> dict[str, dict | Any] | str | float | list: @@ -1642,6 +1756,8 @@ def summarize( """ if isinstance(obj, list): return [summarize(o) for o in obj] + if isinstance(obj, Output): + return summarize(obj.parent_pyotb_app) # => This is the deepest recursion level if not isinstance(obj, App): return obj -- GitLab From 98d03b9ec7aca7d48c542cfa1ceed26668b088bc Mon Sep 17 00:00:00 2001 From: Vincent Delbar <vincent.delbar@latelescop.fr> Date: Wed, 9 Oct 2024 14:27:26 +0200 Subject: [PATCH 05/15] Fixes #130 using WeakValueDictionary --- pyotb/core.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyotb/core.py b/pyotb/core.py index b78efd4..bb589a9 100644 --- a/pyotb/core.py +++ b/pyotb/core.py @@ -7,6 +7,7 @@ from ast import literal_eval from pathlib import Path from time import perf_counter from typing import Any +from weakref import WeakValueDictionary import numpy as np import otbApplication as otb # pylint: disable=import-error @@ -579,7 +580,8 @@ class App(OTBObject): self._exports_dic = {} self._settings, self._auto_parameters = {}, {} self._time_start, self._time_end = 0.0, 0.0 - self.data, self.outputs = {}, {} + self.data = {} + self.outputs = WeakValueDictionary() self.quiet, self.frozen = quiet, frozen # Param keys and types -- GitLab From d09e94ca8f90c17e9ca6adfcfa965f257baa8aef Mon Sep 17 00:00:00 2001 From: Vincent Delbar <vincent.delbar@latelescop.fr> Date: Wed, 9 Oct 2024 14:48:09 +0200 Subject: [PATCH 06/15] Revert "Fixes #130 using WeakValueDictionary" This reverts commit 98d03b9ec7aca7d48c542cfa1ceed26668b088bc. --- pyotb/core.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pyotb/core.py b/pyotb/core.py index bb589a9..b78efd4 100644 --- a/pyotb/core.py +++ b/pyotb/core.py @@ -7,7 +7,6 @@ from ast import literal_eval from pathlib import Path from time import perf_counter from typing import Any -from weakref import WeakValueDictionary import numpy as np import otbApplication as otb # pylint: disable=import-error @@ -580,8 +579,7 @@ class App(OTBObject): self._exports_dic = {} self._settings, self._auto_parameters = {}, {} self._time_start, self._time_end = 0.0, 0.0 - self.data = {} - self.outputs = WeakValueDictionary() + self.data, self.outputs = {}, {} self.quiet, self.frozen = quiet, frozen # Param keys and types -- GitLab From f44c6738ae2713339003a13b88bf9e44751e78d5 Mon Sep 17 00:00:00 2001 From: Vincent Delbar <vincent.delbar@latelescop.fr> Date: Wed, 9 Oct 2024 14:52:29 +0200 Subject: [PATCH 07/15] Try with weakref.ref --- pyotb/core.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyotb/core.py b/pyotb/core.py index b78efd4..83c9dc7 100644 --- a/pyotb/core.py +++ b/pyotb/core.py @@ -2,6 +2,7 @@ from __future__ import annotations import re +import weakref from abc import ABC, abstractmethod from ast import literal_eval from pathlib import Path @@ -1538,7 +1539,7 @@ class Output(OTBObject): mkdir: bool = True, ): """Constructor for an Output object, initialized during App.__init__.""" - self.parent_pyotb_app = pyotb_app # keep trace of parent app + self.parent_pyotb_app = weakref.ref(pyotb_app) # keep a weak reference to parent app self.param_key = param_key self.filepath = filepath if mkdir and filepath is not None: -- GitLab From 12774a23d6bd9a37f10b2b3a78bee3b5035af4e6 Mon Sep 17 00:00:00 2001 From: Vincent Delbar <vincent.delbar@latelescop.fr> Date: Wed, 9 Oct 2024 15:00:14 +0200 Subject: [PATCH 08/15] Use weakref.proxy --- pyotb/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyotb/core.py b/pyotb/core.py index 83c9dc7..c7262d8 100644 --- a/pyotb/core.py +++ b/pyotb/core.py @@ -1539,7 +1539,7 @@ class Output(OTBObject): mkdir: bool = True, ): """Constructor for an Output object, initialized during App.__init__.""" - self.parent_pyotb_app = weakref.ref(pyotb_app) # keep a weak reference to parent app + self.parent_pyotb_app = weakref.proxy(pyotb_app) # keep a weak reference to parent app self.param_key = param_key self.filepath = filepath if mkdir and filepath is not None: -- GitLab From 6a8d18b0d1b662ce2715104a0b359efb80bc477c Mon Sep 17 00:00:00 2001 From: Vincent Delbar <vincent.delbar@latelescop.fr> Date: Wed, 9 Oct 2024 16:21:56 +0200 Subject: [PATCH 09/15] Do not instantiate Output objects during App init --- pyotb/core.py | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/pyotb/core.py b/pyotb/core.py index c7262d8..d4b7e24 100644 --- a/pyotb/core.py +++ b/pyotb/core.py @@ -2,7 +2,6 @@ from __future__ import annotations import re -import weakref from abc import ABC, abstractmethod from ast import literal_eval from pathlib import Path @@ -580,7 +579,7 @@ class App(OTBObject): self._exports_dic = {} self._settings, self._auto_parameters = {}, {} self._time_start, self._time_end = 0.0, 0.0 - self.data, self.outputs = {}, {} + self.data = {} self.quiet, self.frozen = quiet, frozen # Param keys and types @@ -598,17 +597,15 @@ class App(OTBObject): for key in self.parameters_keys if self.app.GetParameterType(key) == otb.ParameterType_Choice } + self._out_image_keys = tuple( + key + for key, param in self._out_param_types.items() + if param == otb.ParameterType_OutputImage + ) # Init, execute and write (auto flush only when output param was provided) if args or kwargs: self.set_parameters(*args, **kwargs) - # Create Output image objects - for key in ( - key - for key, param in self._out_param_types.items() - if param == otb.ParameterType_OutputImage - ): - self.outputs[key] = Output(self, key, self._settings.get(key)) if not self.frozen: self.execute() @@ -644,8 +641,8 @@ class App(OTBObject): return self._all_param_types[key] in param_types def __is_multi_output(self): - """Check if app has multiple outputs to ensure re-execution during write().""" - return len(self.outputs) > 1 + """Check if app has multiple image outputs to ensure re-execution in write().""" + return len(self._out_image_keys) > 1 def is_input(self, key: str) -> bool: """Returns True if the parameter key is an input.""" @@ -746,10 +743,8 @@ class App(OTBObject): f"{self.name}: error before execution," f" while setting '{key}' to '{obj}': {e})" ) from e - # Save / update setting value and update the Output object initialized in __init__ without a filepath + # Save / update setting value self._settings[key] = obj - if key in self.outputs: - self.outputs[key].filepath = obj if key in self._auto_parameters: del self._auto_parameters[key] @@ -1105,8 +1100,8 @@ class App(OTBObject): if isinstance(key, str): if key in self.data: return self.data[key] - if key in self.outputs: - return self.outputs[key] + if key in self._out_image_keys: + return Output(self, key, self._settings.get(key)) if key in self.parameters: return self.parameters[key] raise KeyError(f"{self.name}: unknown or undefined parameter '{key}'") @@ -1539,7 +1534,7 @@ class Output(OTBObject): mkdir: bool = True, ): """Constructor for an Output object, initialized during App.__init__.""" - self.parent_pyotb_app = weakref.proxy(pyotb_app) # keep a weak reference to parent app + self.parent_pyotb_app = pyotb_app # keep a weak reference to parent app self.param_key = param_key self.filepath = filepath if mkdir and filepath is not None: -- GitLab From 97811e16ad3a8c0945cb769e9afbd5540f7cdc0a Mon Sep 17 00:00:00 2001 From: Vincent Delbar <vincent.delbar@latelescop.fr> Date: Wed, 9 Oct 2024 16:23:58 +0200 Subject: [PATCH 10/15] Update comment --- pyotb/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyotb/core.py b/pyotb/core.py index d4b7e24..ee73fcb 100644 --- a/pyotb/core.py +++ b/pyotb/core.py @@ -1534,7 +1534,7 @@ class Output(OTBObject): mkdir: bool = True, ): """Constructor for an Output object, initialized during App.__init__.""" - self.parent_pyotb_app = pyotb_app # keep a weak reference to parent app + self.parent_pyotb_app = pyotb_app # keep a reference to parent app self.param_key = param_key self.filepath = filepath if mkdir and filepath is not None: -- GitLab From 0c5d55dea3da07adbef9b95da5709a2363a036ae Mon Sep 17 00:00:00 2001 From: Vincent Delbar <vincent.delbar@latelescop.fr> Date: Wed, 9 Oct 2024 16:28:29 +0200 Subject: [PATCH 11/15] Add version bump and release notes --- RELEASE_NOTES.txt | 6 ++++++ pyotb/__init__.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 7a36b43..02ad82d 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,3 +1,9 @@ +--------------------------------------------------------------------- +2.1.0 (Oct 9, 2024) - Changes since version 2.0.2 + +- Fix memory leak due to circular class reference to Output objects in App +- Braking change : replaced App.outputs by a list of out image keys (App._out_image_keys) + --------------------------------------------------------------------- 2.0.2 (Apr 5, 2024) - Changes since version 2.0.1 diff --git a/pyotb/__init__.py b/pyotb/__init__.py index 594272b..5e58316 100644 --- a/pyotb/__init__.py +++ b/pyotb/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """This module provides convenient python wrapping of otbApplications.""" -__version__ = "2.0.3.dev2" +__version__ = "2.1.0" from .install import install_otb from .helpers import logger -- GitLab From a879d756d0a59488a1a617867a81da5b413e54a0 Mon Sep 17 00:00:00 2001 From: Vincent Delbar <vincent.delbar@latelescop.fr> Date: Wed, 9 Oct 2024 16:28:57 +0200 Subject: [PATCH 12/15] Enhance release notes --- RELEASE_NOTES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 02ad82d..f43d456 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,7 +1,7 @@ --------------------------------------------------------------------- 2.1.0 (Oct 9, 2024) - Changes since version 2.0.2 -- Fix memory leak due to circular class reference to Output objects in App +- Fix memory leak due to circular class reference to Output objects in App.outputs - Braking change : replaced App.outputs by a list of out image keys (App._out_image_keys) --------------------------------------------------------------------- -- GitLab From 81daa2e62066360a2b89c8f583012ca90bd8b542 Mon Sep 17 00:00:00 2001 From: Vincent Delbar <vincent.delbar@latelescop.fr> Date: Wed, 9 Oct 2024 16:34:26 +0200 Subject: [PATCH 13/15] Typo --- RELEASE_NOTES.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index f43d456..90a9076 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,8 +1,8 @@ --------------------------------------------------------------------- 2.1.0 (Oct 9, 2024) - Changes since version 2.0.2 -- Fix memory leak due to circular class reference to Output objects in App.outputs -- Braking change : replaced App.outputs by a list of out image keys (App._out_image_keys) +- Fix memory leak due to circular references to Output objects in list App.outputs +- Breaking change : replaced App.outputs by a list of out image keys (App._out_image_keys) --------------------------------------------------------------------- 2.0.2 (Apr 5, 2024) - Changes since version 2.0.1 -- GitLab From dba41eacc3ee8e323462298d142c6c884902b5f9 Mon Sep 17 00:00:00 2001 From: Vincent Delbar <vincent.delbar@latelescop.fr> Date: Wed, 9 Oct 2024 16:34:57 +0200 Subject: [PATCH 14/15] Remove useless newlines --- RELEASE_NOTES.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 90a9076..a3116c1 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -11,13 +11,11 @@ - Fix a bug with parameters of type "field" for vector files - Fix wrong output parameter key in ImageClassifier and ImageClassifierFromDeepFeatures - --------------------------------------------------------------------- 2.0.1 (Dec 18, 2023) - Changes since version 2.0.0 - Fix a bug when writing outputs in uint8 - --------------------------------------------------------------------- 2.0.0 (Nov 23, 2023) - Changes since version 1.5.4 -- GitLab From a7c46538e15049ce282832e33b8e9a20b37418dd Mon Sep 17 00:00:00 2001 From: Vincent Delbar <vincent.delbar@latelescop.fr> Date: Wed, 9 Oct 2024 16:35:32 +0200 Subject: [PATCH 15/15] Typo --- RELEASE_NOTES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index a3116c1..ff64cbe 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -2,7 +2,7 @@ 2.1.0 (Oct 9, 2024) - Changes since version 2.0.2 - Fix memory leak due to circular references to Output objects in list App.outputs -- Breaking change : replaced App.outputs by a list of out image keys (App._out_image_keys) +- Breaking change : replaced App.outputs by a tuple of out image keys (App._out_image_keys) --------------------------------------------------------------------- 2.0.2 (Apr 5, 2024) - Changes since version 2.0.1 -- GitLab