From 01e7109ec9f60fe59cc7386aa4bebb8192cb9bc2 Mon Sep 17 00:00:00 2001 From: Sven Sager Date: Mon, 20 Nov 2023 08:36:23 +0100 Subject: [PATCH 1/4] chore: Increase to RC3 of upcoming Release 2.7.0 Signed-off-by: Sven Sager --- src/revpimodio2/__about__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/revpimodio2/__about__.py b/src/revpimodio2/__about__.py index 1ac724e..d093900 100644 --- a/src/revpimodio2/__about__.py +++ b/src/revpimodio2/__about__.py @@ -3,4 +3,4 @@ __author__ = "Sven Sager " __copyright__ = "Copyright (C) 2023 Sven Sager" __license__ = "LGPLv2" -__version__ = "2.7.0rc2" +__version__ = "2.7.0rc3" From 12a34e7d11a9f58535eebb64498c3708c195778d Mon Sep 17 00:00:00 2001 From: Sven Sager Date: Mon, 20 Nov 2023 09:04:34 +0100 Subject: [PATCH 2/4] docs: Add IO context manager description Signed-off-by: Sven Sager --- src/revpimodio2/io.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/revpimodio2/io.py b/src/revpimodio2/io.py index 4dae8bd..b77e78d 100644 --- a/src/revpimodio2/io.py +++ b/src/revpimodio2/io.py @@ -88,6 +88,17 @@ class IOList(object): io_del._parentdevice._update_my_io_list() def __enter__(self): + """ + Read inputs on entering context manager and write outputs on leaving. + + All entries are read when entering the context manager. Within the + context manager, further .readprocimg() or .writeprocimg() calls can + be made and the process image can be read or written. When exiting, + all outputs are always written into the process image. + + When 'autorefresh=True' is used, all read or write actions in the + background are performed automatically. + """ if self.__modio._looprunning: raise RuntimeError("can not start multiple mainloop/cycleloop/with sessions") self.__modio._looprunning = True @@ -96,6 +107,12 @@ class IOList(object): return self def __exit__(self, exc_type, exc_val, exc_tb): + """ + Write outputs to process image before leaving the context manager. + + If 'autorefresh=True' is used, this operation is asynchronous. The + outputs are automatically written in the background. + """ self.__modio.writeprocimg() self.__modio._looprunning = False From 5a6ed54e5ceb2c561bbab16e7237a0795a154cba Mon Sep 17 00:00:00 2001 From: Sven Sager Date: Fri, 27 Oct 2023 14:58:11 +0200 Subject: [PATCH 3/4] feat: Add context manager for modio instance Signed-off-by: Sven Sager --- src/revpimodio2/io.py | 12 ++++++++---- src/revpimodio2/modio.py | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/revpimodio2/io.py b/src/revpimodio2/io.py index b77e78d..f12467f 100644 --- a/src/revpimodio2/io.py +++ b/src/revpimodio2/io.py @@ -99,9 +99,11 @@ class IOList(object): When 'autorefresh=True' is used, all read or write actions in the background are performed automatically. """ - if self.__modio._looprunning: - raise RuntimeError("can not start multiple mainloop/cycleloop/with sessions") - self.__modio._looprunning = True + if not self.__modio._context_manager: + # If ModIO itself is in a context manager, it sets the _looprunning=True flag itself + if self.__modio._looprunning: + raise RuntimeError("can not enter context manager inside mainloop or cycleloop") + self.__modio._looprunning = True self.__modio.readprocimg() return self @@ -114,7 +116,9 @@ class IOList(object): outputs are automatically written in the background. """ self.__modio.writeprocimg() - self.__modio._looprunning = False + if self.__modio._context_manager: + # Do not reset if ModIO is in a context manager itself, it will handle that flag + self.__modio._looprunning = False def __getattr__(self, key): """ diff --git a/src/revpimodio2/modio.py b/src/revpimodio2/modio.py index 38bceb1..ff37f3a 100644 --- a/src/revpimodio2/modio.py +++ b/src/revpimodio2/modio.py @@ -70,6 +70,7 @@ class RevPiModIO(object): "_autorefresh", "_buffedwrite", "_configrsc", + "_context_manager", "_debug", "_devselect", "_exit", @@ -146,6 +147,7 @@ class RevPiModIO(object): self._autorefresh = autorefresh self._configrsc = configrsc + self._context_manager = False self._monitoring = monitoring self._procimg = "/dev/piControl0" if procimg is None else procimg self._set_device_based_cycle_time = True @@ -205,6 +207,22 @@ class RevPiModIO(object): if self._myfh is not None: self._myfh.close() + def __enter__(self): + if self._context_manager: + raise RuntimeError("can not use multiple context managers of same instance") + if self._looprunning: + raise RuntimeError("can not enter context manager with running mainloop or cycleloop") + self._context_manager = True + self._looprunning = True + + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.writeprocimg() + self.exit(full=True) + self._looprunning = False + self._context_manager = False + def __evt_exit(self, signum, sigframe) -> None: """ Eventhandler fuer Programmende. @@ -805,6 +823,9 @@ class RevPiModIO(object): :param blocking: Wenn False, blockiert das Programm hier NICHT :return: None or the return value of the cycle function """ + # Check for context manager + if self._context_manager: + raise RuntimeError("Can not start cycleloop inside a context manager (with statement)") # Prüfen ob ein Loop bereits läuft if self._looprunning: raise RuntimeError("can not start multiple loops mainloop/cycleloop") @@ -1060,6 +1081,9 @@ class RevPiModIO(object): :param blocking: Wenn False, blockiert das Programm hier NICHT """ + # Check for context manager + if self._context_manager: + raise RuntimeError("Can not start mainloop inside a context manager (with statement)") # Prüfen ob ein Loop bereits läuft if self._looprunning: raise RuntimeError("can not start multiple loops mainloop/cycleloop") From d5320603f55595910cc3246f3d96f60574c5fdd5 Mon Sep 17 00:00:00 2001 From: Sven Sager Date: Mon, 20 Nov 2023 10:14:33 +0100 Subject: [PATCH 4/4] feat: Add context manager for modio instance Signed-off-by: Sven Sager --- src/revpimodio2/io.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/revpimodio2/io.py b/src/revpimodio2/io.py index f12467f..847339b 100644 --- a/src/revpimodio2/io.py +++ b/src/revpimodio2/io.py @@ -109,13 +109,18 @@ class IOList(object): return self def __exit__(self, exc_type, exc_val, exc_tb): - """ - Write outputs to process image before leaving the context manager. + """Write outputs to process image before leaving the context manager.""" + if self.__modio._imgwriter.is_alive(): + # Reset new data flat to sync with imgwriter + self.__modio._imgwriter.newdata.clear() - If 'autorefresh=True' is used, this operation is asynchronous. The - outputs are automatically written in the background. - """ + # Write outputs on devices without autorefresh self.__modio.writeprocimg() + + if self.__modio._imgwriter.is_alive(): + # Wait until imgwriter has written outputs + self.__modio._imgwriter.newdata.wait(2.5) + if self.__modio._context_manager: # Do not reset if ModIO is in a context manager itself, it will handle that flag self.__modio._looprunning = False