From ddfd06876d7a8305f35876e76b5610aa21db9035 Mon Sep 17 00:00:00 2001 From: hmasdev Date: Sun, 16 Nov 2025 11:53:41 +0900 Subject: [PATCH 1/3] Refactor type annotations in factory functions and improve stopwatch decorator documentation --- .../key_monitor/factory.py | 5 +- .../sentence_generator/factory.py | 5 +- .../openai_sentence_generator.py | 4 +- simple_typing_application/ui/factory.py | 5 +- simple_typing_application/utils/stopwatch.py | 56 ++++++++++++++++++- 5 files changed, 65 insertions(+), 10 deletions(-) diff --git a/simple_typing_application/key_monitor/factory.py b/simple_typing_application/key_monitor/factory.py index aaceb18..f538c1d 100644 --- a/simple_typing_application/key_monitor/factory.py +++ b/simple_typing_application/key_monitor/factory.py @@ -37,10 +37,11 @@ def create_key_monitor( # create key monitor logger.debug(f"create {key_monitor_cls.__name__}") + key_monitor_config: BaseKeyMonitorConfigModel if isinstance(config, key_monitor_config_model): - key_monitor_config: BaseKeyMonitorConfigModel = config + key_monitor_config = config else: - key_monitor_config: BaseKeyMonitorConfigModel = key_monitor_config_model(**config.model_dump()) # noqa + key_monitor_config = key_monitor_config_model(**config.model_dump()) # noqa key_monitor: BaseKeyMonitor = key_monitor_cls(**key_monitor_config.model_dump()) # type: ignore # noqa return key_monitor diff --git a/simple_typing_application/sentence_generator/factory.py b/simple_typing_application/sentence_generator/factory.py index 1cc92f9..5215f62 100644 --- a/simple_typing_application/sentence_generator/factory.py +++ b/simple_typing_application/sentence_generator/factory.py @@ -50,10 +50,11 @@ def create_sentence_generator( # create sentence generator logger.debug(f"create {sentence_generator_cls.__name__}") + sentence_generator_config: BaseSentenceGeneratorConfigModel if isinstance(config, sentence_generator_config_model): - sentence_generator_config: BaseSentenceGeneratorConfigModel = config + sentence_generator_config = config else: - sentence_generator_config: BaseSentenceGeneratorConfigModel = sentence_generator_config_model(**config.model_dump()) # noqa + sentence_generator_config = sentence_generator_config_model(**config.model_dump()) # noqa sentence_generator: BaseSentenceGenerator = sentence_generator_cls(**sentence_generator_config.model_dump()) # type: ignore # noqa return sentence_generator diff --git a/simple_typing_application/sentence_generator/openai_sentence_generator.py b/simple_typing_application/sentence_generator/openai_sentence_generator.py index 24663fb..015b3ba 100644 --- a/simple_typing_application/sentence_generator/openai_sentence_generator.py +++ b/simple_typing_application/sentence_generator/openai_sentence_generator.py @@ -90,8 +90,8 @@ async def generate( self._logger.debug(f"agent input messages: {messages}") with stopwatch(level=DEBUG, logger=self._logger, prefix="OpenAI agent invocation"): ret: dict[str, Any] = await self._agent.ainvoke( - {"messages": messages}, - ) # type: ignore + {"messages": messages}, # type: ignore + ) self._logger.debug(f"agent response: {ret}") # store to memory diff --git a/simple_typing_application/ui/factory.py b/simple_typing_application/ui/factory.py index 3f937af..f01f46d 100644 --- a/simple_typing_application/ui/factory.py +++ b/simple_typing_application/ui/factory.py @@ -32,10 +32,11 @@ def create_user_interface( # create user interface logger.debug(f"create {user_interface_cls.__name__}") + user_interface_config: BaseUserInterfaceConfigModel if isinstance(config, user_interface_config_model): - user_interface_config: BaseUserInterfaceConfigModel = config + user_interface_config = config else: - user_interface_config: BaseUserInterfaceConfigModel = user_interface_config_model(**config.model_dump()) # noqa + user_interface_config = user_interface_config_model(**config.model_dump()) # noqa user_interface: BaseUserInterface = user_interface_cls(**user_interface_config.model_dump()) # type: ignore # noqa return user_interface diff --git a/simple_typing_application/utils/stopwatch.py b/simple_typing_application/utils/stopwatch.py index 2dee7f4..faf00e2 100644 --- a/simple_typing_application/utils/stopwatch.py +++ b/simple_typing_application/utils/stopwatch.py @@ -3,7 +3,7 @@ from contextlib import contextmanager from functools import wraps, partial from logging import Logger, getLogger -from typing import Callable, Generator, TypeVar, ParamSpec +from typing import Callable, Generator, TypeVar, ParamSpec, overload T = TypeVar("T") P = ParamSpec("P") @@ -67,8 +67,9 @@ def stopwatch( log_func(log_msg_fmt.format(elapsed_time=end_time - start_time)) +@overload def stopwatch_deco( - func: Callable[P, T] | None = None, + func: Callable[P, T], *, level: int = logging.INFO, prefix: str | None = None, @@ -77,6 +78,57 @@ def stopwatch_deco( ) -> Callable[P, T]: """Decorator to measure the execution time of a function. + Args: + func (Callable[P, T]): function to be decorated. + *, + level (int, optional): log level. Defaults to logging.INFO. + Must be one of logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL. + prefix (str | None, optional): prefix of the log message. Defaults to None. + postfix (str, optional): postfix of the log message. Defaults to "". + logger (Logger, optional): logger. Defaults to logger. + + Returns: + Callable[P, T]: decorated function. + """ # noqa + ... + + +@overload +def stopwatch_deco( + func: None = None, + *, + level: int = logging.INFO, + prefix: str | None = None, + postfix: str = "", + logger: Logger = logger, +) -> Callable[[Callable[P, T]], Callable[P, T]]: + """Decorator to measure the execution time of a function. + + Args: + func (Callable[P, T], optional): function to be decorated. Defaults to None. + *, + level (int, optional): log level. Defaults to logging.INFO. + Must be one of logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL. + prefix (str | None, optional): prefix of the log message. Defaults to None. + postfix (str, optional): postfix of the log message. Defaults to "". + logger (Logger, optional): logger. Defaults to logger. + + Returns: + Callable[[Callable[P, T]], Callable[P, T]]: decorator. + """ # noqa + ... + + +def stopwatch_deco( + func: Callable[P, T] | None = None, + *, + level: int = logging.INFO, + prefix: str | None = None, + postfix: str = "", + logger: Logger = logger, +) -> Callable[P, T] | Callable[[Callable[P, T]], Callable[P, T]]: + """Decorator to measure the execution time of a function. + Args: func (Callable[P, T], optional): function to be decorated. Defaults to None. *, From 4bc243ec29af804accf166f94de97236ac658298 Mon Sep 17 00:00:00 2001 From: hmasdev Date: Sun, 16 Nov 2025 11:59:08 +0900 Subject: [PATCH 2/3] Remove unnecessary asterisk from stopwatch_deco function arguments --- simple_typing_application/utils/stopwatch.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/simple_typing_application/utils/stopwatch.py b/simple_typing_application/utils/stopwatch.py index faf00e2..13144f9 100644 --- a/simple_typing_application/utils/stopwatch.py +++ b/simple_typing_application/utils/stopwatch.py @@ -80,7 +80,6 @@ def stopwatch_deco( Args: func (Callable[P, T]): function to be decorated. - *, level (int, optional): log level. Defaults to logging.INFO. Must be one of logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL. prefix (str | None, optional): prefix of the log message. Defaults to None. @@ -105,8 +104,7 @@ def stopwatch_deco( """Decorator to measure the execution time of a function. Args: - func (Callable[P, T], optional): function to be decorated. Defaults to None. - *, + func (None): None. Defaults to None. level (int, optional): log level. Defaults to logging.INFO. Must be one of logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL. prefix (str | None, optional): prefix of the log message. Defaults to None. @@ -131,7 +129,6 @@ def stopwatch_deco( Args: func (Callable[P, T], optional): function to be decorated. Defaults to None. - *, level (int, optional): log level. Defaults to logging.INFO. Must be one of logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL. prefix (str | None, optional): prefix of the log message. Defaults to None. From 7c93b0a2f2089df9448e23d29c03d6ab365add3f Mon Sep 17 00:00:00 2001 From: "H. Masui" <73353463+hmasdev@users.noreply.github.com> Date: Sun, 16 Nov 2025 12:04:02 +0900 Subject: [PATCH 3/3] Update simple_typing_application/utils/stopwatch.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- simple_typing_application/utils/stopwatch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simple_typing_application/utils/stopwatch.py b/simple_typing_application/utils/stopwatch.py index 13144f9..c1f1ea5 100644 --- a/simple_typing_application/utils/stopwatch.py +++ b/simple_typing_application/utils/stopwatch.py @@ -104,7 +104,7 @@ def stopwatch_deco( """Decorator to measure the execution time of a function. Args: - func (None): None. Defaults to None. + func (None): Not used in this overload. This signature is for parameterized decoration (e.g., @stopwatch_deco(level=DEBUG)). level (int, optional): log level. Defaults to logging.INFO. Must be one of logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL. prefix (str | None, optional): prefix of the log message. Defaults to None.