The @singleton decorator stored its instance in wrapper_singleton.instance
inside a closure. Tests could reset __new__-based singletons via
ClassName._instance = None, but @singleton classes had no equivalent reset
mechanism, causing state to leak between tests.
Add wrapper_singleton.reset() to every @singleton-decorated class. The
method clears wrapper_singleton.instance so the next call creates a fresh
instance, matching the __new__ singleton pattern.
Update all tests to call ClassName.reset() instead of manually setting
ClassName.instance = None (tests/client/test_client.py x5,
tests/client/test_registry.py x1).
Tests added (tests/utils/test_utils.py):
- test_singleton_has_reset: asserts reset is callable on the wrapper
- test_singleton_reset_clears_instance: verifies a new instance is created
after reset(), not the cached one
- test_singleton_instance_is_none_before_first_call: verifies the instance
lifecycle — None → populated → None after reset
Closes#240
- test_checks_initialised_to_false: asserts _checks is False right after
__init__, catching any regression that removes the initialisation
- test_keepalive_check_first_call_no_reset: verifies no AttributeError and
no spurious reset on the very first keepalive_check() call even when the
driver is already dead
- test_keepalive_check: remove the manual _checks = False setup that masked
the original bug; rely on the __init__ value instead
The client registry defined a protocol that all drivers had
to implement. This patch ensures that all methods are
consistent in the protocol definition.