13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
from bzrlib.smart import message, protocol
19
19
from bzrlib.trace import warning
20
from bzrlib import errors
23
26
class _SmartClient(object):
34
37
self._headers = dict(headers)
36
39
def _send_request(self, protocol_version, method, args, body=None,
40
readv_body=None, body_stream=None):
38
41
encoder, response_handler = self._construct_protocol(
40
43
encoder.set_headers(self._headers)
42
45
if readv_body is not None:
43
46
raise AssertionError(
44
47
"body and readv_body are mutually exclusive.")
48
if body_stream is not None:
50
"body and body_stream are mutually exclusive.")
45
51
encoder.call_with_body_bytes((method, ) + args, body)
46
52
elif readv_body is not None:
47
encoder.call_with_body_readv_array((method, ) + args,
53
if body_stream is not None:
55
"readv_body and body_stream are mutually exclusive.")
56
encoder.call_with_body_readv_array((method, ) + args, readv_body)
57
elif body_stream is not None:
58
encoder.call_with_body_stream((method, ) + args, body_stream)
50
60
encoder.call(method, *args)
51
61
return response_handler
63
def _run_call_hooks(self, method, args, body, readv_body):
64
if not _SmartClient.hooks['call']:
66
params = CallHookParams(method, args, body, readv_body, self._medium)
67
for hook in _SmartClient.hooks['call']:
53
70
def _call_and_read_response(self, method, args, body=None, readv_body=None,
54
expect_response_body=True):
71
body_stream=None, expect_response_body=True):
72
self._run_call_hooks(method, args, body, readv_body)
55
73
if self._medium._protocol_version is not None:
56
74
response_handler = self._send_request(
57
75
self._medium._protocol_version, method, args, body=body,
58
readv_body=readv_body)
76
readv_body=readv_body, body_stream=body_stream)
59
77
return (response_handler.read_response_tuple(
60
78
expect_body=expect_response_body),
66
84
self._medium._remember_remote_is_before((1, 6))
67
85
response_handler = self._send_request(
68
86
protocol_version, method, args, body=body,
69
readv_body=readv_body)
87
readv_body=readv_body, body_stream=body_stream)
71
89
response_tuple = response_handler.read_response_tuple(
72
90
expect_body=expect_response_body)
115
133
def call_expecting_body(self, method, *args):
116
134
"""Call a method and return the result and the protocol object.
118
136
The body can be read like so::
120
138
result, smart_protocol = smart_client.call_expecting_body(...)
154
172
args[0], args[1:], readv_body=body, expect_response_body=True)
155
173
return (response, response_handler)
175
def call_with_body_stream(self, args, stream):
176
response, response_handler = self._call_and_read_response(
177
args[0], args[1:], body_stream=stream,
178
expect_response_body=False)
179
return (response, response_handler)
157
181
def remote_path_from_transport(self, transport):
158
182
"""Convert transport into a path suitable for using in a request.
160
184
Note that the resulting remote path doesn't encode the host name or
161
185
anything but path, so it is only safe to use it in requests sent over
162
186
the medium from the matching transport.
164
188
return self._medium.remote_path_from_transport(transport)
191
class SmartClientHooks(hooks.Hooks):
194
hooks.Hooks.__init__(self)
195
self.create_hook(hooks.HookPoint('call',
196
"Called when the smart client is submitting a request to the "
197
"smart server. Called with a bzrlib.smart.client.CallHookParams "
198
"object. Streaming request bodies, and responses, are not "
199
"accessible.", None, None))
202
_SmartClient.hooks = SmartClientHooks()
205
class CallHookParams(object):
207
def __init__(self, method, args, body, readv_body, medium):
211
self.readv_body = readv_body
215
attrs = dict((k, v) for (k, v) in self.__dict__.iteritems()
217
return '<%s %r>' % (self.__class__.__name__, attrs)
219
def __eq__(self, other):
220
if type(other) is not type(self):
221
return NotImplemented
222
return self.__dict__ == other.__dict__
224
def __ne__(self, other):
225
return not self == other