From c3a0f6f0683232ac3f90290d4e2923b57d187fdb Mon Sep 17 00:00:00 2001 From: Mark Final Date: Sun, 14 Dec 2025 09:37:29 +0000 Subject: [PATCH 1/4] Tests: Determine all cruizlib modules to test for GUI imports But exclude the workers api modules, since they import Conan packages, into the same process and will infect all subsequent tests. --- .../multiprocessingmessagequeuetype.py | 15 +++++++-- tests/interop/test_imports.py | 32 ------------------- tests/test_imports.py | 32 +++++++++++++++++++ 3 files changed, 44 insertions(+), 35 deletions(-) delete mode 100644 tests/interop/test_imports.py create mode 100644 tests/test_imports.py diff --git a/src/cruizlib/multiprocessingmessagequeuetype.py b/src/cruizlib/multiprocessingmessagequeuetype.py index 732151b8..665e4bf9 100644 --- a/src/cruizlib/multiprocessingmessagequeuetype.py +++ b/src/cruizlib/multiprocessingmessagequeuetype.py @@ -3,9 +3,18 @@ """Type annotation for multiprocssing Queues on Messages.""" import multiprocessing +import multiprocessing.queues from cruizlib.interop.message import Message -# pylint: disable=unsubscriptable-object -MultiProcessingMessageQueueType = multiprocessing.Queue[Message] -MultiProcessingStringJoinableQueueType = multiprocessing.JoinableQueue[str] +try: + # multiprocessing.Queue is a function rather than a class, so it does not satisfy + # the usual static type rules + # multiprocessing.queues is undocumented in more recent Pythons + # see https://github.com/python/cpython/issues/99509#issuecomment-1742069772 + MultiProcessingMessageQueueType = multiprocessing.queues.Queue[Message] + MultiProcessingStringJoinableQueueType = multiprocessing.queues.JoinableQueue[str] +except TypeError: + # pylint: disable=unsubscriptable-object + MultiProcessingMessageQueueType = multiprocessing.Queue[Message] + MultiProcessingStringJoinableQueueType = multiprocessing.JoinableQueue[str] diff --git a/tests/interop/test_imports.py b/tests/interop/test_imports.py deleted file mode 100644 index 8727259c..00000000 --- a/tests/interop/test_imports.py +++ /dev/null @@ -1,32 +0,0 @@ -"""Tests for imports that are prohibited.""" - -import importlib -import sys - -MODULES_TO_IMPORT = ( - "cruizlib.constants", - "cruizlib.globals", - "cruizlib.runcommands", - "cruizlib.interop.commandparameters", - "cruizlib.interop.commonparameters", - "cruizlib.interop.dependencygraph", - "cruizlib.interop.message", - "cruizlib.interop.packagenode", - "cruizlib.interop.pod", -) - - -def test_no_gui_imports() -> None: - """Ensure no GUI imports are in the cruizlib package.""" - for module_path in MODULES_TO_IMPORT: - assert importlib.import_module(module_path) - modules = list(sys.modules.keys()) - modules = [module for module in modules if module.startswith("PySide")] - allow_list_prefix = ("PySide6.support",) - modules = [module for module in modules if not module.startswith(allow_list_prefix)] - allow_list_exact = ( - "PySide6", - "PySide6.QtCore", - ) - modules = [module for module in modules if module not in allow_list_exact] - assert not modules diff --git a/tests/test_imports.py b/tests/test_imports.py new file mode 100644 index 00000000..e14bdf14 --- /dev/null +++ b/tests/test_imports.py @@ -0,0 +1,32 @@ +"""Tests for imports that are prohibited.""" + +import importlib +import os +import pathlib +import sys + + +def test_no_gui_imports() -> None: + """Ensure no GUI imports are in the cruizlib package.""" + current_file_path = pathlib.Path(__file__) + tests_dir = current_file_path.parent + root_dir = tests_dir.parent + src_dir = root_dir / "src" + cruiz_lib_src = src_dir / "cruizlib" + for file in cruiz_lib_src.rglob("*.py"): + if "v1" in os.fspath(file) or "v2" in os.fspath(file): + # those modules that import conan cannot be tested "in process" + continue + module_path = os.fspath(file.relative_to(src_dir)).replace(os.path.sep, ".") + module_name = module_path.replace(".py", "") + assert importlib.import_module(module_name) + modules = list(sys.modules.keys()) + modules = [module for module in modules if module.startswith("PySide")] + allow_list_prefix = ("PySide6.support",) + modules = [module for module in modules if not module.startswith(allow_list_prefix)] + allow_list_exact = ( + "PySide6", + "PySide6.QtCore", + ) + modules = [module for module in modules if module not in allow_list_exact] + assert not modules From 40c1a2ab5aad4144057f457690f52c051ba22063 Mon Sep 17 00:00:00 2001 From: Mark Final Date: Sun, 14 Dec 2025 16:35:24 +0000 Subject: [PATCH 2/4] Fix --- .../multiprocessingmessagequeuetype.py | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/cruizlib/multiprocessingmessagequeuetype.py b/src/cruizlib/multiprocessingmessagequeuetype.py index 665e4bf9..9c2b4bb3 100644 --- a/src/cruizlib/multiprocessingmessagequeuetype.py +++ b/src/cruizlib/multiprocessingmessagequeuetype.py @@ -3,18 +3,19 @@ """Type annotation for multiprocssing Queues on Messages.""" import multiprocessing -import multiprocessing.queues + +# import multiprocessing.queues from cruizlib.interop.message import Message -try: - # multiprocessing.Queue is a function rather than a class, so it does not satisfy - # the usual static type rules - # multiprocessing.queues is undocumented in more recent Pythons - # see https://github.com/python/cpython/issues/99509#issuecomment-1742069772 - MultiProcessingMessageQueueType = multiprocessing.queues.Queue[Message] - MultiProcessingStringJoinableQueueType = multiprocessing.queues.JoinableQueue[str] -except TypeError: - # pylint: disable=unsubscriptable-object - MultiProcessingMessageQueueType = multiprocessing.Queue[Message] - MultiProcessingStringJoinableQueueType = multiprocessing.JoinableQueue[str] +# multiprocessing.Queue is a function rather than a class, so it does not satisfy +# the usual static type rules +# multiprocessing.queues is undocumented in more recent Pythons +# see https://github.com/python/cpython/issues/99509#issuecomment-1742069772 +# unfortunately canot do this while older Pythons (at least 3.10) are being tested +# MultiProcessingMessageQueueType = multiprocessing.queues.Queue[Message] +# MultiProcessingStringJoinableQueueType = multiprocessing.queues.JoinableQueue[str] + +# pylint: disable=unsubscriptable-object +MultiProcessingMessageQueueType = multiprocessing.Queue[Message] +MultiProcessingStringJoinableQueueType = multiprocessing.JoinableQueue[str] From 132955cfe553e2e1b7e82a3043e80c17e998adce Mon Sep 17 00:00:00 2001 From: Mark Final Date: Sun, 14 Dec 2025 16:35:37 +0000 Subject: [PATCH 3/4] Tests: Fail fast on the first error with pytest --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index a38c7e7c..410939d2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -191,6 +191,7 @@ addopts = [ "--cov", "cruizlib", "--cov-report", "term-missing:skip-covered", "--import-mode=importlib", + "-x", ] pythonpath = [ "tests", From bc1fad832363bbace2edf97ce98f27d49e7531d4 Mon Sep 17 00:00:00 2001 From: Mark Final Date: Sun, 14 Dec 2025 16:40:04 +0000 Subject: [PATCH 4/4] see if this works --- src/cruizlib/multiprocessingmessagequeuetype.py | 16 ++++++++-------- tests/test_imports.py | 6 ++++++ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/cruizlib/multiprocessingmessagequeuetype.py b/src/cruizlib/multiprocessingmessagequeuetype.py index 9c2b4bb3..a01d03a8 100644 --- a/src/cruizlib/multiprocessingmessagequeuetype.py +++ b/src/cruizlib/multiprocessingmessagequeuetype.py @@ -3,8 +3,7 @@ """Type annotation for multiprocssing Queues on Messages.""" import multiprocessing - -# import multiprocessing.queues +import multiprocessing.queues from cruizlib.interop.message import Message @@ -13,9 +12,10 @@ # multiprocessing.queues is undocumented in more recent Pythons # see https://github.com/python/cpython/issues/99509#issuecomment-1742069772 # unfortunately canot do this while older Pythons (at least 3.10) are being tested -# MultiProcessingMessageQueueType = multiprocessing.queues.Queue[Message] -# MultiProcessingStringJoinableQueueType = multiprocessing.queues.JoinableQueue[str] - -# pylint: disable=unsubscriptable-object -MultiProcessingMessageQueueType = multiprocessing.Queue[Message] -MultiProcessingStringJoinableQueueType = multiprocessing.JoinableQueue[str] +try: + MultiProcessingMessageQueueType = multiprocessing.queues.Queue[Message] + MultiProcessingStringJoinableQueueType = multiprocessing.queues.JoinableQueue[str] +except TypeError: + # pylint: disable=unsubscriptable-object + MultiProcessingMessageQueueType = multiprocessing.Queue[Message] + MultiProcessingStringJoinableQueueType = multiprocessing.JoinableQueue[str] diff --git a/tests/test_imports.py b/tests/test_imports.py index e14bdf14..f3f96357 100644 --- a/tests/test_imports.py +++ b/tests/test_imports.py @@ -5,7 +5,13 @@ import pathlib import sys +import pytest + +@pytest.mark.skipif( + sys.version_info < (3, 13), + reason="multiprocessing type annotation quirks in older Python versions", +) def test_no_gui_imports() -> None: """Ensure no GUI imports are in the cruizlib package.""" current_file_path = pathlib.Path(__file__)