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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
18
from bzrlib.smart import message, protocol
19
19
from bzrlib.trace import warning
20
from bzrlib import errors
26
23
class _SmartClient(object):
37
34
self._headers = dict(headers)
39
36
def _send_request(self, protocol_version, method, args, body=None,
40
readv_body=None, body_stream=None):
41
38
encoder, response_handler = self._construct_protocol(
43
40
encoder.set_headers(self._headers)
45
42
if readv_body is not None:
46
43
raise AssertionError(
47
44
"body and readv_body are mutually exclusive.")
48
if body_stream is not None:
50
"body and body_stream are mutually exclusive.")
51
45
encoder.call_with_body_bytes((method, ) + args, body)
52
46
elif readv_body is not None:
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)
47
encoder.call_with_body_readv_array((method, ) + args,
60
50
encoder.call(method, *args)
61
51
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']:
70
53
def _call_and_read_response(self, method, args, body=None, readv_body=None,
71
body_stream=None, expect_response_body=True):
72
self._run_call_hooks(method, args, body, readv_body)
54
expect_response_body=True):
73
55
if self._medium._protocol_version is not None:
74
56
response_handler = self._send_request(
75
57
self._medium._protocol_version, method, args, body=body,
76
readv_body=readv_body, body_stream=body_stream)
58
readv_body=readv_body)
77
59
return (response_handler.read_response_tuple(
78
60
expect_body=expect_response_body),
84
66
self._medium._remember_remote_is_before((1, 6))
85
67
response_handler = self._send_request(
86
68
protocol_version, method, args, body=body,
87
readv_body=readv_body, body_stream=body_stream)
69
readv_body=readv_body)
89
71
response_tuple = response_handler.read_response_tuple(
90
72
expect_body=expect_response_body)
133
115
def call_expecting_body(self, method, *args):
134
116
"""Call a method and return the result and the protocol object.
136
118
The body can be read like so::
138
120
result, smart_protocol = smart_client.call_expecting_body(...)
172
154
args[0], args[1:], readv_body=body, expect_response_body=True)
173
155
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)
181
157
def remote_path_from_transport(self, transport):
182
158
"""Convert transport into a path suitable for using in a request.
184
160
Note that the resulting remote path doesn't encode the host name or
185
161
anything but path, so it is only safe to use it in requests sent over
186
162
the medium from the matching transport.
188
164
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