From 1b7f73c722a84efa022137b99d90dfbde87e54cb Mon Sep 17 00:00:00 2001 From: Bernhard Lang <82966268+bernhardlang@users.noreply.github.com> Date: Sat, 29 Aug 2026 11:43:17 +0200 Subject: [PATCH 1/3] added to draft: minimal example for exposing classes and methods using decorators --- draft/test_decorators.py | 147 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 draft/test_decorators.py diff --git a/draft/test_decorators.py b/draft/test_decorators.py new file mode 100644 index 0000000..79efe0c --- /dev/null +++ b/draft/test_decorators.py @@ -0,0 +1,147 @@ +class SequencerObjectManager: + + def __init__(self): + self.objects = [] + + def register(self, obj): + self.objects.append(obj) + + +sequencer_object_manager = SequencerObjectManager() + + +def expose_to_sequencer(manager): + + def decorator(cls): + + decorator_exposed_methods = [ + name for name in cls.__dict__ + if getattr(getattr(cls, name), "_exposed", False) + # default False if attr _exposed not present + ] + + if hasattr(cls, 'exposed_methods'): + for name in decorator_exposed_methods: + if name not in cls.exposed_methods: + cls.exposed_methods.append(name) + else: + cls.exposed_methods = decorator_exposed_methods + + original_init = cls.__init__ + + def __init__(self, *args, **kwargs): + original_init(self, *args, **kwargs) + manager.register(self) + + cls.__init__ = __init__ + return cls + + return decorator + + +def expose(method): + method._exposed = True + return method + + +# class written for the sequencer +@expose_to_sequencer(sequencer_object_manager) +class ExposedClassA: + + exposed_methods = ['method_a', 'method_b'] + + def __init__(self, name): + self.name = name + + def method_a(self): + pass + + def method_b(self): + pass + + def method_c(self): + pass + + def method_d(self): + pass + + +# also written for the sequencer, but with method decorator approach +@expose_to_sequencer(sequencer_object_manager) +class ExposedClassB: + + def __init__(self, name): + self.name = name + + @expose + def method_a(self): + pass + + def method_b(self): + pass + + @expose + def method_c(self): + pass + + def method_d(self): + pass + + +# also written for the sequencer, mixing both approaches because @expose is not +# compatible with @property (and possibly other decorators) +@expose_to_sequencer(sequencer_object_manager) +class ExposedClassC: + + exposed_methods = ['method_b'] + + def __init__(self, name): + self.name = name + + @expose + def method_a(self): + pass + + @property + def method_b(self): + return "something" @expose + + def method_c(self): + pass + + def method_d(self): + pass + + +# some PyMoDAQ class to be exposed to the sequencer without modifying the class +class OriginalClass: + + def __init__(self, name): + self.name = name + + def method_a(self): + pass + + def method_b(self): + pass + + def method_c(self): + pass + + def method_d(self): + pass + + + +@expose_to_sequencer(sequencer_object_manager) +class ExposedOriginalClass(OriginalClass): + exposed_methods = ['method_c', 'method_d'] + + +inst1 = ExposedClassA("With Dict") +inst2 = ExposedClassB("With Decorator") +inst2 = ExposedClassC("Mixed") +inst3 = ExposedOriginalClass("Derived Class") + +print([f'{o.name}: {o.exposed_methods}' + for o in sequencer_object_manager.objects]) From 581afc49c566878402b7f6292c2d791d3177470c Mon Sep 17 00:00:00 2001 From: Bernhard Lang <82966268+bernhardlang@users.noreply.github.com> Date: Sat, 29 Aug 2026 11:50:41 +0200 Subject: [PATCH 2/3] fixing typo and reordering for better comprehensibility --- draft/test_decorators.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/draft/test_decorators.py b/draft/test_decorators.py index 79efe0c..f1bb370 100644 --- a/draft/test_decorators.py +++ b/draft/test_decorators.py @@ -10,6 +10,11 @@ def register(self, obj): sequencer_object_manager = SequencerObjectManager() +def expose(method): + method._exposed = True + return method + + def expose_to_sequencer(manager): def decorator(cls): @@ -39,11 +44,6 @@ def __init__(self, *args, **kwargs): return decorator -def expose(method): - method._exposed = True - return method - - # class written for the sequencer @expose_to_sequencer(sequencer_object_manager) class ExposedClassA: @@ -104,7 +104,7 @@ def method_a(self): @property def method_b(self): - return "something" @expose + return "something" def method_c(self): pass From d8097c411a7ee5850f922fecb863eaec0b14f070 Mon Sep 17 00:00:00 2001 From: Bernhard Lang <82966268+bernhardlang@users.noreply.github.com> Date: Sat, 29 Aug 2026 11:54:02 +0200 Subject: [PATCH 3/3] doc --- draft/{test_decorators.py => decorator_example.py} | 4 ++++ 1 file changed, 4 insertions(+) rename draft/{test_decorators.py => decorator_example.py} (98%) diff --git a/draft/test_decorators.py b/draft/decorator_example.py similarity index 98% rename from draft/test_decorators.py rename to draft/decorator_example.py index f1bb370..ffe9706 100644 --- a/draft/test_decorators.py +++ b/draft/decorator_example.py @@ -1,3 +1,5 @@ +### decorator code + class SequencerObjectManager: def __init__(self): @@ -44,6 +46,8 @@ def __init__(self, *args, **kwargs): return decorator +### examples and testing + # class written for the sequencer @expose_to_sequencer(sequencer_object_manager) class ExposedClassA: