Chris Norman
2016-04-02 09:35:01 UTC
Hi all,
I recently got over myself and forced myself to read about Deferreds
rather than using threading opperations.
I've used them successfully in a couple of places, but this one has me
flummoxed:
Here's the code for the Deferred and it's sub-commands:
def do_command(self, cmd, **kwargs):
"""Process a command in true Deferred style."""
if cmd.permissions(self.connection):
cmd(self.connection, **kwargs)
else:
logger.warning('Blocked from running command %s which is secured
with %s.', cmd.__name__, cmd.permissions.__name__)
raise CommandError('You have insufficient privileges to perform this
action. The staff have been notified.')
def handle_error(self, err):
"""Handle an error from do_command."""
if isinstance(err, CommandError):
return self.send_error(e.message, disconnect = e.disconnect)
else:
self.log(e, level = 'exception')
self.send_error('Sorry, but a problem with the server means your
command was not executed. The staff have been notified.')
def lineReceived(self, line):
"""Parse an incoming command."""
global lines
lines += 1 # Increment the line count.
data = line.decode(settings.ENCODING)
try:
command, kwargs = json.loads(data)
if not isinstance(command, string_types) or not isinstance(kwargs,
dict):
raise TypeError('Expecting [str, dict]. Got [%s, %s] instead.' %
(type(command), type(kwargs)))
except (TypeError, ValueError) as e:
self.log('Invalid command string: %s', data, level = 'error')
self.log(e, level = 'exception')
return self.send_error('Invalid command.', disconnect = True)
cmd = commands.commands.get(command, None)
if cmd is None:
self.log('Unrecognised command: %s.', command, level = 'warning')
elif self.connection.player or not cmd.login_required:
d = defer.Deferred()
print('Adding callback.')
d.addCallback(self.do_command, **kwargs)
print('Adding errback.')
d.addErrback(self.handle_error)
print('Calling callback.')
d.callback(cmd)
print('Called.') # Never gets this far.
return d
else:
return self.send_error('Not authenticated.', disconnect = True)
Here's the traceback I get when the callback gets called:
Unhandled Error
Traceback (most recent call last):
File "server/functions.py", line 88, in server_start
reactor.run()
File
"/usr/local/lib/python3.5/site-packages/Twisted-16.0.0-py3.5.egg/twisted/internet/base.py",
line 1194, in run
self.mainLoop()
File
"/usr/local/lib/python3.5/site-packages/Twisted-16.0.0-py3.5.egg/twisted/internet/base.py",
line 1206, in mainLoop
self.doIteration(t)
File
"/usr/local/lib/python3.5/site-packages/Twisted-16.0.0-py3.5.egg/twisted/internet/epollreactor.py",
line 396, in doPoll
log.callWithLogger(selectable, _drdw, selectable, fd, event)
--- <exception caught here> ---
File
"/usr/local/lib/python3.5/site-packages/Twisted-16.0.0-py3.5.egg/twisted/python/log.py",
line 101, in callWithLogger
return callWithContext({"system": lp}, func, *args, **kw)
File
"/usr/local/lib/python3.5/site-packages/Twisted-16.0.0-py3.5.egg/twisted/python/log.py",
line 84, in callWithContext
return context.call({ILogContext: newCtx}, func, *args, **kw)
File
"/usr/local/lib/python3.5/site-packages/Twisted-16.0.0-py3.5.egg/twisted/python/context.py",
line 118, in callWithContext
return self.currentContext().callWithContext(ctx, func, *args, **kw)
File
"/usr/local/lib/python3.5/site-packages/Twisted-16.0.0-py3.5.egg/twisted/python/context.py",
line 81, in callWithContext
return func(*args,**kw)
File
"/usr/local/lib/python3.5/site-packages/Twisted-16.0.0-py3.5.egg/twisted/internet/posixbase.py",
line 610, in _doReadOrWrite
self._disconnectSelectable(selectable, why, inRead)
File
"/usr/local/lib/python3.5/site-packages/Twisted-16.0.0-py3.5.egg/twisted/internet/posixbase.py",
line 258, in _disconnectSelectable
selectable.connectionLost(failure.Failure(why))
File
"/usr/local/lib/python3.5/site-packages/Twisted-16.0.0-py3.5.egg/twisted/python/failure.py",
line 232, in __init__
tb = self.value.__traceback__
builtins.AttributeError: 'Deferred' object has no attribute '__traceback__'
Anyone have any ideas?
Cheers,
Chris
I recently got over myself and forced myself to read about Deferreds
rather than using threading opperations.
I've used them successfully in a couple of places, but this one has me
flummoxed:
Here's the code for the Deferred and it's sub-commands:
def do_command(self, cmd, **kwargs):
"""Process a command in true Deferred style."""
if cmd.permissions(self.connection):
cmd(self.connection, **kwargs)
else:
logger.warning('Blocked from running command %s which is secured
with %s.', cmd.__name__, cmd.permissions.__name__)
raise CommandError('You have insufficient privileges to perform this
action. The staff have been notified.')
def handle_error(self, err):
"""Handle an error from do_command."""
if isinstance(err, CommandError):
return self.send_error(e.message, disconnect = e.disconnect)
else:
self.log(e, level = 'exception')
self.send_error('Sorry, but a problem with the server means your
command was not executed. The staff have been notified.')
def lineReceived(self, line):
"""Parse an incoming command."""
global lines
lines += 1 # Increment the line count.
data = line.decode(settings.ENCODING)
try:
command, kwargs = json.loads(data)
if not isinstance(command, string_types) or not isinstance(kwargs,
dict):
raise TypeError('Expecting [str, dict]. Got [%s, %s] instead.' %
(type(command), type(kwargs)))
except (TypeError, ValueError) as e:
self.log('Invalid command string: %s', data, level = 'error')
self.log(e, level = 'exception')
return self.send_error('Invalid command.', disconnect = True)
cmd = commands.commands.get(command, None)
if cmd is None:
self.log('Unrecognised command: %s.', command, level = 'warning')
elif self.connection.player or not cmd.login_required:
d = defer.Deferred()
print('Adding callback.')
d.addCallback(self.do_command, **kwargs)
print('Adding errback.')
d.addErrback(self.handle_error)
print('Calling callback.')
d.callback(cmd)
print('Called.') # Never gets this far.
return d
else:
return self.send_error('Not authenticated.', disconnect = True)
Here's the traceback I get when the callback gets called:
Unhandled Error
Traceback (most recent call last):
File "server/functions.py", line 88, in server_start
reactor.run()
File
"/usr/local/lib/python3.5/site-packages/Twisted-16.0.0-py3.5.egg/twisted/internet/base.py",
line 1194, in run
self.mainLoop()
File
"/usr/local/lib/python3.5/site-packages/Twisted-16.0.0-py3.5.egg/twisted/internet/base.py",
line 1206, in mainLoop
self.doIteration(t)
File
"/usr/local/lib/python3.5/site-packages/Twisted-16.0.0-py3.5.egg/twisted/internet/epollreactor.py",
line 396, in doPoll
log.callWithLogger(selectable, _drdw, selectable, fd, event)
--- <exception caught here> ---
File
"/usr/local/lib/python3.5/site-packages/Twisted-16.0.0-py3.5.egg/twisted/python/log.py",
line 101, in callWithLogger
return callWithContext({"system": lp}, func, *args, **kw)
File
"/usr/local/lib/python3.5/site-packages/Twisted-16.0.0-py3.5.egg/twisted/python/log.py",
line 84, in callWithContext
return context.call({ILogContext: newCtx}, func, *args, **kw)
File
"/usr/local/lib/python3.5/site-packages/Twisted-16.0.0-py3.5.egg/twisted/python/context.py",
line 118, in callWithContext
return self.currentContext().callWithContext(ctx, func, *args, **kw)
File
"/usr/local/lib/python3.5/site-packages/Twisted-16.0.0-py3.5.egg/twisted/python/context.py",
line 81, in callWithContext
return func(*args,**kw)
File
"/usr/local/lib/python3.5/site-packages/Twisted-16.0.0-py3.5.egg/twisted/internet/posixbase.py",
line 610, in _doReadOrWrite
self._disconnectSelectable(selectable, why, inRead)
File
"/usr/local/lib/python3.5/site-packages/Twisted-16.0.0-py3.5.egg/twisted/internet/posixbase.py",
line 258, in _disconnectSelectable
selectable.connectionLost(failure.Failure(why))
File
"/usr/local/lib/python3.5/site-packages/Twisted-16.0.0-py3.5.egg/twisted/python/failure.py",
line 232, in __init__
tb = self.value.__traceback__
builtins.AttributeError: 'Deferred' object has no attribute '__traceback__'
Anyone have any ideas?
Cheers,
Chris