From fe81adb1945d4e686d2a6a4e3f71fe1c460b7b31 Mon Sep 17 00:00:00 2001 From: Chadwick Boulay Date: Fri, 30 Jan 2026 12:10:56 -0500 Subject: [PATCH] Deprecate ezmsg.util.generator --- examples/ezmsg_generator.py | 56 +++++++++++++++++++++++++++++++++++-- src/ezmsg/util/__init__.py | 2 +- src/ezmsg/util/generator.py | 17 +++++++++++ tests/test_generator.py | 2 ++ 4 files changed, 74 insertions(+), 3 deletions(-) diff --git a/examples/ezmsg_generator.py b/examples/ezmsg_generator.py index cb582952..d281a6b1 100644 --- a/examples/ezmsg_generator.py +++ b/examples/ezmsg_generator.py @@ -1,4 +1,9 @@ """ +.. deprecated:: + This example demonstrates deprecated generator-based patterns from + ``ezmsg.util.generator``. New code should use ``ezmsg.baseproc`` + (BaseTransformer, BaseProducer, etc.) instead. + This ezmsg example showcases a design pattern where core computational logic is encapsulated within a Python generator. This approach is beneficial for several reasons: @@ -22,14 +27,61 @@ """ import asyncio +import traceback import ezmsg.core as ez import numpy as np from typing import Any -from collections.abc import Generator +from collections.abc import AsyncGenerator, Callable, Generator +from functools import wraps, reduce from ezmsg.util.messages.axisarray import AxisArray, replace from ezmsg.util.debuglog import DebugLog from ezmsg.util.gen_to_unit import gen_to_unit -from ezmsg.util.generator import consumer, compose, Gen + + +# --- Inlined helpers (previously from ezmsg.util.generator, now deprecated) --- + +def consumer(func): + """Prime a generator by advancing it to the first yield statement.""" + @wraps(func) + def wrapper(*args, **kwargs): + gen = func(*args, **kwargs) + next(gen) + return gen + return wrapper + + +def compose(*funcs): + """Compose a chain of generator functions into a single callable.""" + return lambda x: reduce(lambda f, g: g.send(f), list(funcs), x) + + +class GenState(ez.State): + gen: Generator[Any, Any, None] + + +class Gen(ez.Unit): + STATE = GenState + + INPUT = ez.InputStream(Any) + OUTPUT = ez.OutputStream(Any) + + async def initialize(self) -> None: + self.construct_generator() + + def construct_generator(self): + raise NotImplementedError + + @ez.subscriber(INPUT) + @ez.publisher(OUTPUT) + async def on_message(self, message: Any) -> AsyncGenerator: + try: + ret = self.STATE.gen.send(message) + if ret is not None: + yield self.OUTPUT, ret + except (StopIteration, GeneratorExit): + ez.logger.debug(f"Generator closed in {self.address}") + except Exception: + ez.logger.info(traceback.format_exc()) @consumer diff --git a/src/ezmsg/util/__init__.py b/src/ezmsg/util/__init__.py index c722ac66..05027c20 100644 --- a/src/ezmsg/util/__init__.py +++ b/src/ezmsg/util/__init__.py @@ -6,7 +6,7 @@ Key modules: - :mod:`ezmsg.util.debuglog`: Debug logging utilities -- :mod:`ezmsg.util.generator`: Generator-based message processing decorators +- :mod:`ezmsg.util.generator`: Generator-based message processing decorators (deprecated — use ``ezmsg.baseproc`` instead) - :mod:`ezmsg.util.messagecodec`: JSON encoding/decoding for message logging - :mod:`ezmsg.util.messagegate`: Message flow control and gating - :mod:`ezmsg.util.messagelogger`: File-based message logging diff --git a/src/ezmsg/util/generator.py b/src/ezmsg/util/generator.py index 7dc04ec6..0d2ebd08 100644 --- a/src/ezmsg/util/generator.py +++ b/src/ezmsg/util/generator.py @@ -1,3 +1,20 @@ +""" +.. deprecated:: + This module is deprecated. Use ``ezmsg.baseproc`` (ezmsg-baseproc) instead. + The ``consumer``, ``compose``, ``GenState``, and ``Gen`` APIs in this module + will be removed in a future release. +""" + +import warnings + +warnings.warn( + "ezmsg.util.generator is deprecated. " + "Use ezmsg.baseproc (BaseTransformer, BaseProducer, etc.) instead. " + "This module will be removed in a future release.", + DeprecationWarning, + stacklevel=2, +) + import ezmsg.core as ez import traceback from collections.abc import AsyncGenerator, Callable, Generator diff --git a/tests/test_generator.py b/tests/test_generator.py index 7736567a..9a9b5f34 100644 --- a/tests/test_generator.py +++ b/tests/test_generator.py @@ -1,3 +1,5 @@ +# NOTE: This file tests the deprecated ezmsg.util.generator module. +# The @consumer usages here are the subject of the tests and should remain. from collections.abc import AsyncGenerator, Generator import copy import json