From 1d4f2dc53be72456ac47209befe906c5f1b6556f Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 25 Mar 2024 10:13:36 +0100 Subject: [PATCH] testutil: extract `find_one_subclass_in_module()` helper A small refactor to avoid shipping this duplicated code (this one is easy to extract/reuse). --- inputs/test/conftest.py | 10 +--------- osbuild/testutil/__init__.py | 18 ++++++++++++++++++ sources/test/conftest.py | 14 +++----------- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/inputs/test/conftest.py b/inputs/test/conftest.py index ed1e79fe..df9ebd63 100644 --- a/inputs/test/conftest.py +++ b/inputs/test/conftest.py @@ -1,4 +1,3 @@ -import inspect import os import pathlib from types import ModuleType @@ -28,14 +27,7 @@ def inputs_service(inputs_module) -> ModuleType: """inputs_service is a fixture that imports a inputs module by its name defined in INPUTS_NAME in the test module and returns a InputService """ - service_cls = None - for memb in inspect.getmembers( - inputs_module, - predicate=lambda obj: inspect.isclass(obj) and issubclass( - obj, inputs.InputService)): - if service_cls: - raise ValueError(f"already have {service_cls}, also found {memb}") - service_cls = memb[1] + service_cls = testutil.find_one_subclass_in_module(inputs_module, inputs.InputService) fd = testutil.make_fake_service_fd() srv_obj = service_cls.from_args(["--service-fd", str(fd)]) return srv_obj diff --git a/osbuild/testutil/__init__.py b/osbuild/testutil/__init__.py index e5e1a1fe..12266a4c 100644 --- a/osbuild/testutil/__init__.py +++ b/osbuild/testutil/__init__.py @@ -2,6 +2,7 @@ Test related utilities """ import contextlib +import inspect import os import pathlib import re @@ -10,6 +11,8 @@ import socket import subprocess import tempfile import textwrap +from types import ModuleType +from typing import Type def has_executable(executable: str) -> bool: @@ -168,3 +171,18 @@ def make_fake_service_fd() -> int: sock = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET) fd = os.dup(sock.fileno()) return fd + + +def find_one_subclass_in_module(module: ModuleType, subclass: Type) -> object: + """Find the class in the given module that is a subclass of the given input + + If multiple classes are found an error is raised. + """ + cls = None + for name, memb in inspect.getmembers( + module, + predicate=lambda obj: inspect.isclass(obj) and issubclass(obj, subclass)): + if cls: + raise ValueError(f"already have {cls}, also found {name}:{memb}") + cls = memb + return cls diff --git a/sources/test/conftest.py b/sources/test/conftest.py index 8ff0a308..e7f6e019 100644 --- a/sources/test/conftest.py +++ b/sources/test/conftest.py @@ -1,4 +1,3 @@ -import inspect import os import pathlib from types import ModuleType @@ -28,14 +27,7 @@ def sources_service(sources_module) -> ModuleType: """sources_service is a fixture that imports a sources module by its name defined in SOURCES_NAME in the test module and returns a SourcesService """ - service_cls = None - for memb in inspect.getmembers( - sources_module, - predicate=lambda obj: inspect.isclass(obj) and issubclass( - obj, sources.SourceService)): - if service_cls: - raise ValueError(f"already have {service_cls}, also found {memb}") - service_cls = memb[1] + service_cls = testutil.find_one_subclass_in_module(sources_module, sources.SourceService) fd = testutil.make_fake_service_fd() - services_obj = service_cls.from_args(["--service-fd", str(fd)]) - return services_obj + srv_obj = service_cls.from_args(["--service-fd", str(fd)]) + return srv_obj