-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add context manager to the client API #2815
base: main
Are you sure you want to change the base?
Conversation
`ApiClient` inherence from `requests.session` that implements `__enter__` and `__exit__` methods and the issue docker#2808 asks to add the same behaviour to the `DockerClient`. At the same time, issue docker#2766 reports a file descriptor leak when `_get_raw_response_socket` is called. To fix both requests, I added a `set` to the `ApiClient` instance to track every socket open by `_get_raw_response_socket` and close when the `close` method is called. I added a test, and documentation now brings the context manager as an example. Signed-off-by: Felipe Ruhland <felipe.ruhland@gmail.com>
@@ -209,6 +218,20 @@ def __init__(self, base_url=None, version=None, | |||
'library.'.format(MINIMUM_DOCKER_API_VERSION) | |||
) | |||
|
|||
def __exit__(self, exc_type, exc_value, traceback): | |||
super().__exit__(exc_type, exc_value, traceback) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're losing any potential return value here, hence overriding any attempt by the super class to suppress an in-flight exception.
@@ -209,6 +218,20 @@ def __init__(self, base_url=None, version=None, | |||
'library.'.format(MINIMUM_DOCKER_API_VERSION) | |||
) | |||
|
|||
def __exit__(self, exc_type, exc_value, traceback): | |||
super().__exit__(exc_type, exc_value, traceback) | |||
self._close_sockets() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm somewhat unclear on the flow here. If we don't define __exit__
, won't the parent's __exit__
call our close method anyway, so the close
definition later would be sufficient.
I might be overlooking something though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also feel like in the current flow, we'll super-call close twice, once in super().__exit__
, and then again in our own close
called from here. That seems odd, and I see a double-close in one of the tests too. Is there some other issue with close
that we're covering up by recalling close()
so much?
url = client._url('/no-tty') | ||
resp = client._post(url, stream=True) | ||
return client._read_from_socket( | ||
resp, stream=stream, tty=tty, demux=demux) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this deliberately introducing a leak by lifting the APIClient out of a with
?
Would it be better to make this a generator instead or something?
This should also close #2457. |
ApiClient
inherence fromrequests.session
that implements__enter__
and__exit__
methods and the issue #2808 asks to add thesame behaviour to the
DockerClient
.At the same time, issue #2766 reports a file descriptor leak when
_get_raw_response_socket
is called.To fix both requests, I added a
set
to theApiClient
instance totrack every socket open by
_get_raw_response_socket
and close whenthe
close
method is called.I added a test, and documentation now brings the context manager as an
example.
Signed-off-by: Felipe Ruhland felipe.ruhland@gmail.com