Skip to content

Add forwarding msgpack packer and unpacker to call function #190

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions tarantool/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ def _read_response(self):
# Read the packet
return self._recv(length)

def _send_request_wo_reconnect(self, request):
def _send_request_wo_reconnect(self, request, unpacker=None):
'''
:rtype: `Response` instance or subclass

Expand All @@ -293,7 +293,7 @@ def _send_request_wo_reconnect(self, request):
while True:
try:
self._socket.sendall(bytes(request))
response = request.response_class(self, self._read_response())
response = request.response_class(self, self._read_response(), unpacker=unpacker)
break
except SchemaReloadException as e:
self.update_schema(e.schema_version)
Expand Down Expand Up @@ -364,7 +364,7 @@ def check(): # Check that connection is alive
attempt += 1
self.handshake()

def _send_request(self, request):
def _send_request(self, request, unpacker=None):
'''
Send the request to the server through the socket.
Return an instance of `Response` class.
Expand All @@ -378,7 +378,7 @@ def _send_request(self, request):

self._opt_reconnect()

return self._send_request_wo_reconnect(request)
return self._send_request_wo_reconnect(request, unpacker=unpacker)

def load_schema(self):
self.schema.fetch_space_all()
Expand All @@ -392,7 +392,7 @@ def flush_schema(self):
self.schema.flush()
self.load_schema()

def call(self, func_name, *args):
def call(self, func_name, *args, msgpack_packer=None, msgpack_unpacker=None):
'''
Execute CALL request. Call stored Lua function.

Expand All @@ -409,8 +409,9 @@ def call(self, func_name, *args):
if len(args) == 1 and isinstance(args[0], (list, tuple)):
args = args[0]

request = RequestCall(self, func_name, args, self.call_16)
response = self._send_request(request)
request = RequestCall(self, func_name, args, self.call_16,
packer=msgpack_packer)
response = self._send_request(request, unpacker=msgpack_unpacker)
return response

def eval(self, expr, *args):
Expand Down
58 changes: 30 additions & 28 deletions tarantool/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,37 +70,39 @@ class Request(object):
'''
request_type = None

def __init__(self, conn):
def __init__(self, conn, packer=None):
self._bytes = None
self.conn = conn
self._sync = None
self._body = ''
self.response_class = Response

packer_kwargs = dict()

# use_bin_type=True is default since msgpack-1.0.0.
#
# The option controls whether to pack binary (non-unicode)
# string values as mp_bin or as mp_str.
#
# The default behaviour of the connector is to pack both
# bytes and Unicode strings as mp_str.
#
# msgpack-0.5.0 (and only this version) warns when the
# option is unset:
#
# | FutureWarning: use_bin_type option is not specified.
# | Default value of the option will be changed in future
# | version.
#
# The option is supported since msgpack-0.4.0, so we can
# just always set it for all msgpack versions to get rid
# of the warning on msgpack-0.5.0 and to keep our
# behaviour on msgpack-1.0.0.
packer_kwargs['use_bin_type'] = False

self.packer = msgpack.Packer(**packer_kwargs)
self.packer = packer

if self.packer is None:
packer_kwargs = dict()

# use_bin_type=True is default since msgpack-1.0.0.
#
# The option controls whether to pack binary (non-unicode)
# string values as mp_bin or as mp_str.
#
# The default behaviour of the connector is to pack both
# bytes and Unicode strings as mp_str.
#
# msgpack-0.5.0 (and only this version) warns when the
# option is unset:
#
# | FutureWarning: use_bin_type option is not specified.
# | Default value of the option will be changed in future
# | version.
#
# The option is supported since msgpack-0.4.0, so we can
# just always set it for all msgpack versions to get rid
# of the warning on msgpack-0.5.0 and to keep our
# behaviour on msgpack-1.0.0.
packer_kwargs['use_bin_type'] = False

self.packer = msgpack.Packer(**packer_kwargs)

def _dumps(self, src):
return self.packer.pack(src)
Expand Down Expand Up @@ -269,10 +271,10 @@ class RequestCall(Request):
request_type = REQUEST_TYPE_CALL

# pylint: disable=W0231
def __init__(self, conn, name, args, call_16):
def __init__(self, conn, name, args, call_16, packer=None):
if call_16:
self.request_type = REQUEST_TYPE_CALL16
super(RequestCall, self).__init__(conn)
super(RequestCall, self).__init__(conn, packer=packer)
assert isinstance(args, (list, tuple))

request_body = self._dumps({IPROTO_FUNCTION_NAME: name,
Expand Down
69 changes: 35 additions & 34 deletions tarantool/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class Response(Sequence):
and parses binary packet received from the server.
'''

def __init__(self, conn, response):
def __init__(self, conn, response, unpacker=None):
'''
Create an instance of `Response` using data received from the server.

Expand All @@ -53,39 +53,40 @@ def __init__(self, conn, response):
# created in the __new__().
# super(Response, self).__init__()

unpacker_kwargs = dict()

# Decode msgpack arrays into Python lists by default (not tuples).
# Can be configured in the Connection init
unpacker_kwargs['use_list'] = conn.use_list

# Use raw=False instead of encoding='utf-8'.
if msgpack.version >= (0, 5, 2) and conn.encoding == 'utf-8':
# Get rid of the following warning.
# > PendingDeprecationWarning: encoding is deprecated,
# > Use raw=False instead.
unpacker_kwargs['raw'] = False
elif conn.encoding is not None:
unpacker_kwargs['encoding'] = conn.encoding

# raw=False is default since msgpack-1.0.0.
#
# The option decodes mp_str to bytes, not a Unicode
# string (when True).
if msgpack.version >= (1, 0, 0) and conn.encoding is None:
unpacker_kwargs['raw'] = True

# encoding option is not supported since msgpack-1.0.0,
# but it is handled in the Connection constructor.
assert(msgpack.version < (1, 0, 0) or conn.encoding in (None, 'utf-8'))

# strict_map_key=True is default since msgpack-1.0.0.
#
# The option forbids non-string keys in a map (when True).
if msgpack.version >= (1, 0, 0):
unpacker_kwargs['strict_map_key'] = False

unpacker = msgpack.Unpacker(**unpacker_kwargs)
if unpacker is None:
unpacker_kwargs = dict()

# Decode msgpack arrays into Python lists by default (not tuples).
# Can be configured in the Connection init
unpacker_kwargs['use_list'] = conn.use_list

# Use raw=False instead of encoding='utf-8'.
if msgpack.version >= (0, 5, 2) and conn.encoding == 'utf-8':
# Get rid of the following warning.
# > PendingDeprecationWarning: encoding is deprecated,
# > Use raw=False instead.
unpacker_kwargs['raw'] = False
elif conn.encoding is not None:
unpacker_kwargs['encoding'] = conn.encoding

# raw=False is default since msgpack-1.0.0.
#
# The option decodes mp_str to bytes, not a Unicode
# string (when True).
if msgpack.version >= (1, 0, 0) and conn.encoding is None:
unpacker_kwargs['raw'] = True

# encoding option is not supported since msgpack-1.0.0,
# but it is handled in the Connection constructor.
assert(msgpack.version < (1, 0, 0) or conn.encoding in (None, 'utf-8'))

# strict_map_key=True is default since msgpack-1.0.0.
#
# The option forbids non-string keys in a map (when True).
if msgpack.version >= (1, 0, 0):
unpacker_kwargs['strict_map_key'] = False

unpacker = msgpack.Unpacker(**unpacker_kwargs)

unpacker.feed(response)
header = unpacker.unpack()
Expand Down