Changed to tabs, to keep things consistent.

This commit is contained in:
Ian Bicking 2006-10-03 12:57:50 -05:00
parent bdf9c1b392
commit bd0e612f1a

View File

@ -46,218 +46,218 @@ _installed = False
fake_get_object = None fake_get_object = None
def _install(): def _install():
""" """
Installs the monkeypatch to dbus. Called automatically when Installs the monkeypatch to dbus. Called automatically when
necessary. necessary.
""" """
global _installed, fake_get_object global _installed, fake_get_object
if _installed: if _installed:
return return
bus = dbus.SessionBus() bus = dbus.SessionBus()
old_get_object = bus.get_object old_get_object = bus.get_object
fake_get_object = FakeGetObject(old_get_object) fake_get_object = FakeGetObject(old_get_object)
bus.get_object = fake_get_object bus.get_object = fake_get_object
_installed = True _installed = True
# XXX: Do we need to override bus.add_signal_receiver? # XXX: Do we need to override bus.add_signal_receiver?
class FakeGetObject(object): class FakeGetObject(object):
""" """
The replacement dbus.get_object() function/callable. This The replacement dbus.get_object() function/callable. This
delegates to the real get_object callable, except when a delegates to the real get_object callable, except when a
MockService has been registered. MockService has been registered.
""" """
def __init__(self, real_get_object): def __init__(self, real_get_object):
self._real_get_object = real_get_object self._real_get_object = real_get_object
self._overrides = {} self._overrides = {}
def register(self, mock_service, service_name, path): def register(self, mock_service, service_name, path):
""" """
Registers a MockService instance to the service_name and path. Registers a MockService instance to the service_name and path.
Calls to dbus.get_object(service_name, path) will now return Calls to dbus.get_object(service_name, path) will now return
this mock_service object. this mock_service object.
""" """
self._overrides[(service_name, path)] = mock_service self._overrides[(service_name, path)] = mock_service
def __call__(self, service_name, path): def __call__(self, service_name, path):
override = self._overrides.get((service_name, path), None) override = self._overrides.get((service_name, path), None)
if override is None: if override is None:
return self._real_get_object(service_name, path) return self._real_get_object(service_name, path)
else: else:
return override return override
class MockService(object): class MockService(object):
""" """
A mock service object. You should first instantiate then install A mock service object. You should first instantiate then install
this object. Once installed, calls to this object. Once installed, calls to
dbus.get_object(service_name, path) will return this object dbus.get_object(service_name, path) will return this object
instead of a real dbus service object. instead of a real dbus service object.
""" """
def __init__(self, service_name, path, name=None): def __init__(self, service_name, path, name=None):
self.service_name = service_name self.service_name = service_name
self.path = path self.path = path
if name is None: if name is None:
name = self.service_name name = self.service_name
self.name = name self.name = name
self._connections = {} self._connections = {}
self._pending_responses = {} self._pending_responses = {}
self._pending_requests = {} self._pending_requests = {}
def __repr__(self): def __repr__(self):
if self.name == self.service_name: if self.name == self.service_name:
return '<%s %s:%s>' % ( return '<%s %s:%s>' % (
self.__class__.__name__, self.__class__.__name__,
self.service_name, self.path) self.service_name, self.path)
else: else:
return '<%s %s %s:%s>' % ( return '<%s %s %s:%s>' % (
self.__class__.__name__, self.__class__.__name__,
self.name, self.name,
self.service_name, self.path) self.service_name, self.path)
def install(self): def install(self):
""" """
Installs this object. Installs this object.
""" """
_install() _install()
fake_get_object.register( fake_get_object.register(
self, self.service_name, self.path) self, self.service_name, self.path)
def __getattr__(self, attr, dbus_interface=None): def __getattr__(self, attr, dbus_interface=None):
if attr == 'make_response': if attr == 'make_response':
return BoundInterface(self.make_response, dbus_interface) return BoundInterface(self.make_response, dbus_interface)
return MockMethod(self, attr, dbus_interface) return MockMethod(self, attr, dbus_interface)
def call(self, meth_name, dbus_interface, *args, **kw): def call(self, meth_name, dbus_interface, *args, **kw):
formatted = [repr(a) for a in args] formatted = [repr(a) for a in args]
formatted.extend(['%s=%r' % item for item in kw.items()]) formatted.extend(['%s=%r' % item for item in kw.items()])
formatted = ', '.join(formatted) formatted = ', '.join(formatted)
print 'Called %s.%s:%s(%s)' % (self.name, dbus_interface, meth_name, formatted) print 'Called %s.%s:%s(%s)' % (self.name, dbus_interface, meth_name, formatted)
if 'reply_handler' in kw: if 'reply_handler' in kw:
reply_handler = kw.pop('reply_handler') reply_handler = kw.pop('reply_handler')
else: else:
reply_handler = None reply_handler = None
if 'error_handler' in kw: if 'error_handler' in kw:
error_handler = kw.pop('error_handler') error_handler = kw.pop('error_handler')
else: else:
error_handler = None error_handler = None
key = (meth_name, dbus_interface) key = (meth_name, dbus_interface)
if reply_handler: if reply_handler:
if key in self._pending_requests: if key in self._pending_requests:
raise ValueError( raise ValueError(
"Duplicate requests not yet handled for %s:%s" % (dbus_interface, meth_name)) "Duplicate requests not yet handled for %s:%s" % (dbus_interface, meth_name))
self._pending_requests[key] = (reply_handler, error_handler) self._pending_requests[key] = (reply_handler, error_handler)
self.call_reply_handlers() self.call_reply_handlers()
return return
assert error_handler is None, ( assert error_handler is None, (
"error_handler %s without reply_handler" % error_handler) "error_handler %s without reply_handler" % error_handler)
if key not in self._pending_responses: if key not in self._pending_responses:
if self._pending_responses: if self._pending_responses:
extra = '(have responses %s)' % self._response_description() extra = '(have responses %s)' % self._response_description()
else: else:
extra = '(have no waiting responses)' extra = '(have no waiting responses)'
raise ValueError( raise ValueError(
"You must call make_response() before %s:%s method " "You must call make_response() before %s:%s method "
"is called %s" "is called %s"
% (dbus_interface, meth_name, extra)) % (dbus_interface, meth_name, extra))
error, response = self._pending_responses.pop(key) error, response = self._pending_responses.pop(key)
if error: if error:
# XXX: Is this how it should be raised? # XXX: Is this how it should be raised?
raise response raise response
else: else:
return response return response
def make_response(self, meth_name, response, error=False, def make_response(self, meth_name, response, error=False,
dbus_interface=None): dbus_interface=None):
""" """
This is used to generate a response to a method call. If This is used to generate a response to a method call. If
error is true, then the response object is an exception that error is true, then the response object is an exception that
will be raised (or passed to error_handler). will be raised (or passed to error_handler).
""" """
key = (meth_name, dbus_interface) key = (meth_name, dbus_interface)
if key in self._pending_responses: if key in self._pending_responses:
raise ValueError( raise ValueError(
"A response %r is already registered for %s:%s" "A response %r is already registered for %s:%s"
% (self._pending_responses[key], dbus_interface, meth_name)) % (self._pending_responses[key], dbus_interface, meth_name))
self._pending_responses[key] = (error, response) self._pending_responses[key] = (error, response)
def _response_description(self): def _response_description(self):
result = [] result = []
for meth_name, dbus_interface in sorted(self._pending_responses.keys()): for meth_name, dbus_interface in sorted(self._pending_responses.keys()):
value = self._pending_responses[(meth_name, dbus_interface)] value = self._pending_responses[(meth_name, dbus_interface)]
result.append('%s:%s()=%r' % (dbus_interface, meth_name, value)) result.append('%s:%s()=%r' % (dbus_interface, meth_name, value))
return ', '.join(result) return ', '.join(result)
def call_reply_handlers(self): def call_reply_handlers(self):
""" """
This calls any reply_handlers that now have responses (or This calls any reply_handlers that now have responses (or
errors) ready for them. This can be called when a response is errors) ready for them. This can be called when a response is
added after an asynchronous method is called, to trigger the added after an asynchronous method is called, to trigger the
response actually being called. response actually being called.
""" """
# XXX: Should make_response automatically call this? # XXX: Should make_response automatically call this?
for key in sorted(self._pending_responses.keys()): for key in sorted(self._pending_responses.keys()):
if key in self._pending_requests: if key in self._pending_requests:
error, response = self._pending_responses[key] error, response = self._pending_responses[key]
reply_handler, error_handler = self._pending_requests[key] reply_handler, error_handler = self._pending_requests[key]
if error: if error:
# XXX: Is this how it should be raised? # XXX: Is this how it should be raised?
error_handler(response) error_handler(response)
else: else:
reply_handler(response) reply_handler(response)
del self._pending_responses[key] del self._pending_responses[key]
del self._pending_requests[key] del self._pending_requests[key]
def connect_to_signal(self, signal, handler_function, def connect_to_signal(self, signal, handler_function,
dbus_interface=None, **kw): dbus_interface=None, **kw):
self._connections.setdefault((signal, dbus_interface), []).append( self._connections.setdefault((signal, dbus_interface), []).append(
handler_function) handler_function)
def send_signal(self, signal, dbus_interface=None): def send_signal(self, signal, dbus_interface=None):
# XXX: This isn't really done # XXX: This isn't really done
for listener in self._connections.get((signal, dbus_interface), []): for listener in self._connections.get((signal, dbus_interface), []):
# XXX: Argument? # XXX: Argument?
listener() listener()
@property @property
def empty(self): def empty(self):
""" """
This can be called to at the end of the test to make sure This can be called to at the end of the test to make sure
there's no responses or requests left over. there's no responses or requests left over.
""" """
return ( return (
not self._pending_responses not self._pending_responses
and not self._pending_requests) and not self._pending_requests)
class MockMethod(object): class MockMethod(object):
def __init__(self, obj, meth_name, dbus_interface): def __init__(self, obj, meth_name, dbus_interface):
self.obj = obj self.obj = obj
self.meth_name = meth_name self.meth_name = meth_name
self.dbus_interface = dbus_interface self.dbus_interface = dbus_interface
def __repr__(self): def __repr__(self):
return '<%s.%s:%s method>' % ( return '<%s.%s:%s method>' % (
self.obj.name, self.meth_name, self.dbus_interface) self.obj.name, self.meth_name, self.dbus_interface)
def __call__(self, *args, **kw): def __call__(self, *args, **kw):
return self.obj.call( return self.obj.call(
self.meth_name, self.dbus_interface, self.meth_name, self.dbus_interface,
*args, **kw) *args, **kw)
class BoundInterface(object): class BoundInterface(object):
def __init__(self, method, dbus_interface): def __init__(self, method, dbus_interface):
self.method = method self.method = method
self.dbus_interface = dbus_interface self.dbus_interface = dbus_interface
def __repr__(self): def __repr__(self):
return '<bound interface %s for %s>' % ( return '<bound interface %s for %s>' % (
self.dbus_interface, self.method) self.dbus_interface, self.method)
def __call__(self, *args, **kw):
kw.setdefault('dbus_interface', self.dbus_interface)
return self.method(*args, **kw)
def __call__(self, *args, **kw):
kw.setdefault('dbus_interface', self.dbus_interface)
return self.method(*args, **kw)