From a7fbd1664a046a2558a09c0a31e32e1e2165c71d Mon Sep 17 00:00:00 2001 From: lou lecrivain Date: Wed, 11 Feb 2026 14:19:49 +0100 Subject: [PATCH 1/2] override multiprocessing default context start method during tests this is related to #85 aka "mock is broken in subprocesses on mac os" --- cosmo/clients/__init__.py | 10 ++++++++++ cosmo/clients/netbox_v4.py | 3 ++- cosmo/tests/test_netboxclient.py | 7 +++++++ cosmo/tests/utils.py | 17 +++++++++++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/cosmo/clients/__init__.py b/cosmo/clients/__init__.py index e69de29b..b022d473 100644 --- a/cosmo/clients/__init__.py +++ b/cosmo/clients/__init__.py @@ -0,0 +1,10 @@ +import multiprocessing + + +def get_client_mp_context(method=None): + # this will set and return the global context, by default + # since method is None. the reason why we use this + # boilerplate is to have an anchor point for + # monkeypatching the multiprocessing context + # during tests. + return multiprocessing.get_context(method=method) diff --git a/cosmo/clients/netbox_v4.py b/cosmo/clients/netbox_v4.py index a8486ed6..348848d9 100644 --- a/cosmo/clients/netbox_v4.py +++ b/cosmo/clients/netbox_v4.py @@ -4,6 +4,7 @@ from multiprocessing import Manager from string import Template +from cosmo.clients import get_client_mp_context from cosmo.clients.netbox_client import NetboxAPIClient @@ -658,7 +659,7 @@ def get_data(self, device_config): # from the main thread. by default this is not possible, see # https://stackoverflow.com/questions/72411392/can-you-do-nested-parallelization-using-multiprocessing-in-python # this avoids having to re-architecture completely using worker/task/queue model. - with Manager() as manager: + with get_client_mp_context().Manager() as manager: client = NetboxAPIClient(self.url, self.token, manager.dict()) for d in device_list: diff --git a/cosmo/tests/test_netboxclient.py b/cosmo/tests/test_netboxclient.py index ac6ddb7e..50368ff5 100644 --- a/cosmo/tests/test_netboxclient.py +++ b/cosmo/tests/test_netboxclient.py @@ -1,14 +1,21 @@ +from unittest.mock import patch + import pytest from packaging.version import Version import cosmo.tests.utils as utils from cosmo.clients.netbox import NetboxClient +from cosmo.tests.utils import override_get_client_mp_context TEST_URL = "https://netbox.example.com" TEST_TOKEN = "token123" TEST_DEVICE_CFG = {"router": ["router1", "router2"], "switch": ["switch1", "switch2"]} +@patch( + "cosmo.clients.netbox_v4.get_client_mp_context", + new=override_get_client_mp_context("fork"), +) def test_case_get_data(mocker): mockAnswer = { "device_list": [], diff --git a/cosmo/tests/utils.py b/cosmo/tests/utils.py index cc31ec70..851cfb90 100644 --- a/cosmo/tests/utils.py +++ b/cosmo/tests/utils.py @@ -1,4 +1,12 @@ import json +import multiprocessing + + +def override_get_client_mp_context(method=None): + def overriden_get_client_mp_context(): + return multiprocessing.get_context(method=method) + + return overriden_get_client_mp_context class CommonSetup: @@ -17,6 +25,15 @@ def __init__( self.patches.append(self.mocker.patch.dict("os.environ", environ)) # patch args, since current ones are from pytest call self.patches.append(self.mocker.patch("sys.argv", args)) + # patch netbox client default mp context for the time of the tests + # patch may be ineffective since not in correct namespace(?) + self.patches.append( + self.mocker.patch( + "cosmo.clients.netbox_v4.get_client_mp_context", + new=override_get_client_mp_context("fork"), + ) + ) + # patch configuration file lookup if requested # Note: If there is no configuration file given, we still need to patch this. From 23ec664d4c6101152fd8f7b250e22d9c5a9e4cc3 Mon Sep 17 00:00:00 2001 From: lou lecrivain Date: Wed, 11 Feb 2026 14:56:59 +0100 Subject: [PATCH 2/2] Revert "flake: disable netbox tests on darwin" This reverts commit 6faa526d64bcb231aa54d46f24fd639ece0ad27c. --- package.nix | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/package.nix b/package.nix index fd17b63a..c0da79e8 100644 --- a/package.nix +++ b/package.nix @@ -1,6 +1,4 @@ -{ lib, - stdenv, - buildPythonApplication, +{ buildPythonApplication, python, poetry-core, requests, @@ -41,16 +39,6 @@ buildPythonApplication rec { coverage ]; - disabledTests = lib.optionals stdenv.hostPlatform.isDarwin [ - # https://github.com/wobcom/cosmo/issues/85 - "test_limit_argument_with_commas" - "test_limit_arguments_with_repeat" - "test_device_generation_ansible" - "test_device_generation_nix" - "test_device_processing_error" - "test_case_get_data" - ]; - passthru = { pythonEnv = python.withPackages (_: dependencies); };