diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 7a36b430f1927e58becbe83fb8bb31adc0c3a71d..ff64cbe1e06b385e302e4cc6fbb944e7baf1809b 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 references to Output objects in list App.outputs +- 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 @@ -5,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 diff --git a/pyotb/__init__.py b/pyotb/__init__.py index 594272bfe336efe543b3a8bea44c6649373848fe..5e5831636cf19b8419a9d9c33afb655ca35fbab4 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 diff --git a/pyotb/core.py b/pyotb/core.py index b78efd478d6c42533f78996ebfba0e70ff449fea..ee73fcbcaa91754afeb41d67b26c35aa49b2274e 100644 --- a/pyotb/core.py +++ b/pyotb/core.py @@ -579,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 @@ -597,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() @@ -643,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.""" @@ -745,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] @@ -1104,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}'") @@ -1538,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 trace of 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: