diff --git a/tarantool/__init__.py b/tarantool/__init__.py index 2ac72e55..06126371 100644 --- a/tarantool/__init__.py +++ b/tarantool/__init__.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # pylint: disable=C0301,W0105,W0401,W0614 -__version__ = "0.5.4" - from tarantool.connection import Connection from tarantool.const import ( SOCKET_TIMEOUT, @@ -24,8 +22,12 @@ ) -def connect(host="localhost", port=33013, user=None, password=None, encoding=ENCODING_DEFAULT): - '''\ +__version__ = "0.5.4" + + +def connect(host="localhost", port=33013, user=None, password=None, + encoding=ENCODING_DEFAULT): + ''' Create a connection to the Tarantool server. :param str host: Server hostname or IP-address diff --git a/tarantool/connection.py b/tarantool/connection.py index f9626660..442f9cb0 100644 --- a/tarantool/connection.py +++ b/tarantool/connection.py @@ -22,7 +22,7 @@ from tarantool.response import Response from tarantool.request import ( Request, - RequestOK, + # RequestOK, RequestCall, RequestDelete, RequestEval, @@ -34,8 +34,8 @@ RequestSubscribe, RequestUpdate, RequestUpsert, - RequestAuthenticate) - + RequestAuthenticate +) from tarantool.space import Space from tarantool.const import ( SOCKET_TIMEOUT, @@ -46,16 +46,17 @@ IPROTO_GREETING_SIZE, ENCODING_DEFAULT, ITERATOR_EQ, - ITERATOR_ALL) - + ITERATOR_ALL +) from tarantool.error import ( NetworkError, - DatabaseError, + # DatabaseError, NetworkWarning, - SchemaReloadException) - -from .schema import Schema -from .utils import check_key, greeting_decode, version_id + SchemaReloadException, + warn +) +from tarantool.schema import Schema +from tarantool.utils import check_key, greeting_decode, version_id class Connection(object): @@ -91,7 +92,9 @@ def __init__(self, host, port, if False than you have to call connect() manualy. ''' if os.name == 'nt': - libc = ctypes.windll.LoadLibrary(ctypes.util.find_library('Ws2_32')) + libc = ctypes.windll.LoadLibrary( + ctypes.util.find_library('Ws2_32') + ) else: libc = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True) recv = self._sys_recv = libc.recv @@ -177,15 +180,24 @@ def _recv(self, to_read): tmp = self._socket.recv(to_read) except OverflowError: self._socket.close() - raise NetworkError(socker.error(errno.ECONNRESET, - "Too big packet. Closing connection to server")) + err = socket.error( + errno.ECONNRESET, + "Too big packet. Closing connection to server" + ) + raise NetworkError(err) except socket.error: - raise NetworkError(socket.error(errno.ECONNRESET, - "Lost connection to server during query")) + err = socket.error( + errno.ECONNRESET, + "Lost connection to server during query" + ) + raise NetworkError(err) else: if len(tmp) == 0: - raise NetworkError(socket.error(errno.ECONNRESET, - "Lost connection to server during query")) + err = socket.error( + errno.ECONNRESET, + "Lost connection to server during query" + ) + raise NetworkError(err) to_read -= len(tmp) buf += tmp return buf @@ -261,7 +273,7 @@ def check(): # Check that connection is alive time.sleep(self.reconnect_delay) try: self.connect_basic() - except NetworkError as e: + except NetworkError: pass else: if self.connected: @@ -394,7 +406,7 @@ def _join_v16(self, server_uuid): self._socket.sendall(bytes(request)) while True: - resp = Response(self, self._read_response()); + resp = Response(self, self._read_response()) yield resp if resp.code == REQUEST_TYPE_OK or resp.code >= REQUEST_TYPE_ERROR: return @@ -543,7 +555,8 @@ def upsert(self, space_name, tuple_value, op_list, **kwargs): space_name = self.schema.get_space(space_name).sid if isinstance(index_name, six.string_types): index_name = self.schema.get_index(space_name, index_name).iid - request = RequestUpsert(self, space_name, index_name, tuple_value, op_list) + request = RequestUpsert(self, space_name, index_name, tuple_value, + op_list) return self._send_request(request) def update(self, space_name, key, op_list, **kwargs): @@ -684,9 +697,10 @@ def select(self, space_name, key=None, **kwargs): index_name = kwargs.get("index", 0) iterator_type = kwargs.get("iterator") - if iterator_type == None: + if iterator_type is None: iterator_type = ITERATOR_EQ - if (key == None or (isinstance(key, (list, tuple)) and len(key) == 0)): + if key is None or (isinstance(key, (list, tuple)) and + len(key) == 0): iterator_type = ITERATOR_ALL # Perform smart type checking (scalar / list of scalars / list of @@ -717,7 +731,7 @@ def space(self, space_name): return Space(self, space_name) def generate_sync(self): - """\ + ''' Need override for async io connection - """ + ''' return 0 diff --git a/tarantool/const.py b/tarantool/const.py index 4fb4adfb..0d21a28a 100644 --- a/tarantool/const.py +++ b/tarantool/const.py @@ -34,7 +34,7 @@ IPROTO_ERROR = 0x31 IPROTO_GREETING_SIZE = 128 -IPROTO_BODY_MAX_LEN = 2147483648 +IPROTO_BODY_MAX_LEN = 2147483648 REQUEST_TYPE_OK = 0 REQUEST_TYPE_SELECT = 1 diff --git a/tarantool/error.py b/tarantool/error.py index b9d559a0..f49ba60c 100644 --- a/tarantool/error.py +++ b/tarantool/error.py @@ -24,6 +24,7 @@ import sys import warnings + try: class Error(StandardError): '''Base class for error exceptions''' @@ -33,12 +34,10 @@ class Error(Exception): class DatabaseError(Error): - '''Error related to the database engine''' class InterfaceError(Error): - ''' Error related to the database interface rather than the database itself ''' @@ -108,6 +107,7 @@ def os_strerror_patched(code): os.strerror = os_strerror_patched del os_strerror_patched + class SchemaError(DatabaseError): def __init__(self, value): super(SchemaError, self).__init__(0, value) @@ -116,11 +116,12 @@ def __init__(self, value): def __str__(self): return str(self.value) + class SchemaReloadException(DatabaseError): def __init__(self, message, schema_version): super(SchemaReloadException, self).__init__(109, message) - self.code = 109 - self.message = message + self.code = 109 + self.message = message self.schema_version = schema_version def __str__(self): @@ -128,7 +129,6 @@ def __str__(self): class NetworkError(DatabaseError): - '''Error related to network''' def __init__(self, orig_exception=None, *args): @@ -148,7 +148,6 @@ def __init__(self, orig_exception=None, *args): class NetworkWarning(UserWarning): - '''Warning related to network''' pass @@ -168,119 +167,177 @@ def warn(message, warning_class): warnings.warn_explicit(message, warning_class, module_name, line_no) _strerror = { - 0: ("ER_UNKNOWN", "Unknown error"), - 1: ("ER_ILLEGAL_PARAMS", "Illegal parameters, %s"), - 2: ("ER_MEMORY_ISSUE", "Failed to allocate %u bytes in %s for %s"), - 3: ("ER_TUPLE_FOUND", "Duplicate key exists in unique index '%s' in space '%s'"), - 4: ("ER_TUPLE_NOT_FOUND", "Tuple doesn't exist in index '%s' in space '%s'"), - 5: ("ER_UNSUPPORTED", "%s does not support %s"), - 6: ("ER_NONMASTER", "Can't modify data on a replication slave. My master is: %s"), - 7: ("ER_READONLY", "Can't modify data because this server is in read-only mode."), - 8: ("ER_INJECTION", "Error injection '%s'"), - 9: ("ER_CREATE_SPACE", "Failed to create space '%s': %s"), - 10: ("ER_SPACE_EXISTS", "Space '%s' already exists"), - 11: ("ER_DROP_SPACE", "Can't drop space '%s': %s"), - 12: ("ER_ALTER_SPACE", "Can't modify space '%s': %s"), - 13: ("ER_INDEX_TYPE", "Unsupported index type supplied for index '%s' in space '%s'"), - 14: ("ER_MODIFY_INDEX", "Can't create or modify index '%s' in space '%s': %s"), - 15: ("ER_LAST_DROP", "Can't drop the primary key in a system space, space '%s'"), - 16: ("ER_TUPLE_FORMAT_LIMIT", "Tuple format limit reached: %u"), - 17: ("ER_DROP_PRIMARY_KEY", "Can't drop primary key in space '%s' while secondary keys exist"), - 18: ("ER_KEY_PART_TYPE", "Supplied key type of part %u does not match index part type: expected %s"), - 19: ("ER_EXACT_MATCH", "Invalid key part count in an exact match (expected %u, got %u)"), - 20: ("ER_INVALID_MSGPACK", "Invalid MsgPack - %s"), - 21: ("ER_PROC_RET", "msgpack.encode: can not encode Lua type '%s'"), - 22: ("ER_TUPLE_NOT_ARRAY", "Tuple/Key must be MsgPack array"), - 23: ("ER_FIELD_TYPE", "Tuple field %u type does not match one required by operation: expected %s"), - 24: ("ER_FIELD_TYPE_MISMATCH", "Ambiguous field type in index '%s', key part %u. Requested type is %s but the field has previously been defined as %s"), - 25: ("ER_SPLICE", "SPLICE error on field %u: %s"), - 26: ("ER_ARG_TYPE", "Argument type in operation '%c' on field %u does not match field type: expected a %s"), - 27: ("ER_TUPLE_IS_TOO_LONG", "Tuple is too long %u"), - 28: ("ER_UNKNOWN_UPDATE_OP", "Unknown UPDATE operation"), - 29: ("ER_UPDATE_FIELD", "Field %u UPDATE error: %s"), - 30: ("ER_FIBER_STACK", "Can not create a new fiber: recursion limit reached"), - 31: ("ER_KEY_PART_COUNT", "Invalid key part count (expected [0..%u], got %u)"), - 32: ("ER_PROC_LUA", "%s"), - 33: ("ER_NO_SUCH_PROC", "Procedure '%.*s' is not defined"), - 34: ("ER_NO_SUCH_TRIGGER", "Trigger is not found"), - 35: ("ER_NO_SUCH_INDEX", "No index #%u is defined in space '%s'"), - 36: ("ER_NO_SUCH_SPACE", "Space '%s' does not exist"), - 37: ("ER_NO_SUCH_FIELD", "Field %d was not found in the tuple"), - 38: ("ER_SPACE_FIELD_COUNT", "Tuple field count %u does not match space '%s' field count %u"), - 39: ("ER_INDEX_FIELD_COUNT", "Tuple field count %u is less than required by a defined index (expected %u)"), - 40: ("ER_WAL_IO", "Failed to write to disk"), - 41: ("ER_MORE_THAN_ONE_TUPLE", "More than one tuple found by get()"), - 42: ("ER_ACCESS_DENIED", "%s access on %s is denied for user '%s'"), - 43: ("ER_CREATE_USER", "Failed to create user '%s': %s"), - 44: ("ER_DROP_USER", "Failed to drop user or role '%s': %s"), - 45: ("ER_NO_SUCH_USER", "User '%s' is not found"), - 46: ("ER_USER_EXISTS", "User '%s' already exists"), - 47: ("ER_PASSWORD_MISMATCH", "Incorrect password supplied for user '%s'"), - 48: ("ER_UNKNOWN_REQUEST_TYPE", "Unknown request type %u"), - 49: ("ER_UNKNOWN_SCHEMA_OBJECT", "Unknown object type '%s'"), - 50: ("ER_CREATE_FUNCTION", "Failed to create function '%s': %s"), - 51: ("ER_NO_SUCH_FUNCTION", "Function '%s' does not exist"), - 52: ("ER_FUNCTION_EXISTS", "Function '%s' already exists"), - 53: ("ER_FUNCTION_ACCESS_DENIED", "%s access is denied for user '%s' to function '%s'"), - 54: ("ER_FUNCTION_MAX", "A limit on the total number of functions has been reached: %u"), - 55: ("ER_SPACE_ACCESS_DENIED", "%s access is denied for user '%s' to space '%s'"), - 56: ("ER_USER_MAX", "A limit on the total number of users has been reached: %u"), - 57: ("ER_NO_SUCH_ENGINE", "Space engine '%s' does not exist"), - 58: ("ER_RELOAD_CFG", "Can't set option '%s' dynamically"), - 59: ("ER_CFG", "Incorrect value for option '%s': %s"), - 60: ("ER_SOPHIA", "%s"), - 61: ("ER_LOCAL_SERVER_IS_NOT_ACTIVE", "Local server is not active"), - 62: ("ER_UNKNOWN_SERVER", "Server %s is not registered with the cluster"), - 63: ("ER_CLUSTER_ID_MISMATCH", "Cluster id of the replica %s doesn't match cluster id of the master %s"), - 64: ("ER_INVALID_UUID", "Invalid UUID: %s"), - 65: ("ER_CLUSTER_ID_IS_RO", "Can't reset cluster id: it is already assigned"), - 66: ("ER_RESERVED66", "Reserved66"), - 67: ("ER_SERVER_ID_IS_RESERVED", "Can't initialize server id with a reserved value %u"), - 68: ("ER_INVALID_ORDER", "Invalid LSN order for server %u: previous LSN = %llu, new lsn = %llu"), - 69: ("ER_MISSING_REQUEST_FIELD", "Missing mandatory field '%s' in request"), - 70: ("ER_IDENTIFIER", "Invalid identifier '%s' (expected letters, digits or an underscore)"), - 71: ("ER_DROP_FUNCTION", "Can't drop function %u: %s"), - 72: ("ER_ITERATOR_TYPE", "Unknown iterator type '%s'"), - 73: ("ER_REPLICA_MAX", "Replica count limit reached: %u"), - 74: ("ER_INVALID_XLOG", "Failed to read xlog: %lld"), - 75: ("ER_INVALID_XLOG_NAME", "Invalid xlog name: expected %lld got %lld"), - 76: ("ER_INVALID_XLOG_ORDER", "Invalid xlog order: %lld and %lld"), - 77: ("ER_NO_CONNECTION", "Connection is not established"), - 78: ("ER_TIMEOUT", "Timeout exceeded"), - 79: ("ER_ACTIVE_TRANSACTION", "Operation is not permitted when there is an active transaction "), - 80: ("ER_NO_ACTIVE_TRANSACTION", "Operation is not permitted when there is no active transaction "), - 81: ("ER_CROSS_ENGINE_TRANSACTION", "A multi-statement transaction can not use multiple storage engines"), - 82: ("ER_NO_SUCH_ROLE", "Role '%s' is not found"), - 83: ("ER_ROLE_EXISTS", "Role '%s' already exists"), - 84: ("ER_CREATE_ROLE", "Failed to create role '%s': %s"), - 85: ("ER_INDEX_EXISTS", "Index '%s' already exists"), - 86: ("ER_TUPLE_REF_OVERFLOW", "Tuple reference counter overflow"), - 87: ("ER_ROLE_LOOP", "Granting role '%s' to role '%s' would create a loop"), - 88: ("ER_GRANT", "Incorrect grant arguments: %s"), - 89: ("ER_PRIV_GRANTED", "User '%s' already has %s access on %s '%s'"), - 90: ("ER_ROLE_GRANTED", "User '%s' already has role '%s'"), - 91: ("ER_PRIV_NOT_GRANTED", "User '%s' does not have %s access on %s '%s'"), - 92: ("ER_ROLE_NOT_GRANTED", "User '%s' does not have role '%s'"), - 93: ("ER_MISSING_SNAPSHOT", "Can't find snapshot"), - 94: ("ER_CANT_UPDATE_PRIMARY_KEY", "Attempt to modify a tuple field which is part of index '%s' in space '%s'"), - 95: ("ER_UPDATE_INTEGER_OVERFLOW", "Integer overflow when performing '%c' operation on field %u"), - 96: ("ER_GUEST_USER_PASSWORD", "Setting password for guest user has no effect"), - 97: ("ER_TRANSACTION_CONFLICT", "Transaction has been aborted by conflict"), - 98: ("ER_UNSUPPORTED_ROLE_PRIV", "Unsupported role privilege '%s'"), - 99: ("ER_LOAD_FUNCTION", "Failed to dynamically load function '%s': %s"), - 100: ("ER_FUNCTION_LANGUAGE", "Unsupported language '%s' specified for function '%s'"), - 101: ("ER_RTREE_RECT", "RTree: %s must be an array with %u (point) or %u (rectangle/box) numeric coordinates"), + 0: ("ER_UNKNOWN", "Unknown error"), + 1: ("ER_ILLEGAL_PARAMS", "Illegal parameters, %s"), + 2: ("ER_MEMORY_ISSUE", "Failed to allocate %u bytes in %s for %s"), + 3: ("ER_TUPLE_FOUND", + "Duplicate key exists in unique index '%s' in space '%s'"), + 4: ("ER_TUPLE_NOT_FOUND", + "Tuple doesn't exist in index '%s' in space '%s'"), + 5: ("ER_UNSUPPORTED", "%s does not support %s"), + 6: ("ER_NONMASTER", + "Can't modify data on a replication slave. My master is: %s"), + 7: ("ER_READONLY", + "Can't modify data because this server is in read-only mode."), + 8: ("ER_INJECTION", "Error injection '%s'"), + 9: ("ER_CREATE_SPACE", "Failed to create space '%s': %s"), + 10: ("ER_SPACE_EXISTS", "Space '%s' already exists"), + 11: ("ER_DROP_SPACE", "Can't drop space '%s': %s"), + 12: ("ER_ALTER_SPACE", "Can't modify space '%s': %s"), + 13: ("ER_INDEX_TYPE", + "Unsupported index type supplied for index '%s' in space '%s'"), + 14: ("ER_MODIFY_INDEX", + "Can't create or modify index '%s' in space '%s': %s"), + 15: ("ER_LAST_DROP", + "Can't drop the primary key in a system space, space '%s'"), + 16: ("ER_TUPLE_FORMAT_LIMIT", "Tuple format limit reached: %u"), + 17: ("ER_DROP_PRIMARY_KEY", + "Can't drop primary key in space '%s' while secondary keys exist"), + 18: ("ER_KEY_PART_TYPE", ( + "Supplied key type of part %u does not match index part type:" + " expected %s")), + 19: ("ER_EXACT_MATCH", + "Invalid key part count in an exact match (expected %u, got %u)"), + 20: ("ER_INVALID_MSGPACK", "Invalid MsgPack - %s"), + 21: ("ER_PROC_RET", "msgpack.encode: can not encode Lua type '%s'"), + 22: ("ER_TUPLE_NOT_ARRAY", "Tuple/Key must be MsgPack array"), + 23: ("ER_FIELD_TYPE", ( + "Tuple field %u type does not match one required by operation:" + " expected %s")), + 24: ("ER_FIELD_TYPE_MISMATCH", ( + "Ambiguous field type in index '%s', key part %u. Requested type" + " is %s but the field has previously been defined as %s")), + 25: ("ER_SPLICE", "SPLICE error on field %u: %s"), + 26: ("ER_ARG_TYPE", ( + "Argument type in operation '%c' on field %u does not match" + " field type: expected a %s")), + 27: ("ER_TUPLE_IS_TOO_LONG", "Tuple is too long %u"), + 28: ("ER_UNKNOWN_UPDATE_OP", "Unknown UPDATE operation"), + 29: ("ER_UPDATE_FIELD", "Field %u UPDATE error: %s"), + 30: ("ER_FIBER_STACK", + "Can not create a new fiber: recursion limit reached"), + 31: ("ER_KEY_PART_COUNT", + "Invalid key part count (expected [0..%u], got %u)"), + 32: ("ER_PROC_LUA", "%s"), + 33: ("ER_NO_SUCH_PROC", "Procedure '%.*s' is not defined"), + 34: ("ER_NO_SUCH_TRIGGER", "Trigger is not found"), + 35: ("ER_NO_SUCH_INDEX", "No index #%u is defined in space '%s'"), + 36: ("ER_NO_SUCH_SPACE", "Space '%s' does not exist"), + 37: ("ER_NO_SUCH_FIELD", "Field %d was not found in the tuple"), + 38: ("ER_SPACE_FIELD_COUNT", + "Tuple field count %u does not match space '%s' field count %u"), + 39: ("ER_INDEX_FIELD_COUNT", ( + "Tuple field count %u is less than required by a defined index" + " (expected %u)")), + 40: ("ER_WAL_IO", "Failed to write to disk"), + 41: ("ER_MORE_THAN_ONE_TUPLE", "More than one tuple found by get()"), + 42: ("ER_ACCESS_DENIED", "%s access on %s is denied for user '%s'"), + 43: ("ER_CREATE_USER", "Failed to create user '%s': %s"), + 44: ("ER_DROP_USER", "Failed to drop user or role '%s': %s"), + 45: ("ER_NO_SUCH_USER", "User '%s' is not found"), + 46: ("ER_USER_EXISTS", "User '%s' already exists"), + 47: ("ER_PASSWORD_MISMATCH", "Incorrect password supplied for user '%s'"), + 48: ("ER_UNKNOWN_REQUEST_TYPE", "Unknown request type %u"), + 49: ("ER_UNKNOWN_SCHEMA_OBJECT", "Unknown object type '%s'"), + 50: ("ER_CREATE_FUNCTION", "Failed to create function '%s': %s"), + 51: ("ER_NO_SUCH_FUNCTION", "Function '%s' does not exist"), + 52: ("ER_FUNCTION_EXISTS", "Function '%s' already exists"), + 53: ("ER_FUNCTION_ACCESS_DENIED", + "%s access is denied for user '%s' to function '%s'"), + 54: ("ER_FUNCTION_MAX", + "A limit on the total number of functions has been reached: %u"), + 55: ("ER_SPACE_ACCESS_DENIED", + "%s access is denied for user '%s' to space '%s'"), + 56: ("ER_USER_MAX", + "A limit on the total number of users has been reached: %u"), + 57: ("ER_NO_SUCH_ENGINE", "Space engine '%s' does not exist"), + 58: ("ER_RELOAD_CFG", "Can't set option '%s' dynamically"), + 59: ("ER_CFG", "Incorrect value for option '%s': %s"), + 60: ("ER_SOPHIA", "%s"), + 61: ("ER_LOCAL_SERVER_IS_NOT_ACTIVE", "Local server is not active"), + 62: ("ER_UNKNOWN_SERVER", "Server %s is not registered with the cluster"), + 63: ("ER_CLUSTER_ID_MISMATCH", ( + "Cluster id of the replica %s doesn't match cluster id" + " of the master %s")), + 64: ("ER_INVALID_UUID", "Invalid UUID: %s"), + 65: ("ER_CLUSTER_ID_IS_RO", + "Can't reset cluster id: it is already assigned"), + 66: ("ER_RESERVED66", "Reserved66"), + 67: ("ER_SERVER_ID_IS_RESERVED", + "Can't initialize server id with a reserved value %u"), + 68: ("ER_INVALID_ORDER", ( + "Invalid LSN order for server %u: previous LSN = %llu," + " new lsn = %llu")), + 69: ("ER_MISSING_REQUEST_FIELD", + "Missing mandatory field '%s' in request"), + 70: ("ER_IDENTIFIER", ( + "Invalid identifier '%s' (expected letters, digits" + " or an underscore)")), + 71: ("ER_DROP_FUNCTION", "Can't drop function %u: %s"), + 72: ("ER_ITERATOR_TYPE", "Unknown iterator type '%s'"), + 73: ("ER_REPLICA_MAX", "Replica count limit reached: %u"), + 74: ("ER_INVALID_XLOG", "Failed to read xlog: %lld"), + 75: ("ER_INVALID_XLOG_NAME", "Invalid xlog name: expected %lld got %lld"), + 76: ("ER_INVALID_XLOG_ORDER", "Invalid xlog order: %lld and %lld"), + 77: ("ER_NO_CONNECTION", "Connection is not established"), + 78: ("ER_TIMEOUT", "Timeout exceeded"), + 79: ("ER_ACTIVE_TRANSACTION", + "Operation is not permitted when there is an active transaction "), + 80: ("ER_NO_ACTIVE_TRANSACTION", + "Operation is not permitted when there is no active transaction "), + 81: ("ER_CROSS_ENGINE_TRANSACTION", + "A multi-statement transaction can not use multiple storage engines"), + 82: ("ER_NO_SUCH_ROLE", "Role '%s' is not found"), + 83: ("ER_ROLE_EXISTS", "Role '%s' already exists"), + 84: ("ER_CREATE_ROLE", "Failed to create role '%s': %s"), + 85: ("ER_INDEX_EXISTS", "Index '%s' already exists"), + 86: ("ER_TUPLE_REF_OVERFLOW", "Tuple reference counter overflow"), + 87: ("ER_ROLE_LOOP", + "Granting role '%s' to role '%s' would create a loop"), + 88: ("ER_GRANT", "Incorrect grant arguments: %s"), + 89: ("ER_PRIV_GRANTED", "User '%s' already has %s access on %s '%s'"), + 90: ("ER_ROLE_GRANTED", "User '%s' already has role '%s'"), + 91: ("ER_PRIV_NOT_GRANTED", + "User '%s' does not have %s access on %s '%s'"), + 92: ("ER_ROLE_NOT_GRANTED", "User '%s' does not have role '%s'"), + 93: ("ER_MISSING_SNAPSHOT", "Can't find snapshot"), + 94: ("ER_CANT_UPDATE_PRIMARY_KEY", ( + "Attempt to modify a tuple field which is part of index '%s'" + " in space '%s'")), + 95: ("ER_UPDATE_INTEGER_OVERFLOW", + "Integer overflow when performing '%c' operation on field %u"), + 96: ("ER_GUEST_USER_PASSWORD", + "Setting password for guest user has no effect"), + 97: ("ER_TRANSACTION_CONFLICT", + "Transaction has been aborted by conflict"), + 98: ("ER_UNSUPPORTED_ROLE_PRIV", "Unsupported role privilege '%s'"), + 99: ("ER_LOAD_FUNCTION", "Failed to dynamically load function '%s': %s"), + 100: ("ER_FUNCTION_LANGUAGE", + "Unsupported language '%s' specified for function '%s'"), + 101: ("ER_RTREE_RECT", ( + "RTree: %s must be an array with %u (point)" + " or %u (rectangle/box) numeric coordinates")), 102: ("ER_PROC_C", "%s"), - 103: ("ER_UNKNOWN_RTREE_INDEX_DISTANCE_TYPE", "Unknown RTREE index distance type %s"), + 103: ("ER_UNKNOWN_RTREE_INDEX_DISTANCE_TYPE", + "Unknown RTREE index distance type %s"), 104: ("ER_PROTOCOL", "%s"), - 105: ("ER_UPSERT_UNIQUE_SECONDARY_KEY", "Space %s has a unique secondary index and does not support UPSERT"), - 106: ("ER_WRONG_INDEX_RECORD", "Wrong record in _index space: got {%s}, expected {%s}"), - 107: ("ER_WRONG_INDEX_PARTS", "Wrong index parts (field %u): %s; expected field1 id (number), field1 type (string), ..."), + 105: ("ER_UPSERT_UNIQUE_SECONDARY_KEY", + "Space %s has a unique secondary index and does not support UPSERT"), + 106: ("ER_WRONG_INDEX_RECORD", + "Wrong record in _index space: got {%s}, expected {%s}"), + 107: ("ER_WRONG_INDEX_PARTS", ( + "Wrong index parts (field %u): %s; expected field1 id (number)," + " field1 type (string), ...")), 108: ("ER_WRONG_INDEX_OPTIONS", "Wrong index options (field %u): %s"), - 109: ("ER_WRONG_SCHEMA_VERSION", "Wrong schema version, current: %d, in request: %u"), - 110: ("ER_SLAB_ALLOC_MAX", "Failed to allocate %u bytes for tuple in the slab allocator: tuple is too large. Check 'slab_alloc_maximal' configuration option."), + 109: ("ER_WRONG_SCHEMA_VERSION", + "Wrong schema version, current: %d, in request: %u"), + 110: ("ER_SLAB_ALLOC_MAX", ( + "Failed to allocate %u bytes for tuple in the slab allocator:" + " tuple is too large. Check 'slab_alloc_maximal'" + " configuration option.")), 111: ("ER_WRONG_SPACE_OPTIONS", "Wrong space options (field %u): %s"), - 112: ("ER_UNSUPPORTED_INDEX_FEATURE", "Index '%s' (%s) of space '%s' (%s) does not support %s"), + 112: ("ER_UNSUPPORTED_INDEX_FEATURE", + "Index '%s' (%s) of space '%s' (%s) does not support %s"), 113: ("ER_VIEW_IS_RO", "View '%s' is read-only"), } diff --git a/tarantool/request.py b/tarantool/request.py index 42af6da6..f6e3c86e 100644 --- a/tarantool/request.py +++ b/tarantool/request.py @@ -25,7 +25,7 @@ IPROTO_VCLOCK, IPROTO_EXPR, IPROTO_OPS, - IPROTO_INDEX_BASE, + # IPROTO_INDEX_BASE, IPROTO_SCHEMA_ID, REQUEST_TYPE_OK, REQUEST_TYPE_PING, @@ -67,7 +67,7 @@ def __bytes__(self): @property def sync(self): - '''\ + ''' :type: int Required field in the server request. @@ -77,12 +77,13 @@ def sync(self): def header(self, length): self._sync = self.conn.generate_sync() - header = msgpack.dumps({IPROTO_CODE: self.request_type, - IPROTO_SYNC: self._sync, + header = msgpack.dumps({IPROTO_CODE: self.request_type, + IPROTO_SYNC: self._sync, IPROTO_SCHEMA_ID: self.conn.schema_version}) return msgpack.dumps(length + len(header)) + header + class RequestInsert(Request): ''' Represents INSERT request @@ -115,7 +116,10 @@ def sha1(values): sha = hashlib.sha1() for i in values: if i is not None: - sha.update(i if isinstance(i, six.binary_type) else i.encode()) + if isinstance(i, six.binary_type): + sha.update(i) + else: + sha.update(i.encode()) return sha.digest() def strxor(rhs, lhs): @@ -253,6 +257,7 @@ def __init__(self, conn): super(RequestPing, self).__init__(conn) self._body = b'' + class RequestUpsert(Request): ''' Represents UPSERT request @@ -271,6 +276,7 @@ def __init__(self, conn, space_no, index_no, tuple_value, op_list): self._body = request_body + class RequestJoin(Request): ''' Represents JOIN request @@ -302,6 +308,7 @@ def __init__(self, conn, cluster_uuid, server_uuid, vclock): }) self._body = request_body + class RequestOK(Request): ''' Represents OK acknowledgement @@ -311,6 +318,6 @@ class RequestOK(Request): # pylint: disable=W0231 def __init__(self, conn, sync): super(RequestOK, self).__init__(conn) - header = msgpack.dumps({IPROTO_CODE: self.request_type, - IPROTO_SYNC: sync}) + request_body = msgpack.dumps({IPROTO_CODE: self.request_type, + IPROTO_SYNC: sync}) self._body = request_body diff --git a/tarantool/response.py b/tarantool/response.py index 098be5c3..4f9afd2f 100644 --- a/tarantool/response.py +++ b/tarantool/response.py @@ -14,7 +14,13 @@ IPROTO_SCHEMA_ID, REQUEST_TYPE_ERROR ) -from tarantool.error import DatabaseError, tnt_strerror, SchemaReloadException +from tarantool.error import ( + DatabaseError, + InterfaceError, + SchemaReloadException, + tnt_strerror +) + if sys.version_info < (2, 6): bytes = str # pylint: disable=W0622 @@ -51,7 +57,7 @@ def __init__(self, conn, response): unpacker.feed(response) header = unpacker.unpack() - self.conn = conn + self.conn = conn self._sync = header.get(IPROTO_SYNC, 0) self._code = header[IPROTO_CODE] self._body = {} @@ -65,7 +71,8 @@ def __init__(self, conn, response): self._return_code = 0 self._schema_version = header.get(IPROTO_SCHEMA_ID, None) self._data = self._body.get(IPROTO_DATA, None) - if not isinstance(self._data, (list, tuple)) and self._data is not None: + if (not isinstance(self._data, (list, tuple)) and + self._data is not None): self._data = [self._data] # # Backward-compatibility # if isinstance(self._data, (list, tuple)): @@ -84,37 +91,37 @@ def __init__(self, conn, response): raise DatabaseError(self._return_code, self._return_message) def __getitem__(self, idx): - if self._data == None: + if self._data is None: raise InterfaceError("Trying to access data, when there's no data") return self._data.__getitem__(idx) def __len__(self): - if self._data == None: + if self._data is None: raise InterfaceError("Trying to access data, when there's no data") return len(self._data) def __contains__(self, item): - if self._data == None: + if self._data is None: raise InterfaceError("Trying to access data, when there's no data") return item in self._data def __iter__(self): - if self._data == None: + if self._data is None: raise InterfaceError("Trying to access data, when there's no data") return iter(self._data) def __reversed__(self): - if self._data == None: + if self._data is None: raise InterfaceError("Trying to access data, when there's no data") return reversed(self._data) def index(self, *args): - if self._data == None: + if self._data is None: raise InterfaceError("Trying to access data, when there's no data") return self._data.index(*args) def count(self, item): - if self._data == None: + if self._data is None: raise InterfaceError("Trying to access data, when there's no data") return self._data.count(item) @@ -149,7 +156,7 @@ def code(self): @property def sync(self): - '''\ + ''' :type: int Required field in the server response. @@ -220,7 +227,7 @@ def __str__(self): if self.return_code: return yaml.dump({ 'error': { - 'code' : self.strerror[0], + 'code': self.strerror[0], 'reason': self.return_message } }) diff --git a/tarantool/schema.py b/tarantool/schema.py index 1d8ba798..775c1f44 100644 --- a/tarantool/schema.py +++ b/tarantool/schema.py @@ -77,10 +77,12 @@ def fetch_space(self, space): if len(space_row) > 1: # We have selected more than one space, it's strange - raise SchemaError('Some strange output from server: \n' + str(space_row)) + raise SchemaError( + 'Some strange output from server: \n' + str(space_row) + ) elif len(space_row) == 0 or not len(space_row[0]): # We can't find space with this name or id - temp_name = ('name' if isinstance(space, six.string_types) else 'id') + temp_name = 'name' if isinstance(space, six.string_types) else 'id' errmsg = "There's no space with {1} '{0}'".format(space, temp_name) raise SchemaError(errmsg) @@ -95,13 +97,14 @@ def fetch_space_from(self, space): else: _index = const.INDEX_SPACE_PRIMARY - if space == None: + if space is None: space = () space_row = None try: # Try to fetch from '_vspace' - space_row = self.con.select(const.SPACE_VSPACE, space, index=_index) + space_row = self.con.select(const.SPACE_VSPACE, space, + index=_index) except DatabaseError as e: # if space can't be found, then user is using old version of # tarantool, try again with '_space' @@ -132,12 +135,15 @@ def fetch_index(self, space_object, index): if len(index_row) > 1: # We have selected more than one index, it's strange - raise SchemaError('Some strange output from server: \n' + str(index_row)) + raise SchemaError( + 'Some strange output from server: \n' + str(index_row) + ) elif len(index_row) == 0 or not len(index_row[0]): # We can't find index with this name or id - temp_name = ('name' if isinstance(index, six.string_types) else 'id') + temp_name = 'name' if isinstance(index, six.string_types) else 'id' errmsg = ("There's no index with {2} '{0}'" - " in space '{1}'").format(index, space_object.name, temp_name) + " in space '{1}'").format(index, space_object.name, + temp_name) raise SchemaError(errmsg) index_row = index_row[0] @@ -157,7 +163,7 @@ def fetch_index_from(self, space, index): _index = const.INDEX_INDEX_PRIMARY _key_tuple = None - if space is None and index is None: + if space is None and index is None: _key_tuple = () elif space is not None and index is None: _key_tuple = (space) @@ -169,7 +175,8 @@ def fetch_index_from(self, space, index): index_row = None try: # Try to fetch from '_vindex' - index_row = self.con.select(const.SPACE_VINDEX, _key_tuple, index=_index) + index_row = self.con.select(const.SPACE_VINDEX, _key_tuple, + index=_index) except DatabaseError as e: # if space can't be found, then user is using old version of # tarantool, try again with '_index' @@ -177,7 +184,8 @@ def fetch_index_from(self, space, index): raise if index_row is None: # Try to fetch from '_index' - index_row = self.con.select(const.SPACE_INDEX, _key_tuple, index=_index) + index_row = self.con.select(const.SPACE_INDEX, _key_tuple, + index=_index) return index_row diff --git a/tarantool/space.py b/tarantool/space.py index 73a447c6..53f40dc7 100644 --- a/tarantool/space.py +++ b/tarantool/space.py @@ -74,7 +74,7 @@ def select(self, *args, **kwargs): ''' return self.connection.select(self.space_no, *args, **kwargs) - def call(self, *args, **kwargs): + def call(self, func_name, *args, **kwargs): ''' Execute CALL request. Call stored Lua function. diff --git a/tarantool/utils.py b/tarantool/utils.py index 12f99d65..47b943f0 100644 --- a/tarantool/utils.py +++ b/tarantool/utils.py @@ -4,6 +4,7 @@ import base64 import uuid + def check_key(*args, **kwargs): if 'first' not in kwargs: kwargs['first'] = True @@ -21,9 +22,11 @@ def check_key(*args, **kwargs): assert isinstance(key, six.integer_types + six.string_types) return list(args) + def version_id(major, minor, patch): return (((major << 8) | minor) << 8) | patch + def greeting_decode(greeting_buf): class Greeting: version_id = 0 @@ -59,7 +62,7 @@ class Greeting: # Tarantool < 1.6.7 doesn't add "(Binary)" to greeting result.protocol = "Binary" elif len(tail.strip()) != 0: - raise Exception("x") # Unsuported greeting + raise Exception("x") # Unsuported greeting result.salt = base64.decodestring(greeting_buf[64:])[:20] return result except Exception as e: