Skip to content

Commit 51e72ae

Browse files
committed
Hold a strong reference to the client in _ControllerProxy
The proxy stored weakref.proxy(client), but nothing else kept the client alive, so the one-expression idiom SpaceTrackClient(...).basicspacedata.gp(...) collected the client mid-expression and raised ReferenceError, and hasattr/getattr on a proxy that outlived its client raised ReferenceError instead of reporting the attribute missing. The client-to-proxy reference cycle this creates is handled by the garbage collector, and the finalizer still fires because it does not reference the instance.
1 parent 168de31 commit 51e72ae

3 files changed

Lines changed: 12 additions & 3 deletions

File tree

newsfragments/167.fixed.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed a :class:`ReferenceError` when chaining a request off a temporary client, e.g. ``SpaceTrackClient(...).basicspacedata.gp(...)``.

src/spacetrack/base.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,9 +1090,7 @@ class _ControllerProxy:
10901090
"""Proxies request class methods with a preset request controller."""
10911091

10921092
def __init__(self, client, controller):
1093-
# The client will cache _ControllerProxy instances, so only store
1094-
# a weak reference to it.
1095-
self.client = weakref.proxy(client)
1093+
self.client = client
10961094
self.controller = controller
10971095

10981096
def __getattr__(self, attr):

tests/test_spacetrack.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,16 @@ def test_controller_spacetrack_methods(client):
368368
assert mock_generic_request.call_args == expected
369369

370370

371+
def test_controller_proxy_keeps_client_alive(httpx2_mock):
372+
# A _ControllerProxy used to hold only a weak reference, so using a
373+
# proxy after the client's last strong reference was dropped raised
374+
# ReferenceError.
375+
with patch.object(SpaceTrackClient, "generic_request") as mock_generic_request:
376+
SpaceTrackClient("identity", "password").basicspacedata.gp()
377+
378+
mock_generic_request.assert_called_once()
379+
380+
371381
def test_authenticate(httpx2_mock):
372382
def request_callback(request):
373383
if b"wrongpassword" in request.content:

0 commit comments

Comments
 (0)