diff --git a/.bumpversion.cfg b/.bumpversion.cfg index be2e956cc..d13229aa5 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -3,7 +3,7 @@ commit = True message = Bump version {current_version} to {new_version} tag = False tag_name = {new_version} -current_version = 3.1.0 +current_version = 3.1.1 parse = (?P\d+)\.(?P\d+)\.(?P\d+)(\-(?P[a-z]+))? serialize = {major}.{minor}.{patch}-{release} diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cb2ee1b9..fdbd485b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,16 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). This file follows the formats and conventions from [keepachangelog.com] +## [3.1.1] 2021-06-11 + +### Fixed + +* Allow to stop/abort macro executing other hooked macros (#1603, #1608) + +### Deprecated + +* `MacroExecutor.clearRunningMacro()` in favor of `MacroExecutor.clearMacroStack()` (#1608) + ## [3.1.0] 2021-05-17 ### Added @@ -1047,6 +1057,7 @@ Main improvements since sardana 1.5.0 (aka Jan15): [keepachangelog.com]: http://keepachangelog.com +[3.1.1]: https://github.com/sardana-org/sardana/compare/3.1.1...3.1.0 [3.1.0]: https://github.com/sardana-org/sardana/compare/3.1.0...3.0.3 [3.0.3]: https://github.com/sardana-org/sardana/compare/3.0.3...2.8.6 [2.8.6]: https://github.com/sardana-org/sardana/compare/2.8.6...2.8.5 diff --git a/doc/source/news.rst b/doc/source/news.rst index 97bef3f18..58733af9d 100644 --- a/doc/source/news.rst +++ b/doc/source/news.rst @@ -6,6 +6,21 @@ Below you will find the most relevant news that brings the Sardana releases. For a complete list of changes consult the Sardana `CHANGELOG.md \ `_ file. +**************************** +What's new in Sardana 3.1.1? +**************************** + +Date: 2021-06-11 + +Type: hotfix release + +Fixed +===== + +- Correctly handle stop/abort of macros e.g. ``Ctrl+c`` in Spock in case + the macro was executing another hooked macros e.g. a scan executing a general + hook. + ************************** What's new in Sardana 3.1? ************************** diff --git a/src/sardana/macroserver/msmacromanager.py b/src/sardana/macroserver/msmacromanager.py index 73c96f7d3..052d80cea 100644 --- a/src/sardana/macroserver/msmacromanager.py +++ b/src/sardana/macroserver/msmacromanager.py @@ -1088,7 +1088,6 @@ def __init__(self, door): # self._xml_stack = None self._macro_stack = [] self._xml_stack = [] - self._macro_pointer = None self._last_macro = None self._abort_thread = None self._aborted = False @@ -1120,6 +1119,13 @@ def getMacroServer(self): def macro_manager(self): return self.macro_server.macro_manager + @property + def macro_pointer(self): + macro_stack = self._macro_stack + if not macro_stack: + return None + return macro_stack[-1] + def getGeneralHooks(self): """Get data structure containing definition of the general hooks. @@ -1398,7 +1404,7 @@ def prepareMacro(self, pars, init_opts={}, prepare_opts={}): return macro_obj, prepare_result def getRunningMacro(self): - return self._macro_pointer + return self.macro_pointer def getLastMacro(self): return self._last_macro @@ -1407,8 +1413,18 @@ def clearRunningMacro(self): """Clear pointer to the running macro. ..warning:: Do not call it while the macro is running. + + .. deprecated: Use clearMacroStack() instead. """ - self._macro_pointer = None + self.warning("Deprecated since 3.1.1. Use clearMacroStack() instead.") + self._macro_stack = [] + + def clearMacroStack(self): + """Clear macro stack + + ..warning:: Do not call it while the macro is running. + """ + self._macro_stack = [] def __stopObjects(self): """Stops all the reserved objects in the executor""" @@ -1568,7 +1584,6 @@ def run(self, params, asynch=True): # reset the stacks self._macro_stack = [] self._xml_stack = [] - self._macro_pointer = None self._stop_done = threading.Event() self._abort_done = threading.Event() self._aborted = False @@ -1586,7 +1601,6 @@ def run(self, params, asynch=True): return self._xml else: self.__runXML() - # return self._macro_pointer.getResult() def _jobEnded(self, *args, **kw): self.debug("Job ended (stopped=%s, aborted=%s)", @@ -1602,8 +1616,8 @@ def __runXML(self): except Exception: self.sendState(Macro.Exception) finally: - self._macro_stack = None - self._xml_stack = None + self._macro_stack = [] + self._xml_stack = [] def __runStatelessXML(self, xml=None): if xml is None: @@ -1654,7 +1668,6 @@ def runMacro(self, macro_obj): macro_exp, tb, result = None, None, None try: self.debug("[START] runMacro %s" % desc) - self._macro_pointer = macro_obj self._macro_stack.append(macro_obj) for step in macro_obj.exec_(): self.sendMacroStatus((step,)) @@ -1701,7 +1714,7 @@ def runMacro(self, macro_obj): macro_obj._stopOnError() self.sendMacroStatusStop() - self.returnObjs(self._macro_pointer) + self.returnObjs(self.macro_pointer) # From this point on don't call any method of macro_obj which is part # of the mAPI (methods decorated with @mAPI) to avoid throwing an @@ -1722,7 +1735,6 @@ def runMacro(self, macro_obj): self._popMacro() raise macro_exp self.debug("[ END ] runMacro %s" % desc) - self._popMacro() # decide whether to preserve the macro data env_var_name = 'PreserveMacroData' @@ -1731,12 +1743,13 @@ def runMacro(self, macro_obj): except UnknownEnv: preserve_macro_data = True if preserve_macro_data: - self._last_macro = self._macro_pointer + self._last_macro = self.macro_pointer else: self.debug('Macro data will not be preserved. ' + 'Set "%s" environment variable ' % env_var_name + 'to True in order to change it.') - self._macro_pointer = None + self._last_macro = None + self._popMacro() log_macro_manager.disable() @@ -1744,9 +1757,6 @@ def runMacro(self, macro_obj): def _popMacro(self): self._macro_stack.pop() - length = len(self._macro_stack) - if length > 0: - self._macro_pointer = self._macro_stack[-1] def sendState(self, state): return self.door.set_state(state) @@ -1758,7 +1768,7 @@ def sendResult(self, result): return self.door.set_result(result) def getLastMacroStatus(self): - return self._macro_pointer._getMacroStatus() + return self.macro_pointer._getMacroStatus() def sendMacroStatusFinish(self): ms = self.getLastMacroStatus() diff --git a/src/sardana/release.py b/src/sardana/release.py index d9af23114..834a7b12d 100644 --- a/src/sardana/release.py +++ b/src/sardana/release.py @@ -47,7 +47,7 @@ # we use semantic versioning (http://semver.org/) and we update it using the # bumpversion script (https://github.com/peritus/bumpversion) -version = '3.1.0' +version = '3.1.1' description = "instrument control and data acquisition system" diff --git a/src/sardana/tango/macroserver/Door.py b/src/sardana/tango/macroserver/Door.py index cfee3e75f..eec5e7005 100644 --- a/src/sardana/tango/macroserver/Door.py +++ b/src/sardana/tango/macroserver/Door.py @@ -173,7 +173,7 @@ def delete_device(self): if self.getRunningMacro(): self.debug("aborting running macro") self.macro_executor.abort() - self.macro_executor.clearRunningMacro() + self.macro_executor.clearMacroStack() for handler, filter, format in list(self._handler_dict.values()): handler.finish()