Commit 772221b8 authored by Jim Fulton's avatar Jim Fulton Committed by GitHub

Merge pull request #69 from zopefoundation/dont-pickle-errors

Dont pickle errors
parents c087f634 2c7a04f7
...@@ -37,3 +37,7 @@ class AuthError(StorageError): ...@@ -37,3 +37,7 @@ class AuthError(StorageError):
class ProtocolError(ClientStorageError): class ProtocolError(ClientStorageError):
"""A client contacted a server with an incomparible protocol """A client contacted a server with an incomparible protocol
""" """
class ServerException(ClientStorageError):
"""
"""
...@@ -5,7 +5,7 @@ if PY3: ...@@ -5,7 +5,7 @@ if PY3:
else: else:
import trollius as asyncio import trollius as asyncio
from ZEO.Exceptions import ClientDisconnected from ZEO.Exceptions import ClientDisconnected, ServerException
import concurrent.futures import concurrent.futures
import functools import functools
import logging import logging
...@@ -208,15 +208,22 @@ class Protocol(base.Protocol): ...@@ -208,15 +208,22 @@ class Protocol(base.Protocol):
msgid, async, name, args = decode(data) msgid, async, name, args = decode(data)
if name == '.reply': if name == '.reply':
future = self.futures.pop(msgid) future = self.futures.pop(msgid)
if (isinstance(args, tuple) and len(args) > 1 and if (async): # ZEO 5 exception
type(args[0]) == self.exception_type_type and class_, args = args
issubclass(args[0], Exception) factory = exc_factories.get(class_)
): if factory:
if not issubclass( exc = factory(class_, args)
args[0], ( if not isinstance(exc, unlogged_exceptions):
ZODB.POSException.POSKeyError, logger.error("%s from server: %s:%s",
ZODB.POSException.ConflictError,) self.name, class_, args)
): else:
exc = ServerException(class_, args)
future.set_exception(exc)
elif (isinstance(args, tuple) and len(args) > 1 and
type(args[0]) == self.exception_type_type and
issubclass(args[0], Exception)
):
if not issubclass(args[0], unlogged_exceptions):
logger.error("%s from server: %s.%s:%s", logger.error("%s from server: %s.%s:%s",
self.name, self.name,
args[0].__module__, args[0].__module__,
...@@ -270,6 +277,56 @@ class Protocol(base.Protocol): ...@@ -270,6 +277,56 @@ class Protocol(base.Protocol):
self.heartbeat_handle = self.loop.call_later( self.heartbeat_handle = self.loop.call_later(
self.heartbeat_interval, self.heartbeat) self.heartbeat_interval, self.heartbeat)
def create_Exception(class_, args):
return exc_classes[class_](*args)
def create_ConflictError(class_, args):
exc = exc_classes[class_](
message = args['message'],
oid = args['oid'],
serials = args['serials'],
)
exc.class_name = args.get('class_name')
return exc
def create_BTreesConflictError(class_, args):
return ZODB.POSException.BTreesConflictError(
p1 = args['p1'],
p2 = args['p2'],
p3 = args['p3'],
reason = args['reason'],
)
def create_MultipleUndoErrors(class_, args):
return ZODB.POSException.MultipleUndoErrors(args['_errs'])
exc_classes = {
'builtins.KeyError': KeyError,
'builtins.TypeError': TypeError,
'exceptions.KeyError': KeyError,
'exceptions.TypeError': TypeError,
'ZODB.POSException.ConflictError': ZODB.POSException.ConflictError,
'ZODB.POSException.POSKeyError': ZODB.POSException.POSKeyError,
'ZODB.POSException.ReadConflictError': ZODB.POSException.ReadConflictError,
'ZODB.POSException.ReadOnlyError': ZODB.POSException.ReadOnlyError,
'ZODB.POSException.StorageTransactionError':
ZODB.POSException.StorageTransactionError,
}
exc_factories = {
'builtins.KeyError': create_Exception,
'builtins.TypeError': create_Exception,
'exceptions.KeyError': create_Exception,
'exceptions.TypeError': create_Exception,
'ZODB.POSException.BTreesConflictError': create_BTreesConflictError,
'ZODB.POSException.ConflictError': create_ConflictError,
'ZODB.POSException.MultipleUndoErrors': create_MultipleUndoErrors,
'ZODB.POSException.POSKeyError': create_Exception,
'ZODB.POSException.ReadConflictError': create_ConflictError,
'ZODB.POSException.ReadOnlyError': create_Exception,
'ZODB.POSException.StorageTransactionError': create_Exception,
}
unlogged_exceptions = (ZODB.POSException.POSKeyError,
ZODB.POSException.ConflictError)
class Client(object): class Client(object):
"""asyncio low-level ZEO client interface """asyncio low-level ZEO client interface
""" """
......
...@@ -111,9 +111,9 @@ class ServerProtocol(base.Protocol): ...@@ -111,9 +111,9 @@ class ServerProtocol(base.Protocol):
if not async: if not async:
self.send_reply(message_id, result) self.send_reply(message_id, result)
def send_reply(self, message_id, result, send_error=False): def send_reply(self, message_id, result, send_error=False, flag=0):
try: try:
result = self.encode(message_id, 0, '.reply', result) result = self.encode(message_id, flag, '.reply', result)
except Exception: except Exception:
if isinstance(result, Delay): if isinstance(result, Delay):
result.set_sender(message_id, self) result.set_sender(message_id, self)
...@@ -134,7 +134,10 @@ class ServerProtocol(base.Protocol): ...@@ -134,7 +134,10 @@ class ServerProtocol(base.Protocol):
def send_error(self, message_id, exc, send_error=False): def send_error(self, message_id, exc, send_error=False):
"""Abstracting here so we can make this cleaner in the future """Abstracting here so we can make this cleaner in the future
""" """
self.send_reply(message_id, (exc.__class__, exc), send_error) class_ = exc.__class__
class_ = "%s.%s" % (class_.__module__, class_.__name__)
args = class_, exc.__dict__ or exc.args
self.send_reply(message_id, args, send_error, 2)
def async(self, method, *args): def async(self, method, *args):
self.call_async(method, args) self.call_async(method, args)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment