| Index: mojo/public/python/mojo_bindings/reflection.py
|
| diff --git a/mojo/public/python/mojo_bindings/reflection.py b/mojo/public/python/mojo_bindings/reflection.py
|
| deleted file mode 100644
|
| index 5432691c3e783147eeb67d699b6a54ff413d7320..0000000000000000000000000000000000000000
|
| --- a/mojo/public/python/mojo_bindings/reflection.py
|
| +++ /dev/null
|
| @@ -1,569 +0,0 @@
|
| -# Copyright 2014 The Chromium Authors. All rights reserved.
|
| -# Use of this source code is governed by a BSD-style license that can be
|
| -# found in the LICENSE file.
|
| -
|
| -"""The metaclasses used by the mojo python bindings."""
|
| -
|
| -import itertools
|
| -import logging
|
| -import sys
|
| -
|
| -# pylint: disable=F0401
|
| -import mojo_bindings.messaging as messaging
|
| -import mojo_bindings.promise as promise
|
| -import mojo_bindings.serialization as serialization
|
| -
|
| -
|
| -class MojoEnumType(type):
|
| - """Meta class for enumerations.
|
| -
|
| - Usage:
|
| - class MyEnum(object):
|
| - __metaclass__ = MojoEnumType
|
| - VALUES = [
|
| - ('A', 0),
|
| - 'B',
|
| - ('C', 5),
|
| - ]
|
| -
|
| - This will define a enum with 3 values, 'A' = 0, 'B' = 1 and 'C' = 5.
|
| - """
|
| -
|
| - def __new__(mcs, name, bases, dictionary):
|
| - dictionary['__slots__'] = ()
|
| - dictionary['__new__'] = None
|
| - for value in dictionary.pop('VALUES', []):
|
| - if not isinstance(value, tuple):
|
| - raise ValueError('incorrect value: %r' % value)
|
| - key, enum_value = value
|
| - if isinstance(key, str) and isinstance(enum_value, int):
|
| - dictionary[key] = enum_value
|
| - else:
|
| - raise ValueError('incorrect value: %r' % value)
|
| - return type.__new__(mcs, name, bases, dictionary)
|
| -
|
| - def __setattr__(cls, key, value):
|
| - raise AttributeError('can\'t set attribute')
|
| -
|
| - def __delattr__(cls, key):
|
| - raise AttributeError('can\'t delete attribute')
|
| -
|
| -
|
| -class MojoStructType(type):
|
| - """Meta class for structs.
|
| -
|
| - Usage:
|
| - class MyStruct(object):
|
| - __metaclass__ = MojoStructType
|
| - DESCRIPTOR = {
|
| - 'constants': {
|
| - 'C1': 1,
|
| - 'C2': 2,
|
| - },
|
| - 'enums': {
|
| - 'ENUM1': [
|
| - ('V1', 1),
|
| - 'V2',
|
| - ],
|
| - 'ENUM2': [
|
| - ('V1', 1),
|
| - 'V2',
|
| - ],
|
| - },
|
| - 'fields': [
|
| - SingleFieldGroup('x', _descriptor.TYPE_INT32, 0, 0),
|
| - ],
|
| - }
|
| -
|
| - This will define an struct, with:
|
| - - 2 constants 'C1' and 'C2';
|
| - - 2 enums 'ENUM1' and 'ENUM2', each of those having 2 values, 'V1' and
|
| - 'V2';
|
| - - 1 int32 field named 'x'.
|
| - """
|
| -
|
| - def __new__(mcs, name, bases, dictionary):
|
| - dictionary['__slots__'] = ('_fields')
|
| - descriptor = dictionary.pop('DESCRIPTOR', {})
|
| -
|
| - # Add constants
|
| - dictionary.update(descriptor.get('constants', {}))
|
| -
|
| - # Add enums
|
| - enums = descriptor.get('enums', {})
|
| - for key in enums:
|
| - dictionary[key] = MojoEnumType(key, (object,), { 'VALUES': enums[key] })
|
| -
|
| - # Add fields
|
| - groups = descriptor.get('fields', [])
|
| -
|
| - fields = list(
|
| - itertools.chain.from_iterable([group.descriptors for group in groups]))
|
| - fields.sort(key=lambda f: f.index)
|
| - for field in fields:
|
| - dictionary[field.name] = _BuildProperty(field)
|
| -
|
| - # Add init
|
| - dictionary['__init__'] = _StructInit(fields)
|
| -
|
| - # Add serialization method
|
| - serialization_object = serialization.Serialization(groups)
|
| - def Serialize(self, handle_offset=0):
|
| - return serialization_object.Serialize(self, handle_offset)
|
| - dictionary['Serialize'] = Serialize
|
| -
|
| - # pylint: disable=W0212
|
| - def AsDict(self):
|
| - return self._fields
|
| - dictionary['AsDict'] = AsDict
|
| -
|
| - def Deserialize(cls, context):
|
| - result = cls.__new__(cls)
|
| - fields = {}
|
| - serialization_object.Deserialize(fields, context)
|
| - result._fields = fields
|
| - return result
|
| - dictionary['Deserialize'] = classmethod(Deserialize)
|
| -
|
| - dictionary['__eq__'] = _StructEq(fields)
|
| - dictionary['__ne__'] = _StructNe
|
| -
|
| - return type.__new__(mcs, name, bases, dictionary)
|
| -
|
| - # Prevent adding new attributes, or mutating constants.
|
| - def __setattr__(cls, key, value):
|
| - raise AttributeError('can\'t set attribute')
|
| -
|
| - # Prevent deleting constants.
|
| - def __delattr__(cls, key):
|
| - raise AttributeError('can\'t delete attribute')
|
| -
|
| -
|
| -class MojoInterfaceType(type):
|
| - """Meta class for interfaces.
|
| -
|
| - Usage:
|
| - class MyInterface(object):
|
| - __metaclass__ = MojoInterfaceType
|
| - DESCRIPTOR = {
|
| - 'client': MyInterfaceClient,
|
| - 'methods': [
|
| - {
|
| - 'name': 'FireAndForget',
|
| - 'ordinal': 0,
|
| - 'parameters': [
|
| - SingleFieldGroup('x', _descriptor.TYPE_INT32, 0, 0),
|
| - ]
|
| - },
|
| - {
|
| - 'name': 'Ping',
|
| - 'ordinal': 1,
|
| - 'parameters': [
|
| - SingleFieldGroup('x', _descriptor.TYPE_INT32, 0, 0),
|
| - ],
|
| - 'responses': [
|
| - SingleFieldGroup('x', _descriptor.TYPE_INT32, 0, 0),
|
| - ],
|
| - },
|
| - ],
|
| - }
|
| - """
|
| -
|
| - def __new__(mcs, name, bases, dictionary):
|
| - # If one of the base class is already an interface type, do not edit the
|
| - # class.
|
| - for base in bases:
|
| - if isinstance(base, mcs):
|
| - return type.__new__(mcs, name, bases, dictionary)
|
| -
|
| - descriptor = dictionary.pop('DESCRIPTOR', {})
|
| -
|
| - methods = [_MethodDescriptor(x) for x in descriptor.get('methods', [])]
|
| - for method in methods:
|
| - dictionary[method.name] = _NotImplemented
|
| - client_class_getter = descriptor.get('client', None)
|
| -
|
| - interface_manager = InterfaceManager(name, methods, client_class_getter)
|
| - dictionary.update({
|
| - 'client': None,
|
| - 'manager': None,
|
| - '_interface_manager': interface_manager,
|
| - })
|
| -
|
| - interface_class = type.__new__(mcs, name, bases, dictionary)
|
| - interface_manager.interface_class = interface_class
|
| - return interface_class
|
| -
|
| - @property
|
| - def manager(cls):
|
| - return cls._interface_manager
|
| -
|
| - # Prevent adding new attributes, or mutating constants.
|
| - def __setattr__(cls, key, value):
|
| - raise AttributeError('can\'t set attribute')
|
| -
|
| - # Prevent deleting constants.
|
| - def __delattr__(cls, key):
|
| - raise AttributeError('can\'t delete attribute')
|
| -
|
| -
|
| -class InterfaceProxy(object):
|
| - """
|
| - A proxy allows to access a remote interface through a message pipe.
|
| - """
|
| - pass
|
| -
|
| -
|
| -class InterfaceRequest(object):
|
| - """
|
| - An interface request allows to send a request for an interface to a remote
|
| - object and start using it immediately.
|
| - """
|
| -
|
| - def __init__(self, handle):
|
| - self._handle = handle
|
| -
|
| - def IsPending(self):
|
| - return self._handle.IsValid()
|
| -
|
| - def PassMessagePipe(self):
|
| - result = self._handle
|
| - self._handle = None
|
| - return result
|
| -
|
| -
|
| -class InterfaceManager(object):
|
| - """
|
| - Manager for an interface class. The manager contains the operation that allows
|
| - to bind an implementation to a pipe, or to generate a proxy for an interface
|
| - over a pipe.
|
| - """
|
| -
|
| - def __init__(self, name, methods, client_class_getter):
|
| - self.name = name
|
| - self.methods = methods
|
| - self.interface_class = None
|
| - self._client_class_getter = client_class_getter
|
| - self._client_manager = None
|
| - self._client_manager_computed = False
|
| - self._proxy_class = None
|
| - self._stub_class = None
|
| -
|
| - @property
|
| - def client_manager(self):
|
| - if not self._client_manager_computed:
|
| - self._client_manager_computed = True
|
| - if self._client_class_getter:
|
| - self._client_manager = self._client_class_getter().manager
|
| - return self._client_manager
|
| -
|
| - def Proxy(self, handle):
|
| - router = messaging.Router(handle)
|
| - error_handler = _ProxyErrorHandler()
|
| - router.SetErrorHandler(error_handler)
|
| - router.Start()
|
| - return self._InternalProxy(router, error_handler)
|
| -
|
| - # pylint: disable=W0212
|
| - def Bind(self, impl, handle):
|
| - router = messaging.Router(handle)
|
| - router.SetIncomingMessageReceiver(self._Stub(impl))
|
| - error_handler = _ProxyErrorHandler()
|
| - router.SetErrorHandler(error_handler)
|
| -
|
| - # Retain the router, until an error happen.
|
| - retainer = _Retainer(router)
|
| - def Cleanup(_):
|
| - retainer.release()
|
| - error_handler.AddCallback(Cleanup)
|
| -
|
| - if self.client_manager:
|
| - impl.client = self.client_manager._InternalProxy(router, error_handler)
|
| -
|
| - # Give an instance manager to the implementation to allow it to close
|
| - # the connection.
|
| - impl.manager = InstanceManager(router)
|
| -
|
| - router.Start()
|
| -
|
| - def _InternalProxy(self, router, error_handler):
|
| - if not self._proxy_class:
|
| - dictionary = {
|
| - '__module__': __name__,
|
| - '__init__': _ProxyInit,
|
| - }
|
| - if self.client_manager:
|
| - dictionary['client'] = property(_ProxyGetClient, _ProxySetClient)
|
| - dictionary['manager'] = None
|
| - dictionary['_client_manager'] = self.client_manager
|
| - for method in self.methods:
|
| - dictionary[method.name] = _ProxyMethodCall(method)
|
| - self._proxy_class = type('%sProxy' % self.name,
|
| - (self.interface_class, InterfaceProxy),
|
| - dictionary)
|
| -
|
| - proxy = self._proxy_class(router, error_handler)
|
| - # Give an instance manager to the proxy to allow to close the connection.
|
| - proxy.manager = InstanceManager(router)
|
| - return proxy
|
| -
|
| - def _Stub(self, impl):
|
| - if not self._stub_class:
|
| - accept_method = _StubAccept(self.methods)
|
| - dictionary = {
|
| - '__module__': __name__,
|
| - '__init__': _StubInit,
|
| - 'Accept': accept_method,
|
| - 'AcceptWithResponder': accept_method,
|
| - }
|
| - self._stub_class = type('%sStub' % self.name,
|
| - (messaging.MessageReceiverWithResponder,),
|
| - dictionary)
|
| - return self._stub_class(impl)
|
| -
|
| -
|
| -class InstanceManager(object):
|
| - """
|
| - Manager for the implementation of an interface or a proxy. The manager allows
|
| - to control the connection over the pipe.
|
| - """
|
| - def __init__(self, router):
|
| - self.router = router
|
| -
|
| - def Close(self):
|
| - self.router.Close()
|
| -
|
| - def PassMessagePipe(self):
|
| - return self.router.PassMessagePipe()
|
| -
|
| -
|
| -class _MethodDescriptor(object):
|
| - def __init__(self, descriptor):
|
| - self.name = descriptor['name']
|
| - self.ordinal = descriptor['ordinal']
|
| - self.parameters_struct = _ConstructParameterStruct(
|
| - descriptor['parameters'], self.name, "Parameters")
|
| - self.response_struct = _ConstructParameterStruct(
|
| - descriptor.get('responses'), self.name, "Responses")
|
| -
|
| -
|
| -def _ConstructParameterStruct(descriptor, name, suffix):
|
| - if descriptor is None:
|
| - return None
|
| - parameter_dictionary = {
|
| - '__metaclass__': MojoStructType,
|
| - '__module__': __name__,
|
| - 'DESCRIPTOR': descriptor,
|
| - }
|
| - return MojoStructType(
|
| - '%s%s' % (name, suffix),
|
| - (object,),
|
| - parameter_dictionary)
|
| -
|
| -
|
| -class _ProxyErrorHandler(messaging.ConnectionErrorHandler):
|
| - def __init__(self):
|
| - messaging.ConnectionErrorHandler.__init__(self)
|
| - self._callbacks = set()
|
| -
|
| - def OnError(self, result):
|
| - exception = messaging.MessagingException('Mojo error: %d' % result)
|
| - for callback in list(self._callbacks):
|
| - callback(exception)
|
| - self._callbacks = None
|
| -
|
| - def AddCallback(self, callback):
|
| - if self._callbacks is not None:
|
| - self._callbacks.add(callback)
|
| -
|
| - def RemoveCallback(self, callback):
|
| - if self._callbacks:
|
| - self._callbacks.remove(callback)
|
| -
|
| -
|
| -class _Retainer(object):
|
| -
|
| - # Set to force instances to be retained.
|
| - _RETAINED = set()
|
| -
|
| - def __init__(self, retained):
|
| - self._retained = retained
|
| - _Retainer._RETAINED.add(self)
|
| -
|
| - def release(self):
|
| - self._retained = None
|
| - _Retainer._RETAINED.remove(self)
|
| -
|
| -
|
| -def _StructInit(fields):
|
| - def _Init(self, *args, **kwargs):
|
| - if len(args) + len(kwargs) > len(fields):
|
| - raise TypeError('__init__() takes %d argument (%d given)' %
|
| - (len(fields), len(args) + len(kwargs)))
|
| - self._fields = {}
|
| - for f, a in zip(fields, args):
|
| - self.__setattr__(f.name, a)
|
| - remaining_fields = set(x.name for x in fields[len(args):])
|
| - for name in kwargs:
|
| - if not name in remaining_fields:
|
| - if name in (x.name for x in fields[:len(args)]):
|
| - raise TypeError(
|
| - '__init__() got multiple values for keyword argument %r' % name)
|
| - raise TypeError('__init__() got an unexpected keyword argument %r' %
|
| - name)
|
| - self.__setattr__(name, kwargs[name])
|
| - return _Init
|
| -
|
| -
|
| -def _BuildProperty(field):
|
| - """Build the property for the given field."""
|
| -
|
| - # pylint: disable=W0212
|
| - def Get(self):
|
| - if field.name not in self._fields:
|
| - self._fields[field.name] = field.GetDefaultValue()
|
| - return self._fields[field.name]
|
| -
|
| - # pylint: disable=W0212
|
| - def Set(self, value):
|
| - self._fields[field.name] = field.field_type.Convert(value)
|
| -
|
| - return property(Get, Set)
|
| -
|
| -
|
| -def _StructEq(fields):
|
| - def _Eq(self, other):
|
| - if type(self) is not type(other):
|
| - return False
|
| - for field in fields:
|
| - if getattr(self, field.name) != getattr(other, field.name):
|
| - return False
|
| - return True
|
| - return _Eq
|
| -
|
| -def _StructNe(self, other):
|
| - return not self.__eq__(other)
|
| -
|
| -
|
| -def _ProxyInit(self, router, error_handler):
|
| - self._router = router
|
| - self._error_handler = error_handler
|
| - self._client = None
|
| -
|
| -
|
| -# pylint: disable=W0212
|
| -def _ProxyGetClient(self):
|
| - return self._client
|
| -
|
| -
|
| -# pylint: disable=W0212
|
| -def _ProxySetClient(self, client):
|
| - self._client = client
|
| - stub = self._client_manager._Stub(client)
|
| - self._router.SetIncomingMessageReceiver(stub)
|
| -
|
| -
|
| -# pylint: disable=W0212
|
| -def _ProxyMethodCall(method):
|
| - flags = messaging.NO_FLAG
|
| - if method.response_struct:
|
| - flags = messaging.MESSAGE_EXPECTS_RESPONSE_FLAG
|
| - def _Call(self, *args, **kwargs):
|
| - def GenerationMethod(resolve, reject):
|
| - message = _GetMessage(method, flags, *args, **kwargs)
|
| - if method.response_struct:
|
| - def Accept(message):
|
| - try:
|
| - assert message.header.message_type == method.ordinal
|
| - payload = message.payload
|
| - response = method.response_struct.Deserialize(
|
| - serialization.RootDeserializationContext(payload.data,
|
| - payload.handles))
|
| - as_dict = response.AsDict()
|
| - if len(as_dict) == 1:
|
| - value = as_dict.values()[0]
|
| - if not isinstance(value, dict):
|
| - response = value
|
| - resolve(response)
|
| - return True
|
| - except Exception as e:
|
| - # Adding traceback similarly to python 3.0 (pep-3134)
|
| - e.__traceback__ = sys.exc_info()[2]
|
| - reject(e)
|
| - return False
|
| - finally:
|
| - self._error_handler.RemoveCallback(reject)
|
| -
|
| - self._error_handler.AddCallback(reject)
|
| - if not self._router.AcceptWithResponder(
|
| - message, messaging.ForwardingMessageReceiver(Accept)):
|
| - self._error_handler.RemoveCallback(reject)
|
| - reject(messaging.MessagingException("Unable to send message."))
|
| - else:
|
| - if (self._router.Accept(message)):
|
| - resolve(None)
|
| - else:
|
| - reject(messaging.MessagingException("Unable to send message."))
|
| - return promise.Promise(GenerationMethod)
|
| - return _Call
|
| -
|
| -
|
| -def _GetMessage(method, flags, *args, **kwargs):
|
| - if flags == messaging.MESSAGE_IS_RESPONSE_FLAG:
|
| - struct = method.response_struct(*args, **kwargs)
|
| - else:
|
| - struct = method.parameters_struct(*args, **kwargs)
|
| - header = messaging.MessageHeader(method.ordinal, flags)
|
| - data = header.Serialize()
|
| - (payload, handles) = struct.Serialize()
|
| - data.extend(payload)
|
| - return messaging.Message(data, handles, header)
|
| -
|
| -
|
| -def _StubInit(self, impl):
|
| - self.impl = impl
|
| -
|
| -
|
| -def _StubAccept(methods):
|
| - methods_by_ordinal = dict((m.ordinal, m) for m in methods)
|
| - def Accept(self, message, responder=None):
|
| - try:
|
| - header = message.header
|
| - assert header.expects_response == bool(responder)
|
| - assert header.message_type in methods_by_ordinal
|
| - method = methods_by_ordinal[header.message_type]
|
| - payload = message.payload
|
| - parameters = method.parameters_struct.Deserialize(
|
| - serialization.RootDeserializationContext(
|
| - payload.data, payload.handles)).AsDict()
|
| - response = getattr(self.impl, method.name)(**parameters)
|
| - if header.expects_response:
|
| - def SendResponse(response):
|
| - if isinstance(response, dict):
|
| - response_message = _GetMessage(method,
|
| - messaging.MESSAGE_IS_RESPONSE_FLAG,
|
| - **response)
|
| - else:
|
| - response_message = _GetMessage(method,
|
| - messaging.MESSAGE_IS_RESPONSE_FLAG,
|
| - response)
|
| - response_message.header.request_id = header.request_id
|
| - responder.Accept(response_message)
|
| - p = promise.Promise.Resolve(response).Then(SendResponse)
|
| - if self.impl.manager:
|
| - # Close the connection in case of error.
|
| - p.Catch(lambda _: self.impl.manager.Close())
|
| - return True
|
| - # pylint: disable=W0702
|
| - except:
|
| - # Close the connection in case of error.
|
| - logging.warning(
|
| - 'Error occured in accept method. Connection will be closed.')
|
| - if self.impl.manager:
|
| - self.impl.manager.Close()
|
| - return False
|
| - return Accept
|
| -
|
| -
|
| -def _NotImplemented(*_1, **_2):
|
| - raise NotImplementedError()
|
|
|