Issue #20627: xmlrpc.client.ServerProxy is now a context manager.

Patch by Claudiu Popa.
This commit is contained in:
Brett Cannon 2014-03-21 11:24:40 -04:00
parent 051f37d2e7
commit 33a4000374
5 changed files with 42 additions and 10 deletions

View File

@ -191,6 +191,11 @@ grouped under the reserved :attr:`system` attribute:
no such string is available, an empty string is returned. The documentation
string may contain HTML markup.
.. versionchanged:: 3.5
Instances of :class:`ServerProxy` support the :term:`context manager` protocol
for closing the underlying transport.
A working example follows. The server code::
@ -208,9 +213,9 @@ The client code for the preceding server::
import xmlrpc.client
proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")
print("3 is even: %s" % str(proxy.is_even(3)))
print("100 is even: %s" % str(proxy.is_even(100)))
with xmlrpc.client.ServerProxy("http://localhost:8000/") as proxy:
print("3 is even: %s" % str(proxy.is_even(3)))
print("100 is even: %s" % str(proxy.is_even(100)))
.. _datetime-objects:
@ -518,14 +523,14 @@ Example of Client Usage
from xmlrpc.client import ServerProxy, Error
# server = ServerProxy("http://localhost:8000") # local server
server = ServerProxy("http://betty.userland.com")
with ServerProxy("http://betty.userland.com") as proxy:
print(server)
print(proxy)
try:
print(server.examples.getStateName(41))
except Error as v:
print("ERROR", v)
try:
print(proxy.examples.getStateName(41))
except Error as v:
print("ERROR", v)
To access an XML-RPC server through a proxy, you need to define a custom
transport. The following example shows how:

View File

@ -134,7 +134,8 @@ New Modules
Improved Modules
================
* None yet.
* :class:`xmlrpc.client.ServerProxy` is now a :term:`context manager`
(contributed by Claudiu Popa in :issue:`20627`).
Optimizations

View File

@ -713,6 +713,23 @@ class SimpleServerTestCase(BaseServerTestCase):
conn.request('POST', '/RPC2 HTTP/1.0\r\nContent-Length: 100\r\n\r\nbye')
conn.close()
def test_context_manager(self):
with xmlrpclib.ServerProxy(URL) as server:
server.add(2, 3)
self.assertNotEqual(server('transport')._connection,
(None, None))
self.assertEqual(server('transport')._connection,
(None, None))
def test_context_manager_method_error(self):
try:
with xmlrpclib.ServerProxy(URL) as server:
server.add(2, "a")
except xmlrpclib.Fault:
pass
self.assertEqual(server('transport')._connection,
(None, None))
class MultiPathServerTestCase(BaseServerTestCase):
threadFunc = staticmethod(http_multi_server)
@ -898,6 +915,7 @@ class ServerProxyTestCase(unittest.TestCase):
p = xmlrpclib.ServerProxy(self.url, transport=t)
self.assertEqual(p('transport'), t)
# This is a contrived way to make a failure occur on the server side
# in order to test the _send_traceback_header flag on the server
class FailingMessageClass(http.client.HTTPMessage):

View File

@ -1449,6 +1449,12 @@ class ServerProxy:
return self.__transport
raise AttributeError("Attribute %r not found" % (attr,))
def __enter__(self):
return self
def __exit__(self, *args):
self.__close()
# compatibility
Server = ServerProxy

View File

@ -23,6 +23,8 @@ Core and Builtins
Library
-------
- Issue #20627: xmlrpc.client.ServerProxy is now a context manager.
- Issue #19165: The formatter module now raises DeprecationWarning instead of
PendingDeprecationWarning.