diff options
Diffstat (limited to 'mojo/public/python')
-rw-r--r-- | mojo/public/python/BUILD.gn | 96 | ||||
-rw-r--r-- | mojo/public/python/c_async_waiter.pxd | 28 | ||||
-rw-r--r-- | mojo/public/python/c_core.pxd | 201 | ||||
-rw-r--r-- | mojo/public/python/c_environment.pxd | 35 | ||||
-rw-r--r-- | mojo/public/python/c_export.pxd | 11 | ||||
-rw-r--r-- | mojo/public/python/c_thunks.pxd | 12 | ||||
-rw-r--r-- | mojo/public/python/mojo_bindings/__init__.py | 3 | ||||
-rw-r--r-- | mojo/public/python/mojo_bindings/descriptor.py | 696 | ||||
-rw-r--r-- | mojo/public/python/mojo_bindings/messaging.py | 407 | ||||
-rw-r--r-- | mojo/public/python/mojo_bindings/promise.py | 196 | ||||
-rw-r--r-- | mojo/public/python/mojo_bindings/reflection.py | 569 | ||||
-rw-r--r-- | mojo/public/python/mojo_bindings/serialization.py | 193 | ||||
-rw-r--r-- | mojo/public/python/mojo_system.pyx | 804 | ||||
-rw-r--r-- | mojo/public/python/mojo_system_impl.pyx | 75 | ||||
-rw-r--r-- | mojo/public/python/src/common.cc | 173 | ||||
-rw-r--r-- | mojo/public/python/src/common.h | 103 | ||||
-rw-r--r-- | mojo/public/python/src/python_system_helper.cc | 43 | ||||
-rw-r--r-- | mojo/public/python/src/python_system_helper.h | 30 |
18 files changed, 0 insertions, 3675 deletions
diff --git a/mojo/public/python/BUILD.gn b/mojo/public/python/BUILD.gn deleted file mode 100644 index 5b9c8ab..0000000 --- a/mojo/public/python/BUILD.gn +++ /dev/null @@ -1,96 +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. - -import("//third_party/cython/rules.gni") - -group("python") { - deps = [ - ":bindings", - ":mojo_system", - ":mojo_system_impl", - ] -} - -# GYP version: mojo.gyp:mojo_python_system -python_binary_module("mojo_system") { - configs = [ "../build/config:mojo_sdk" ] - deps = [ - ":system_embedded", - ] -} - -python_binary_source_set("system_embedded") { - cython_sources = [ - "c_async_waiter.pxd", - "c_core.pxd", - "c_export.pxd", - "c_thunks.pxd", - "mojo_system.pyx", - ] - configs = [ "../build/config:mojo_sdk" ] - deps = [ - "../c/system", - "../cpp/bindings:callback", - "../cpp/system", - "../cpp/utility", - "../platform/native:system", - ] -} - -python_binary_module("mojo_system_impl") { - cython_sources = [ - "c_environment.pxd", - "c_export.pxd", - "c_thunks.pxd", - "mojo_system_impl.pyx", - ] - sources = [ - "src/python_system_helper.cc", - "src/python_system_helper.h", - ] - configs = [ "../build/config:mojo_sdk" ] - deps = [ - ":python_common", - "../c/environment", - "../c/system", - "../cpp/bindings:callback", - "../cpp/environment:standalone", - "../cpp/system", - "../cpp/utility", - "../platform/native:system", - ] -} - -python_binary_source_set("python_common") { - sources = [ - "src/common.cc", - "src/common.h", - ] - configs = [ "../build/config:mojo_sdk" ] - deps = [ - "../c/environment:environment", - "../cpp/bindings:callback", - "../cpp/environment:environment", - "../cpp/system:system", - "../cpp/utility", - ] -} - -# GYP version: mojo.gyp:mojo_python_bindings -copy("bindings") { - sources = [ - "mojo_bindings/__init__.py", - "mojo_bindings/descriptor.py", - "mojo_bindings/messaging.py", - "mojo_bindings/promise.py", - "mojo_bindings/reflection.py", - "mojo_bindings/serialization.py", - ] - outputs = [ - "$root_out_dir/python/mojo_bindings/{{source_file_part}}", - ] - deps = [ - ":mojo_system", - ] -} diff --git a/mojo/public/python/c_async_waiter.pxd b/mojo/public/python/c_async_waiter.pxd deleted file mode 100644 index e2c3048..0000000 --- a/mojo/public/python/c_async_waiter.pxd +++ /dev/null @@ -1,28 +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. - -# distutils: language = c++ - -from libc.stdint cimport intptr_t, uint32_t, uint64_t - - -cdef extern from "mojo/public/c/system/core.h" nogil: - ctypedef uint32_t MojoHandle - ctypedef uint64_t MojoDeadline - ctypedef uint32_t MojoHandleSignals - - -cdef extern from "mojo/public/c/environment/async_waiter.h" nogil: - ctypedef intptr_t MojoAsyncWaitID - - -cdef extern from "mojo/public/python/src/common.h" \ - namespace "mojo::python" nogil: - cdef cppclass PythonAsyncWaiter "mojo::python::PythonAsyncWaiter": - PythonAsyncWaiter() - MojoAsyncWaitID AsyncWait(MojoHandle, - MojoHandleSignals, - MojoDeadline, - object) - void CancelWait(MojoAsyncWaitID) diff --git a/mojo/public/python/c_core.pxd b/mojo/public/python/c_core.pxd deleted file mode 100644 index bd3edd9..0000000 --- a/mojo/public/python/c_core.pxd +++ /dev/null @@ -1,201 +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. - -# distutils: language = c++ - -from cpython.buffer cimport PyBUF_CONTIG -from cpython.buffer cimport PyBUF_CONTIG_RO -from cpython.buffer cimport Py_buffer -from cpython.buffer cimport PyBuffer_FillInfo -from cpython.buffer cimport PyBuffer_Release -from cpython.buffer cimport PyObject_GetBuffer -from cpython.mem cimport PyMem_Malloc, PyMem_Free -from libc.stdint cimport int32_t, int64_t, uint32_t, uint64_t, uintptr_t - -cdef extern from "mojo/public/c/system/core.h" nogil: - # types.h - ctypedef int64_t MojoTimeTicks - - ctypedef uint32_t MojoHandle - const MojoHandle MOJO_HANDLE_INVALID - - ctypedef int32_t MojoResult - const MojoResult MOJO_RESULT_OK - const MojoResult MOJO_RESULT_CANCELLED - const MojoResult MOJO_RESULT_UNKNOWN - const MojoResult MOJO_RESULT_INVALID_ARGUMENT - const MojoResult MOJO_RESULT_DEADLINE_EXCEEDED - const MojoResult MOJO_RESULT_NOT_FOUND - const MojoResult MOJO_RESULT_ALREADY_EXISTS - const MojoResult MOJO_RESULT_PERMISSION_DENIED - const MojoResult MOJO_RESULT_RESOURCE_EXHAUSTED - const MojoResult MOJO_RESULT_FAILED_PRECONDITION - const MojoResult MOJO_RESULT_ABORTED - const MojoResult MOJO_RESULT_OUT_OF_RANGE - const MojoResult MOJO_RESULT_UNIMPLEMENTED - const MojoResult MOJO_RESULT_INTERNAL - const MojoResult MOJO_RESULT_UNAVAILABLE - const MojoResult MOJO_RESULT_DATA_LOSS - const MojoResult MOJO_RESULT_BUSY - const MojoResult MOJO_RESULT_SHOULD_WAIT - - ctypedef uint64_t MojoDeadline - const MojoDeadline MOJO_DEADLINE_INDEFINITE - - ctypedef uint32_t MojoHandleSignals - const MojoHandleSignals MOJO_HANDLE_SIGNAL_NONE - const MojoHandleSignals MOJO_HANDLE_SIGNAL_READABLE - const MojoHandleSignals MOJO_HANDLE_SIGNAL_WRITABLE - const MojoHandleSignals MOJO_HANDLE_SIGNAL_PEER_CLOSED - - cdef struct MojoHandleSignalsState: - MojoHandleSignals satisfied_signals - MojoHandleSignals satisfiable_signals - - # functions.h - MojoTimeTicks MojoGetTimeTicksNow() - MojoResult MojoClose(MojoHandle handle) - MojoResult MojoWait "MojoWait"(MojoHandle handle, - MojoHandleSignals signals, - MojoDeadline deadline, - MojoHandleSignalsState* signals_state) - MojoResult MojoWaitMany "MojoWaitMany"(const MojoHandle* handles, - const MojoHandleSignals* signals, - uint32_t num_handles, - MojoDeadline deadline, - uint32_t* result_index, - MojoHandleSignalsState* signals_states) - - # message_pipe.h - ctypedef uint32_t MojoCreateMessagePipeOptionsFlags - const MojoCreateMessagePipeOptionsFlags MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE - - ctypedef uint32_t MojoWriteMessageFlags - const MojoWriteMessageFlags MOJO_WRITE_MESSAGE_FLAG_NONE - - ctypedef uint32_t MojoReadMessageFlags - const MojoReadMessageFlags MOJO_READ_MESSAGE_FLAG_NONE - const MojoReadMessageFlags MOJO_READ_MESSAGE_FLAG_MAY_DISCARD - - cdef struct MojoCreateMessagePipeOptions: - uint32_t struct_size - MojoCreateMessagePipeOptionsFlags flags - - MojoResult MojoCreateMessagePipe( - const MojoCreateMessagePipeOptions* options, - MojoHandle* message_pipe_handle0, - MojoHandle* message_pipe_handle1) - - MojoResult MojoWriteMessage( - MojoHandle message_pipe_handle, - const void* bytes, - uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, - MojoWriteMessageFlags flags) - - MojoResult MojoReadMessage( - MojoHandle message_pipe_handle, - void* bytes, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoReadMessageFlags flags) - - # data_pipe.h - ctypedef uint32_t MojoCreateDataPipeOptionsFlags - const MojoCreateDataPipeOptionsFlags MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE - const MojoCreateDataPipeOptionsFlags MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD - - cdef struct MojoCreateDataPipeOptions: - uint32_t struct_size - MojoCreateDataPipeOptionsFlags flags - uint32_t element_num_bytes - uint32_t capacity_num_bytes - - ctypedef uint32_t MojoWriteDataFlags - - const MojoWriteDataFlags MOJO_WRITE_DATA_FLAG_NONE - const MojoWriteDataFlags MOJO_WRITE_DATA_FLAG_ALL_OR_NONE - - ctypedef uint32_t MojoReadDataFlags - - const MojoReadDataFlags MOJO_READ_DATA_FLAG_NONE - const MojoReadDataFlags MOJO_READ_DATA_FLAG_ALL_OR_NONE - const MojoReadDataFlags MOJO_READ_DATA_FLAG_DISCARD - const MojoReadDataFlags MOJO_READ_DATA_FLAG_QUERY - const MojoReadDataFlags MOJO_READ_DATA_FLAG_PEEK - - MojoResult MojoCreateDataPipe( - const MojoCreateDataPipeOptions* options, - MojoHandle* data_pipe_producer_handle, - MojoHandle* data_pipe_consumer_handle) - - MojoResult MojoWriteData( - MojoHandle data_pipe_producer_handle, - const void* elements, - uint32_t* num_bytes, - MojoWriteDataFlags flags) - - MojoResult MojoBeginWriteData( - MojoHandle data_pipe_producer_handle, - void** buffer, - uint32_t* buffer_num_bytes, - MojoWriteDataFlags flags) - - MojoResult MojoEndWriteData( - MojoHandle data_pipe_producer_handle, - uint32_t num_bytes_written) - - MojoResult MojoReadData( - MojoHandle data_pipe_consumer_handle, - void* elements, - uint32_t* num_bytes, - MojoReadDataFlags flags) - - MojoResult MojoBeginReadData( - MojoHandle data_pipe_consumer_handle, - const void** buffer, - uint32_t* buffer_num_bytes, - MojoReadDataFlags flags) - - MojoResult MojoEndReadData( - MojoHandle data_pipe_consumer_handle, - uint32_t num_bytes_read) - - # buffer.h - ctypedef uint32_t MojoCreateSharedBufferOptionsFlags - const MojoCreateSharedBufferOptionsFlags MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE - - cdef struct MojoCreateSharedBufferOptions: - uint32_t struct_size - MojoCreateSharedBufferOptionsFlags flags - - ctypedef uint32_t MojoDuplicateBufferHandleOptionsFlags - const MojoDuplicateBufferHandleOptionsFlags MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE - - cdef struct MojoDuplicateBufferHandleOptions: - uint32_t struct_size - MojoDuplicateBufferHandleOptionsFlags flags - - ctypedef uint32_t MojoMapBufferFlags - const MojoMapBufferFlags MOJO_MAP_BUFFER_FLAG_NONE - - MojoResult MojoCreateSharedBuffer( - const MojoCreateSharedBufferOptions* options, - uint64_t num_bytes, - MojoHandle* shared_buffer_handle) - - MojoResult MojoDuplicateBufferHandle( - MojoHandle buffer_handle, - const MojoDuplicateBufferHandleOptions* options, - MojoHandle* new_buffer_handle) - - MojoResult MojoMapBuffer(MojoHandle buffer_handle, - uint64_t offset, - uint64_t num_bytes, - void** buffer, - MojoMapBufferFlags flags) - - MojoResult MojoUnmapBuffer(void* buffer) diff --git a/mojo/public/python/c_environment.pxd b/mojo/public/python/c_environment.pxd deleted file mode 100644 index c1b37d6..0000000 --- a/mojo/public/python/c_environment.pxd +++ /dev/null @@ -1,35 +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. - -# distutils: language = c++ - -from libc.stdint cimport int64_t, intptr_t, uint32_t, uint64_t - -cimport c_async_waiter - - -cdef extern from "mojo/public/cpp/bindings/callback.h" nogil: - cdef cppclass CClosure "mojo::Callback<void()>": - CClosure() - - -cdef extern from "mojo/public/python/src/python_system_helper.h" \ - namespace "mojo::python" nogil: - cdef CClosure BuildClosure(object) - cdef c_async_waiter.PythonAsyncWaiter* NewAsyncWaiter() - - -cdef extern from "mojo/public/cpp/utility/run_loop.h" nogil: - cdef cppclass CRunLoop "mojo::RunLoop": - CRunLoop() - void Run() except * - void RunUntilIdle() except * - void Quit() - void PostDelayedTask(CClosure&, int64_t) - cdef CRunLoop CRunLoopCurrent "mojo::RunLoop::current"() - - -cdef extern from "mojo/public/cpp/environment/environment.h" nogil: - cdef cppclass CEnvironment "mojo::Environment": - CEnvironment() diff --git a/mojo/public/python/c_export.pxd b/mojo/public/python/c_export.pxd deleted file mode 100644 index 2e26118..0000000 --- a/mojo/public/python/c_export.pxd +++ /dev/null @@ -1,11 +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. - -# distutils: language = c++ - - -# If the definition below is not present, cython-compiled modules do not expose -# an init method as they should. -cdef extern from "third_party/cython/python_export.h": - pass diff --git a/mojo/public/python/c_thunks.pxd b/mojo/public/python/c_thunks.pxd deleted file mode 100644 index 61d9156..0000000 --- a/mojo/public/python/c_thunks.pxd +++ /dev/null @@ -1,12 +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. - -# distutils: language = c++ - - -cdef extern from "mojo/public/platform/native/system_thunks.h" nogil: - cdef struct MojoSystemThunks: - pass - -cdef extern size_t MojoSetSystemThunks(const MojoSystemThunks* system_thunks) diff --git a/mojo/public/python/mojo_bindings/__init__.py b/mojo/public/python/mojo_bindings/__init__.py deleted file mode 100644 index 4d6aabb..0000000 --- a/mojo/public/python/mojo_bindings/__init__.py +++ /dev/null @@ -1,3 +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. diff --git a/mojo/public/python/mojo_bindings/descriptor.py b/mojo/public/python/mojo_bindings/descriptor.py deleted file mode 100644 index 45e073f..0000000 --- a/mojo/public/python/mojo_bindings/descriptor.py +++ /dev/null @@ -1,696 +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 descriptors used to define generated elements of the mojo python bindings. -""" - -import array -import itertools -import struct - -import mojo_bindings.reflection as reflection -import mojo_bindings.serialization as serialization - -# pylint: disable=E0611,F0401 -import mojo_system - - -class Type(object): - """Describes the type of a struct field or a method parameter,""" - - def Convert(self, value): # pylint: disable=R0201 - """ - Convert the given value into its canonical representation, raising an - exception if the value cannot be converted. - """ - return value - - def GetDefaultValue(self, value): - """ - Returns the default value for this type associated with the given value. - This method must be able to correcly handle value being None. - """ - return self.Convert(value) - - -class SerializableType(Type): - """Describe a type that can be serialized by itself.""" - - def __init__(self, typecode): - Type.__init__(self) - self.typecode = typecode - self.byte_size = struct.calcsize('<%s' % self.GetTypeCode()) - - def GetTypeCode(self): - """ - Returns the type code (as defined by the struct module) used to encode - this type. - """ - return self.typecode - - def GetByteSize(self): - """ - Returns the size of the encoding of this type. - """ - return self.byte_size - - def Serialize(self, value, data_offset, data, handle_offset): - """ - Serialize a value of this type. - - Args: - value: the value to serialize. - data_offset: the offset to the end of the data bytearray. Used to encode - pointers. - data: the bytearray to append additional data to. - handle_offset: the offset to use to encode handles. - - Returns a a tuple where the first element is the value to encode, and the - second is the array of handles to add to the message. - """ - raise NotImplementedError() - - def Deserialize(self, value, context): - """ - Deserialize a value of this type. - - Args: - value: the base value for this type. This is always a numeric type, and - corresponds to the first element in the tuple returned by - Serialize. - data: the bytearray to retrieve additional data from. - handles: the array of handles contained in the message to deserialize. - - Returns the deserialized value. - """ - raise NotImplementedError() - - -class BooleanType(Type): - """Type object for booleans""" - - def Convert(self, value): - return bool(value) - - -class NumericType(SerializableType): - """Base Type object for all numeric types""" - - def GetDefaultValue(self, value): - if value is None: - return self.Convert(0) - return self.Convert(value) - - def Serialize(self, value, data_offset, data, handle_offset): - return (value, []) - - def Deserialize(self, value, context): - return value - - -class IntegerType(NumericType): - """Type object for integer types.""" - - def __init__(self, typecode): - NumericType.__init__(self, typecode) - size = 8 * self.byte_size - signed = typecode.islower() - if signed: - self._min_value = -(1 << (size - 1)) - self._max_value = (1 << (size - 1)) - 1 - else: - self._min_value = 0 - self._max_value = (1 << size) - 1 - - def Convert(self, value): - if value is None: - raise TypeError('None is not an integer.') - if not isinstance(value, (int, long)): - raise TypeError('%r is not an integer type' % value) - if value < self._min_value or value > self._max_value: - raise OverflowError('%r is not in the range [%d, %d]' % - (value, self._min_value, self._max_value)) - return value - - -class FloatType(NumericType): - """Type object for floating point number types.""" - - def Convert(self, value): - if value is None: - raise TypeError('None is not an floating point number.') - if not isinstance(value, (int, long, float)): - raise TypeError('%r is not a numeric type' % value) - return float(value) - - -class PointerType(SerializableType): - """Base Type object for pointers.""" - - def __init__(self, nullable=False): - SerializableType.__init__(self, 'Q') - self.nullable = nullable - - def Serialize(self, value, data_offset, data, handle_offset): - if value is None and not self.nullable: - raise serialization.SerializationException( - 'Trying to serialize null for non nullable type.') - if value is None: - return (0, []) - return self.SerializePointer(value, data_offset, data, handle_offset) - - def Deserialize(self, value, context): - if value == 0: - if not self.nullable: - raise serialization.DeserializationException( - 'Trying to deserialize null for non nullable type.') - return None - if value % 8 != 0: - raise serialization.DeserializationException( - 'Pointer alignment is incorrect.') - sub_context = context.GetSubContext(value) - if len(sub_context.data) < serialization.HEADER_STRUCT.size: - raise serialization.DeserializationException( - 'Available data too short to contain header.') - (size, nb_elements) = serialization.HEADER_STRUCT.unpack_from( - sub_context.data) - if len(sub_context.data) < size or size < serialization.HEADER_STRUCT.size: - raise serialization.DeserializationException('Header size is incorrect.') - sub_context.ClaimMemory(0, size) - return self.DeserializePointer(size, nb_elements, sub_context) - - def SerializePointer(self, value, data_offset, data, handle_offset): - """Serialize the not null value.""" - raise NotImplementedError() - - def DeserializePointer(self, size, nb_elements, context): - raise NotImplementedError() - - -class StringType(PointerType): - """ - Type object for strings. - - Strings are represented as unicode, and the conversion is done using the - default encoding if a string instance is used. - """ - - def __init__(self, nullable=False): - PointerType.__init__(self, nullable) - self._array_type = NativeArrayType('B', nullable) - - def Convert(self, value): - if value is None or isinstance(value, unicode): - return value - if isinstance(value, str): - return unicode(value) - raise TypeError('%r is not a string' % value) - - def SerializePointer(self, value, data_offset, data, handle_offset): - string_array = array.array('b') - string_array.fromstring(value.encode('utf8')) - return self._array_type.SerializeArray( - string_array, data_offset, data, handle_offset) - - def DeserializePointer(self, size, nb_elements, context): - string_array = self._array_type.DeserializeArray(size, nb_elements, context) - return unicode(string_array.tostring(), 'utf8') - - -class BaseHandleType(SerializableType): - """Type object for handles.""" - - def __init__(self, nullable=False): - SerializableType.__init__(self, 'i') - self.nullable = nullable - - def Serialize(self, value, data_offset, data, handle_offset): - handle = self.ToHandle(value) - if not handle.IsValid() and not self.nullable: - raise serialization.SerializationException( - 'Trying to serialize null for non nullable type.') - if not handle.IsValid(): - return (-1, []) - return (handle_offset, [handle]) - - def Deserialize(self, value, context): - if value == -1: - if not self.nullable: - raise serialization.DeserializationException( - 'Trying to deserialize null for non nullable type.') - return self.FromHandle(mojo_system.Handle()) - return self.FromHandle(context.ClaimHandle(value)) - - def FromHandle(self, handle): - raise NotImplementedError() - - def ToHandle(self, value): - raise NotImplementedError() - - -class HandleType(BaseHandleType): - """Type object for handles.""" - - def Convert(self, value): - if value is None: - return mojo_system.Handle() - if not isinstance(value, mojo_system.Handle): - raise TypeError('%r is not a handle' % value) - return value - - def FromHandle(self, handle): - return handle - - def ToHandle(self, value): - return value - - -class InterfaceRequestType(BaseHandleType): - """Type object for interface requests.""" - - def Convert(self, value): - if value is None: - return reflection.InterfaceRequest(mojo_system.Handle()) - if not isinstance(value, reflection.InterfaceRequest): - raise TypeError('%r is not an interface request' % value) - return value - - def FromHandle(self, handle): - return reflection.InterfaceRequest(handle) - - def ToHandle(self, value): - return value.PassMessagePipe() - - -class InterfaceType(BaseHandleType): - """Type object for interfaces.""" - - def __init__(self, interface_getter, nullable=False): - BaseHandleType.__init__(self, nullable) - self._interface_getter = interface_getter - self._interface = None - - def Convert(self, value): - if value is None or isinstance(value, self.interface): - return value - raise TypeError('%r is not an instance of ' % self.interface) - - @property - def interface(self): - if not self._interface: - self._interface = self._interface_getter() - return self._interface - - def FromHandle(self, handle): - if handle.IsValid(): - return self.interface.manager.Proxy(handle) - return None - - def ToHandle(self, value): - if not value: - return mojo_system.Handle() - if isinstance(value, reflection.InterfaceProxy): - return value.manager.PassMessagePipe() - pipe = mojo_system.MessagePipe() - self.interface.manager.Bind(value, pipe.handle0) - return pipe.handle1 - - -class BaseArrayType(PointerType): - """Abstract Type object for arrays.""" - - def __init__(self, nullable=False, length=0): - PointerType.__init__(self, nullable) - self.length = length - - def SerializePointer(self, value, data_offset, data, handle_offset): - if self.length != 0 and len(value) != self.length: - raise serialization.SerializationException('Incorrect array size') - return self.SerializeArray(value, data_offset, data, handle_offset) - - def SerializeArray(self, value, data_offset, data, handle_offset): - """Serialize the not null array.""" - raise NotImplementedError() - - def DeserializePointer(self, size, nb_elements, context): - if self.length != 0 and nb_elements != self.length: - raise serialization.DeserializationException('Incorrect array size') - if (size < - serialization.HEADER_STRUCT.size + self.SizeForLength(nb_elements)): - raise serialization.DeserializationException('Incorrect array size') - return self.DeserializeArray(size, nb_elements, context) - - def DeserializeArray(self, size, nb_elements, context): - raise NotImplementedError() - - def SizeForLength(self, nb_elements): - raise NotImplementedError() - - -class BooleanArrayType(BaseArrayType): - - def __init__(self, nullable=False, length=0): - BaseArrayType.__init__(self, nullable, length) - self._array_type = NativeArrayType('B', nullable) - - def Convert(self, value): - if value is None: - return value - return [TYPE_BOOL.Convert(x) for x in value] - - def SerializeArray(self, value, data_offset, data, handle_offset): - groups = [value[i:i+8] for i in range(0, len(value), 8)] - converted = array.array('B', [_ConvertBooleansToByte(x) for x in groups]) - return _SerializeNativeArray(converted, data_offset, data, len(value)) - - def DeserializeArray(self, size, nb_elements, context): - converted = self._array_type.DeserializeArray(size, nb_elements, context) - elements = list(itertools.islice( - itertools.chain.from_iterable( - [_ConvertByteToBooleans(x, 8) for x in converted]), - 0, - nb_elements)) - return elements - - def SizeForLength(self, nb_elements): - return (nb_elements + 7) // 8 - - -class GenericArrayType(BaseArrayType): - """Type object for arrays of pointers.""" - - def __init__(self, sub_type, nullable=False, length=0): - BaseArrayType.__init__(self, nullable, length) - assert isinstance(sub_type, SerializableType) - self.sub_type = sub_type - - def Convert(self, value): - if value is None: - return value - return [self.sub_type.Convert(x) for x in value] - - def SerializeArray(self, value, data_offset, data, handle_offset): - size = (serialization.HEADER_STRUCT.size + - self.sub_type.GetByteSize() * len(value)) - data_end = len(data) - position = len(data) + serialization.HEADER_STRUCT.size - data.extend(bytearray(size + - serialization.NeededPaddingForAlignment(size))) - returned_handles = [] - to_pack = [] - for item in value: - (new_data, new_handles) = self.sub_type.Serialize( - item, - len(data) - position, - data, - handle_offset + len(returned_handles)) - to_pack.append(new_data) - returned_handles.extend(new_handles) - position = position + self.sub_type.GetByteSize() - serialization.HEADER_STRUCT.pack_into(data, data_end, size, len(value)) - struct.pack_into('%d%s' % (len(value), self.sub_type.GetTypeCode()), - data, - data_end + serialization.HEADER_STRUCT.size, - *to_pack) - return (data_offset, returned_handles) - - def DeserializeArray(self, size, nb_elements, context): - values = struct.unpack_from( - '%d%s' % (nb_elements, self.sub_type.GetTypeCode()), - buffer(context.data, serialization.HEADER_STRUCT.size)) - result = [] - sub_context = context.GetSubContext(serialization.HEADER_STRUCT.size) - for value in values: - result.append(self.sub_type.Deserialize( - value, - sub_context)) - sub_context = sub_context.GetSubContext(self.sub_type.GetByteSize()) - return result - - def SizeForLength(self, nb_elements): - return nb_elements * self.sub_type.GetByteSize(); - - -class NativeArrayType(BaseArrayType): - """Type object for arrays of native types.""" - - def __init__(self, typecode, nullable=False, length=0): - BaseArrayType.__init__(self, nullable, length) - self.array_typecode = typecode - self.element_size = struct.calcsize('<%s' % self.array_typecode) - - def Convert(self, value): - if value is None: - return value - if (isinstance(value, array.array) and - value.array_typecode == self.array_typecode): - return value - return array.array(self.array_typecode, value) - - def SerializeArray(self, value, data_offset, data, handle_offset): - return _SerializeNativeArray(value, data_offset, data, len(value)) - - def DeserializeArray(self, size, nb_elements, context): - result = array.array(self.array_typecode) - result.fromstring(buffer(context.data, - serialization.HEADER_STRUCT.size, - size - serialization.HEADER_STRUCT.size)) - return result - - def SizeForLength(self, nb_elements): - return nb_elements * self.element_size - - -class StructType(PointerType): - """Type object for structs.""" - - def __init__(self, struct_type_getter, nullable=False): - PointerType.__init__(self) - self._struct_type_getter = struct_type_getter - self._struct_type = None - self.nullable = nullable - - @property - def struct_type(self): - if not self._struct_type: - self._struct_type = self._struct_type_getter() - return self._struct_type - - def Convert(self, value): - if value is None or isinstance(value, self.struct_type): - return value - raise TypeError('%r is not an instance of %r' % (value, self.struct_type)) - - def GetDefaultValue(self, value): - if value: - return self.struct_type() - return None - - def SerializePointer(self, value, data_offset, data, handle_offset): - (new_data, new_handles) = value.Serialize(handle_offset) - data.extend(new_data) - return (data_offset, new_handles) - - def DeserializePointer(self, size, nb_elements, context): - return self.struct_type.Deserialize(context) - - -class MapType(SerializableType): - """Type objects for maps.""" - - def __init__(self, key_type, value_type, nullable=False): - self._key_type = key_type - self._value_type = value_type - dictionary = { - '__metaclass__': reflection.MojoStructType, - '__module__': __name__, - 'DESCRIPTOR': { - 'fields': [ - SingleFieldGroup('keys', MapType._GetArrayType(key_type), 0, 0), - SingleFieldGroup('values', MapType._GetArrayType(value_type), 1, 1), - ], - } - } - self.struct = reflection.MojoStructType('MapStruct', (object,), dictionary) - self.struct_type = StructType(lambda: self.struct, nullable) - SerializableType.__init__(self, self.struct_type.typecode) - - def Convert(self, value): - if value is None: - return value - if isinstance(value, dict): - return dict([(self._key_type.Convert(x), self._value_type.Convert(y)) for - x, y in value.iteritems()]) - raise TypeError('%r is not a dictionary.') - - def Serialize(self, value, data_offset, data, handle_offset): - s = None - if value: - keys, values = [], [] - for key, value in value.iteritems(): - keys.append(key) - values.append(value) - s = self.struct(keys=keys, values=values) - return self.struct_type.Serialize(s, data_offset, data, handle_offset) - - def Deserialize(self, value, context): - s = self.struct_type.Deserialize(value, context) - if s: - if len(s.keys) != len(s.values): - raise serialization.DeserializationException( - 'keys and values do not have the same length.') - return dict(zip(s.keys, s.values)) - return None - - @staticmethod - def _GetArrayType(t): - if t == TYPE_BOOL: - return BooleanArrayType() - else: - return GenericArrayType(t) - - -TYPE_BOOL = BooleanType() - -TYPE_INT8 = IntegerType('b') -TYPE_INT16 = IntegerType('h') -TYPE_INT32 = IntegerType('i') -TYPE_INT64 = IntegerType('q') - -TYPE_UINT8 = IntegerType('B') -TYPE_UINT16 = IntegerType('H') -TYPE_UINT32 = IntegerType('I') -TYPE_UINT64 = IntegerType('Q') - -TYPE_FLOAT = FloatType('f') -TYPE_DOUBLE = FloatType('d') - -TYPE_STRING = StringType() -TYPE_NULLABLE_STRING = StringType(True) - -TYPE_HANDLE = HandleType() -TYPE_NULLABLE_HANDLE = HandleType(True) - -TYPE_INTERFACE_REQUEST = InterfaceRequestType() -TYPE_NULLABLE_INTERFACE_REQUEST = InterfaceRequestType(True) - - -class FieldDescriptor(object): - """Describes a field in a generated struct.""" - - def __init__(self, name, field_type, index, version, default_value=None): - self.name = name - self.field_type = field_type - self.version = version - self.index = index - self._default_value = default_value - - def GetDefaultValue(self): - return self.field_type.GetDefaultValue(self._default_value) - - -class FieldGroup(object): - """ - Describe a list of field in the generated struct that must be - serialized/deserialized together. - """ - def __init__(self, descriptors): - self.descriptors = descriptors - - def GetDescriptors(self): - return self.descriptors - - def GetTypeCode(self): - raise NotImplementedError() - - def GetByteSize(self): - raise NotImplementedError() - - def GetVersion(self): - raise NotImplementedError() - - def Serialize(self, obj, data_offset, data, handle_offset): - raise NotImplementedError() - - def Deserialize(self, value, context): - raise NotImplementedError() - - -class SingleFieldGroup(FieldGroup, FieldDescriptor): - """A FieldGroup that contains a single FieldDescriptor.""" - - def __init__(self, name, field_type, index, version, default_value=None): - FieldDescriptor.__init__( - self, name, field_type, index, version, default_value) - FieldGroup.__init__(self, [self]) - - def GetTypeCode(self): - return self.field_type.GetTypeCode() - - def GetByteSize(self): - return self.field_type.GetByteSize() - - def GetVersion(self): - return self.version - - def Serialize(self, obj, data_offset, data, handle_offset): - value = getattr(obj, self.name) - return self.field_type.Serialize(value, data_offset, data, handle_offset) - - def Deserialize(self, value, context): - entity = self.field_type.Deserialize(value, context) - return { self.name: entity } - - -class BooleanGroup(FieldGroup): - """A FieldGroup to pack booleans.""" - def __init__(self, descriptors): - FieldGroup.__init__(self, descriptors) - self.version = min([descriptor.version for descriptor in descriptors]) - - def GetTypeCode(self): - return 'B' - - def GetByteSize(self): - return 1 - - def GetVersion(self): - return self.version - - def Serialize(self, obj, data_offset, data, handle_offset): - value = _ConvertBooleansToByte( - [getattr(obj, field.name) for field in self.GetDescriptors()]) - return (value, []) - - def Deserialize(self, value, context): - values = itertools.izip_longest([x.name for x in self.descriptors], - _ConvertByteToBooleans(value), - fillvalue=False) - return dict(values) - - -def _SerializeNativeArray(value, data_offset, data, length): - data_size = len(data) - data.extend(bytearray(serialization.HEADER_STRUCT.size)) - data.extend(buffer(value)) - data_length = len(data) - data_size - data.extend(bytearray(serialization.NeededPaddingForAlignment(data_length))) - serialization.HEADER_STRUCT.pack_into(data, data_size, data_length, length) - return (data_offset, []) - - -def _ConvertBooleansToByte(booleans): - """Pack a list of booleans into an integer.""" - return reduce(lambda x, y: x * 2 + y, reversed(booleans), 0) - - -def _ConvertByteToBooleans(value, min_size=0): - """Unpack an integer into a list of booleans.""" - res = [] - while value: - res.append(bool(value&1)) - value = value / 2 - res.extend([False] * (min_size - len(res))) - return res diff --git a/mojo/public/python/mojo_bindings/messaging.py b/mojo/public/python/mojo_bindings/messaging.py deleted file mode 100644 index 385a080..0000000 --- a/mojo/public/python/mojo_bindings/messaging.py +++ /dev/null @@ -1,407 +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. - -"""Utility classes to handle sending and receiving messages.""" - - -import struct -import sys -import weakref - -import mojo_bindings.serialization as serialization - -# pylint: disable=E0611,F0401 -import mojo_system as system - - -# The flag values for a message header. -NO_FLAG = 0 -MESSAGE_EXPECTS_RESPONSE_FLAG = 1 << 0 -MESSAGE_IS_RESPONSE_FLAG = 1 << 1 - - -class MessagingException(Exception): - def __init__(self, *args, **kwargs): - Exception.__init__(self, *args, **kwargs) - self.__traceback__ = sys.exc_info()[2] - - -class MessageHeader(object): - """The header of a mojo message.""" - - _SIMPLE_MESSAGE_NUM_FIELDS = 2 - _SIMPLE_MESSAGE_STRUCT = struct.Struct("<IIII") - - _REQUEST_ID_STRUCT = struct.Struct("<Q") - _REQUEST_ID_OFFSET = _SIMPLE_MESSAGE_STRUCT.size - - _MESSAGE_WITH_REQUEST_ID_NUM_FIELDS = 3 - _MESSAGE_WITH_REQUEST_ID_SIZE = ( - _SIMPLE_MESSAGE_STRUCT.size + _REQUEST_ID_STRUCT.size) - - def __init__(self, message_type, flags, request_id=0, data=None): - self._message_type = message_type - self._flags = flags - self._request_id = request_id - self._data = data - - @classmethod - def Deserialize(cls, data): - buf = buffer(data) - if len(data) < cls._SIMPLE_MESSAGE_STRUCT.size: - raise serialization.DeserializationException('Header is too short.') - (size, version, message_type, flags) = ( - cls._SIMPLE_MESSAGE_STRUCT.unpack_from(buf)) - if (version < cls._SIMPLE_MESSAGE_NUM_FIELDS): - raise serialization.DeserializationException('Incorrect version.') - request_id = 0 - if _HasRequestId(flags): - if version < cls._MESSAGE_WITH_REQUEST_ID_NUM_FIELDS: - raise serialization.DeserializationException('Incorrect version.') - if (size < cls._MESSAGE_WITH_REQUEST_ID_SIZE or - len(data) < cls._MESSAGE_WITH_REQUEST_ID_SIZE): - raise serialization.DeserializationException('Header is too short.') - (request_id, ) = cls._REQUEST_ID_STRUCT.unpack_from( - buf, cls._REQUEST_ID_OFFSET) - return MessageHeader(message_type, flags, request_id, data) - - @property - def message_type(self): - return self._message_type - - # pylint: disable=E0202 - @property - def request_id(self): - assert self.has_request_id - return self._request_id - - # pylint: disable=E0202 - @request_id.setter - def request_id(self, request_id): - assert self.has_request_id - self._request_id = request_id - self._REQUEST_ID_STRUCT.pack_into(self._data, self._REQUEST_ID_OFFSET, - request_id) - - @property - def has_request_id(self): - return _HasRequestId(self._flags) - - @property - def expects_response(self): - return self._HasFlag(MESSAGE_EXPECTS_RESPONSE_FLAG) - - @property - def is_response(self): - return self._HasFlag(MESSAGE_IS_RESPONSE_FLAG) - - @property - def size(self): - if self.has_request_id: - return self._MESSAGE_WITH_REQUEST_ID_SIZE - return self._SIMPLE_MESSAGE_STRUCT.size - - def Serialize(self): - if not self._data: - self._data = bytearray(self.size) - version = self._SIMPLE_MESSAGE_NUM_FIELDS - size = self._SIMPLE_MESSAGE_STRUCT.size - if self.has_request_id: - version = self._MESSAGE_WITH_REQUEST_ID_NUM_FIELDS - size = self._MESSAGE_WITH_REQUEST_ID_SIZE - self._SIMPLE_MESSAGE_STRUCT.pack_into(self._data, 0, size, version, - self._message_type, self._flags) - if self.has_request_id: - self._REQUEST_ID_STRUCT.pack_into(self._data, self._REQUEST_ID_OFFSET, - self._request_id) - return self._data - - def _HasFlag(self, flag): - return self._flags & flag != 0 - - -class Message(object): - """A message for a message pipe. This contains data and handles.""" - - def __init__(self, data=None, handles=None, header=None): - self.data = data - self.handles = handles - self._header = header - self._payload = None - - @property - def header(self): - if self._header is None: - self._header = MessageHeader.Deserialize(self.data) - return self._header - - @property - def payload(self): - if self._payload is None: - self._payload = Message(self.data[self.header.size:], self.handles) - return self._payload - - def SetRequestId(self, request_id): - header = self.header - header.request_id = request_id - (data, _) = header.Serialize() - self.data[:header.Size] = data[:header.Size] - - -class MessageReceiver(object): - """A class which implements this interface can receive Message objects.""" - - def Accept(self, message): - """ - Receive a Message. The MessageReceiver is allowed to mutate the message. - - Args: - message: the received message. - - Returns: - True if the message has been handled, False otherwise. - """ - raise NotImplementedError() - - -class MessageReceiverWithResponder(MessageReceiver): - """ - A MessageReceiver that can also handle the response message generated from the - given message. - """ - - def AcceptWithResponder(self, message, responder): - """ - A variant on Accept that registers a MessageReceiver (known as the - responder) to handle the response message generated from the given message. - The responder's Accept method may be called as part of the call to - AcceptWithResponder, or some time after its return. - - Args: - message: the received message. - responder: the responder that will receive the response. - - Returns: - True if the message has been handled, False otherwise. - """ - raise NotImplementedError() - - -class ConnectionErrorHandler(object): - """ - A ConnectionErrorHandler is notified of an error happening while using the - bindings over message pipes. - """ - - def OnError(self, result): - raise NotImplementedError() - - -class Connector(MessageReceiver): - """ - A Connector owns a message pipe and will send any received messages to the - registered MessageReceiver. It also acts as a MessageReceiver and will send - any message through the handle. - - The method Start must be called before the Connector will start listening to - incoming messages. - """ - - def __init__(self, handle): - MessageReceiver.__init__(self) - self._handle = handle - self._cancellable = None - self._incoming_message_receiver = None - self._error_handler = None - - def __del__(self): - if self._cancellable: - self._cancellable() - - def SetIncomingMessageReceiver(self, message_receiver): - """ - Set the MessageReceiver that will receive message from the owned message - pipe. - """ - self._incoming_message_receiver = message_receiver - - def SetErrorHandler(self, error_handler): - """ - Set the ConnectionErrorHandler that will be notified of errors on the owned - message pipe. - """ - self._error_handler = error_handler - - def Start(self): - assert not self._cancellable - self._RegisterAsyncWaiterForRead() - - def Accept(self, message): - result = self._handle.WriteMessage(message.data, message.handles) - return result == system.RESULT_OK - - def Close(self): - if self._cancellable: - self._cancellable() - self._cancellable = None - self._handle.Close() - - def PassMessagePipe(self): - if self._cancellable: - self._cancellable() - self._cancellable = None - result = self._handle - self._handle = system.Handle() - return result - - def _OnAsyncWaiterResult(self, result): - self._cancellable = None - if result == system.RESULT_OK: - self._ReadOutstandingMessages() - else: - self._OnError(result) - - def _OnError(self, result): - assert not self._cancellable - if self._error_handler: - self._error_handler.OnError(result) - self._handle.Close() - - def _RegisterAsyncWaiterForRead(self) : - assert not self._cancellable - self._cancellable = self._handle.AsyncWait( - system.HANDLE_SIGNAL_READABLE, - system.DEADLINE_INDEFINITE, - _WeakCallback(self._OnAsyncWaiterResult)) - - def _ReadOutstandingMessages(self): - result = system.RESULT_OK - while result == system.RESULT_OK: - result = _ReadAndDispatchMessage(self._handle, - self._incoming_message_receiver) - if result == system.RESULT_SHOULD_WAIT: - self._RegisterAsyncWaiterForRead() - return - self._OnError(result) - - -class Router(MessageReceiverWithResponder): - """ - A Router will handle mojo message and forward those to a Connector. It deals - with parsing of headers and adding of request ids in order to be able to match - a response to a request. - """ - - def __init__(self, handle): - MessageReceiverWithResponder.__init__(self) - self._incoming_message_receiver = None - self._next_request_id = 1 - self._responders = {} - self._connector = Connector(handle) - self._connector.SetIncomingMessageReceiver( - ForwardingMessageReceiver(_WeakCallback(self._HandleIncomingMessage))) - - def Start(self): - self._connector.Start() - - def SetIncomingMessageReceiver(self, message_receiver): - """ - Set the MessageReceiver that will receive message from the owned message - pipe. - """ - self._incoming_message_receiver = message_receiver - - def SetErrorHandler(self, error_handler): - """ - Set the ConnectionErrorHandler that will be notified of errors on the owned - message pipe. - """ - self._connector.SetErrorHandler(error_handler) - - def Accept(self, message): - # A message without responder is directly forwarded to the connector. - return self._connector.Accept(message) - - def AcceptWithResponder(self, message, responder): - # The message must have a header. - header = message.header - assert header.expects_response - request_id = self._NextRequestId() - header.request_id = request_id - if not self._connector.Accept(message): - return False - self._responders[request_id] = responder - return True - - def Close(self): - self._connector.Close() - - def PassMessagePipe(self): - return self._connector.PassMessagePipe() - - def _HandleIncomingMessage(self, message): - header = message.header - if header.expects_response: - if self._incoming_message_receiver: - return self._incoming_message_receiver.AcceptWithResponder( - message, self) - # If we receive a request expecting a response when the client is not - # listening, then we have no choice but to tear down the pipe. - self.Close() - return False - if header.is_response: - request_id = header.request_id - responder = self._responders.pop(request_id, None) - if responder is None: - return False - return responder.Accept(message) - if self._incoming_message_receiver: - return self._incoming_message_receiver.Accept(message) - # Ok to drop the message - return False - - def _NextRequestId(self): - request_id = self._next_request_id - while request_id == 0 or request_id in self._responders: - request_id = (request_id + 1) % (1 << 64) - self._next_request_id = (request_id + 1) % (1 << 64) - return request_id - -class ForwardingMessageReceiver(MessageReceiver): - """A MessageReceiver that forward calls to |Accept| to a callable.""" - - def __init__(self, callback): - MessageReceiver.__init__(self) - self._callback = callback - - def Accept(self, message): - return self._callback(message) - - -def _WeakCallback(callback): - func = callback.im_func - self = callback.im_self - if not self: - return callback - weak_self = weakref.ref(self) - def Callback(*args, **kwargs): - self = weak_self() - if self: - return func(self, *args, **kwargs) - return Callback - - -def _ReadAndDispatchMessage(handle, message_receiver): - (result, _, sizes) = handle.ReadMessage() - if result == system.RESULT_OK and message_receiver: - message_receiver.Accept(Message(bytearray(), [])) - if result != system.RESULT_RESOURCE_EXHAUSTED: - return result - (result, data, _) = handle.ReadMessage(bytearray(sizes[0]), sizes[1]) - if result == system.RESULT_OK and message_receiver: - message_receiver.Accept(Message(data[0], data[1])) - return result - -def _HasRequestId(flags): - return flags & (MESSAGE_EXPECTS_RESPONSE_FLAG|MESSAGE_IS_RESPONSE_FLAG) != 0 diff --git a/mojo/public/python/mojo_bindings/promise.py b/mojo/public/python/mojo_bindings/promise.py deleted file mode 100644 index ebf6f85..0000000 --- a/mojo/public/python/mojo_bindings/promise.py +++ /dev/null @@ -1,196 +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. - -""" -Promise used by the python bindings. - -The API is following the ECMAScript 6 API for promises. -""" - -import sys - - -class Promise(object): - """The promise object.""" - - STATE_PENDING = 0 - STATE_FULLFILLED = 1 - STATE_REJECTED = 2 - STATE_BOUND = 3 - - def __init__(self, generator_function): - """ - Constructor. - - Args: - generator_function: A function taking 2 arguments: resolve and reject. - When |resolve| is called, the promise is fullfilled with the given value. - When |reject| is called, the promise is rejected with the given value. - A promise can only be resolved or rejected once, all following calls will - have no effect. - """ - self._onCatched = [] - self._onFulfilled = [] - self._onRejected = [] - self._state = Promise.STATE_PENDING - self._result = None - try: - generator_function(self._Resolve, self._Reject) - except Exception as e: - # Adding traceback similarly to python 3.0 (pep-3134) - e.__traceback__ = sys.exc_info()[2] - self._Reject(e) - - @staticmethod - def Resolve(value): - """ - If value is a promise, make a promise that have the same behavior as value, - otherwise make a promise that fulfills to value. - """ - if isinstance(value, Promise): - return value - return Promise(lambda x, y: x(value)) - - @staticmethod - def Reject(reason): - "Make a promise that rejects to reason.""" - return Promise(lambda x, y: y(reason)) - - @staticmethod - def All(*iterable): - """ - Make a promise that fulfills when every item in the array fulfills, and - rejects if (and when) any item rejects. Each array item is passed to - Promise.resolve, so the array can be a mixture of promise-like objects and - other objects. The fulfillment value is an array (in order) of fulfillment - values. The rejection value is the first rejection value. - """ - def GeneratorFunction(resolve, reject): - state = { - 'rejected': False, - 'nb_resolved': 0, - } - promises = [Promise.Resolve(x) for x in iterable] - results = [None for x in promises] - def OnFullfilled(i): - def OnFullfilled(res): - if state['rejected']: - return - results[i] = res - state['nb_resolved'] = state['nb_resolved'] + 1 - if state['nb_resolved'] == len(results): - resolve(results) - return OnFullfilled - def OnRejected(reason): - if state['rejected']: - return - state['rejected'] = True - reject(reason) - - for (i, promise) in enumerate(promises): - promise.Then(OnFullfilled(i), OnRejected) - return Promise(GeneratorFunction) - - @staticmethod - def Race(*iterable): - """ - Make a Promise that fulfills as soon as any item fulfills, or rejects as - soon as any item rejects, whichever happens first. - """ - def GeneratorFunction(resolve, reject): - state = { - 'ended': False - } - def OnEvent(callback): - def OnEvent(res): - if state['ended']: - return - state['ended'] = True - callback(res) - return OnEvent - for promise in [Promise.Resolve(x) for x in iterable]: - promise.Then(OnEvent(resolve), OnEvent(reject)) - return Promise(GeneratorFunction) - - @property - def state(self): - if isinstance(self._result, Promise): - return self._result.state - return self._state - - def Then(self, onFullfilled=None, onRejected=None): - """ - onFulfilled is called when/if this promise resolves. onRejected is called - when/if this promise rejects. Both are optional, if either/both are omitted - the next onFulfilled/onRejected in the chain is called. Both callbacks have - a single parameter, the fulfillment value or rejection reason. |Then| - returns a new promise equivalent to the value you return from - onFulfilled/onRejected after being passed through Resolve. If an - error is thrown in the callback, the returned promise rejects with that - error. - """ - if isinstance(self._result, Promise): - return self._result.Then(onFullfilled, onRejected) - def GeneratorFunction(resolve, reject): - if self._state == Promise.STATE_PENDING: - self._onFulfilled.append(_Delegate(resolve, reject, onFullfilled)) - self._onRejected.append(_Delegate(reject, reject, onRejected)) - if self._state == self.STATE_FULLFILLED: - _Delegate(resolve, reject, onFullfilled)(self._result) - if self._state == self.STATE_REJECTED: - recover = reject - if onRejected: - recover = resolve - _Delegate(recover, reject, onRejected)(self._result) - return Promise(GeneratorFunction) - - def Catch(self, onCatched): - """Equivalent to |Then(None, onCatched)|""" - return self.Then(None, onCatched) - - def _Resolve(self, value): - if self.state != Promise.STATE_PENDING: - return - self._result = value - if isinstance(value, Promise): - self._state = Promise.STATE_BOUND - self._result.Then(_IterateAction(self._onFulfilled), - _IterateAction(self._onRejected)) - return - self._state = Promise.STATE_FULLFILLED - for f in self._onFulfilled: - f(value) - self._onFulfilled = None - self._onRejected = None - - def _Reject(self, reason): - if self.state != Promise.STATE_PENDING: - return - self._result = reason - self._state = Promise.STATE_REJECTED - for f in self._onRejected: - f(reason) - self._onFulfilled = None - self._onRejected = None - - -def _IterateAction(iterable): - def _Run(x): - for f in iterable: - f(x) - return _Run - - -def _Delegate(resolve, reject, action): - def _Run(x): - try: - if action: - resolve(action(x)) - else: - resolve(x) - except Exception as e: - # Adding traceback similarly to python 3.0 (pep-3134) - e.__traceback__ = sys.exc_info()[2] - reject(e) - return _Run diff --git a/mojo/public/python/mojo_bindings/reflection.py b/mojo/public/python/mojo_bindings/reflection.py deleted file mode 100644 index 5432691..0000000 --- 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() diff --git a/mojo/public/python/mojo_bindings/serialization.py b/mojo/public/python/mojo_bindings/serialization.py deleted file mode 100644 index b5ea1bd..0000000 --- a/mojo/public/python/mojo_bindings/serialization.py +++ /dev/null @@ -1,193 +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. - -"""Utility classes for serialization""" - -import struct - - -# Format of a header for a struct or an array. -HEADER_STRUCT = struct.Struct("<II") - - -class SerializationException(Exception): - """Error when strying to serialize a struct.""" - pass - - -class DeserializationException(Exception): - """Error when strying to deserialize a struct.""" - pass - - -class DeserializationContext(object): - - def ClaimHandle(self, handle): - raise NotImplementedError() - - def ClaimMemory(self, start, size): - raise NotImplementedError() - - def GetSubContext(self, offset): - raise NotImplementedError() - - def IsInitialContext(self): - raise NotImplementedError() - - -class RootDeserializationContext(DeserializationContext): - def __init__(self, data, handles): - if isinstance(data, buffer): - self.data = data - else: - self.data = buffer(data) - self._handles = handles - self._next_handle = 0; - self._next_memory = 0; - - def ClaimHandle(self, handle): - if handle < self._next_handle: - raise DeserializationException('Accessing handles out of order.') - self._next_handle = handle + 1 - return self._handles[handle] - - def ClaimMemory(self, start, size): - if start < self._next_memory: - raise DeserializationException('Accessing buffer out of order.') - self._next_memory = start + size - - def GetSubContext(self, offset): - return _ChildDeserializationContext(self, offset) - - def IsInitialContext(self): - return True - - -class _ChildDeserializationContext(DeserializationContext): - def __init__(self, parent, offset): - self._parent = parent - self._offset = offset - self.data = buffer(parent.data, offset) - - def ClaimHandle(self, handle): - return self._parent.ClaimHandle(handle) - - def ClaimMemory(self, start, size): - return self._parent.ClaimMemory(self._offset + start, size) - - def GetSubContext(self, offset): - return self._parent.GetSubContext(self._offset + offset) - - def IsInitialContext(self): - return False - - -class Serialization(object): - """ - Helper class to serialize/deserialize a struct. - """ - def __init__(self, groups): - self.version = _GetVersion(groups) - self._groups = groups - main_struct = _GetStruct(groups) - self.size = HEADER_STRUCT.size + main_struct.size - self._struct_per_version = { - self.version: main_struct, - } - self._groups_per_version = { - self.version: groups, - } - - def _GetMainStruct(self): - return self._GetStruct(self.version) - - def _GetGroups(self, version): - # If asking for a version greater than the last known. - version = min(version, self.version) - if version not in self._groups_per_version: - self._groups_per_version[version] = _FilterGroups(self._groups, version) - return self._groups_per_version[version] - - def _GetStruct(self, version): - # If asking for a version greater than the last known. - version = min(version, self.version) - if version not in self._struct_per_version: - self._struct_per_version[version] = _GetStruct(self._GetGroups(version)) - return self._struct_per_version[version] - - def Serialize(self, obj, handle_offset): - """ - Serialize the given obj. handle_offset is the the first value to use when - encoding handles. - """ - handles = [] - data = bytearray(self.size) - HEADER_STRUCT.pack_into(data, 0, self.size, self.version) - position = HEADER_STRUCT.size - to_pack = [] - for group in self._groups: - position = position + NeededPaddingForAlignment(position, - group.GetByteSize()) - (entry, new_handles) = group.Serialize( - obj, - len(data) - position, - data, - handle_offset + len(handles)) - to_pack.append(entry) - handles.extend(new_handles) - position = position + group.GetByteSize() - self._GetMainStruct().pack_into(data, HEADER_STRUCT.size, *to_pack) - return (data, handles) - - def Deserialize(self, fields, context): - if len(context.data) < HEADER_STRUCT.size: - raise DeserializationException( - 'Available data too short to contain header.') - (size, version) = HEADER_STRUCT.unpack_from(context.data) - if len(context.data) < size or size < HEADER_STRUCT.size: - raise DeserializationException('Header size is incorrect.') - if context.IsInitialContext(): - context.ClaimMemory(0, size) - version_struct = self._GetStruct(version) - entitities = version_struct.unpack_from(context.data, HEADER_STRUCT.size) - filtered_groups = self._GetGroups(version) - position = HEADER_STRUCT.size - for (group, value) in zip(filtered_groups, entitities): - position = position + NeededPaddingForAlignment(position, - group.GetByteSize()) - fields.update(group.Deserialize(value, context.GetSubContext(position))) - position += group.GetByteSize() - - -def NeededPaddingForAlignment(value, alignment=8): - """Returns the padding necessary to align value with the given alignment.""" - if value % alignment: - return alignment - (value % alignment) - return 0 - - -def _GetVersion(groups): - return sum([len(x.descriptors) for x in groups]) - - -def _FilterGroups(groups, version): - return [group for group in groups if group.GetVersion() < version] - - -def _GetStruct(groups): - index = 0 - codes = [ '<' ] - for group in groups: - code = group.GetTypeCode() - size = group.GetByteSize() - needed_padding = NeededPaddingForAlignment(index, size) - if needed_padding: - codes.append('x' * needed_padding) - index = index + needed_padding - codes.append(code) - index = index + size - alignment_needed = NeededPaddingForAlignment(index) - if alignment_needed: - codes.append('x' * alignment_needed) - return struct.Struct(''.join(codes)) diff --git a/mojo/public/python/mojo_system.pyx b/mojo/public/python/mojo_system.pyx deleted file mode 100644 index 4e684af..0000000 --- a/mojo/public/python/mojo_system.pyx +++ /dev/null @@ -1,804 +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. - -# distutils language = c++ - -cimport c_core -cimport c_export # needed so the init function gets exported -cimport c_thunks - - -from cpython.buffer cimport PyBUF_CONTIG -from cpython.buffer cimport PyBUF_CONTIG_RO -from cpython.buffer cimport Py_buffer -from cpython.buffer cimport PyBuffer_FillInfo -from cpython.buffer cimport PyBuffer_Release -from cpython.buffer cimport PyObject_GetBuffer -from cpython.mem cimport PyMem_Malloc, PyMem_Free -from cpython.object cimport Py_EQ, Py_NE -from libc.stdint cimport int32_t, int64_t, uint32_t, uint64_t, uintptr_t - -import ctypes -import threading - -import mojo_system_impl - -def SetSystemThunks(system_thunks_as_object): - """Bind the basic Mojo Core functions. - - This should only be used by the embedder. - """ - cdef const c_thunks.MojoSystemThunks* system_thunks = ( - <const c_thunks.MojoSystemThunks*><uintptr_t>system_thunks_as_object) - c_thunks.MojoSetSystemThunks(system_thunks) - -HANDLE_INVALID = c_core.MOJO_HANDLE_INVALID -RESULT_OK = c_core.MOJO_RESULT_OK -RESULT_CANCELLED = c_core.MOJO_RESULT_CANCELLED -RESULT_UNKNOWN = c_core.MOJO_RESULT_UNKNOWN -RESULT_INVALID_ARGUMENT = c_core.MOJO_RESULT_INVALID_ARGUMENT -RESULT_DEADLINE_EXCEEDED = c_core.MOJO_RESULT_DEADLINE_EXCEEDED -RESULT_NOT_FOUND = c_core.MOJO_RESULT_NOT_FOUND -RESULT_ALREADY_EXISTS = c_core.MOJO_RESULT_ALREADY_EXISTS -RESULT_PERMISSION_DENIED = c_core.MOJO_RESULT_PERMISSION_DENIED -RESULT_RESOURCE_EXHAUSTED = c_core.MOJO_RESULT_RESOURCE_EXHAUSTED -RESULT_FAILED_PRECONDITION = c_core.MOJO_RESULT_FAILED_PRECONDITION -RESULT_ABORTED = c_core.MOJO_RESULT_ABORTED -RESULT_OUT_OF_RANGE = c_core.MOJO_RESULT_OUT_OF_RANGE -RESULT_UNIMPLEMENTED = c_core.MOJO_RESULT_UNIMPLEMENTED -RESULT_INTERNAL = c_core.MOJO_RESULT_INTERNAL -RESULT_UNAVAILABLE = c_core.MOJO_RESULT_UNAVAILABLE -RESULT_DATA_LOSS = c_core.MOJO_RESULT_DATA_LOSS -RESULT_BUSY = c_core.MOJO_RESULT_BUSY -RESULT_SHOULD_WAIT = c_core.MOJO_RESULT_SHOULD_WAIT -DEADLINE_INDEFINITE = c_core.MOJO_DEADLINE_INDEFINITE -HANDLE_SIGNAL_NONE = c_core.MOJO_HANDLE_SIGNAL_NONE -HANDLE_SIGNAL_READABLE = c_core.MOJO_HANDLE_SIGNAL_READABLE -HANDLE_SIGNAL_WRITABLE = c_core.MOJO_HANDLE_SIGNAL_WRITABLE -HANDLE_SIGNAL_PEER_CLOSED = c_core.MOJO_HANDLE_SIGNAL_PEER_CLOSED -WRITE_MESSAGE_FLAG_NONE = c_core.MOJO_WRITE_MESSAGE_FLAG_NONE -READ_MESSAGE_FLAG_NONE = c_core.MOJO_READ_MESSAGE_FLAG_NONE -READ_MESSAGE_FLAG_MAY_DISCARD = c_core.MOJO_READ_MESSAGE_FLAG_MAY_DISCARD -WRITE_DATA_FLAG_NONE = c_core.MOJO_WRITE_DATA_FLAG_NONE -WRITE_DATA_FLAG_ALL_OR_NONE = c_core.MOJO_WRITE_DATA_FLAG_ALL_OR_NONE -READ_DATA_FLAG_NONE = c_core.MOJO_READ_DATA_FLAG_NONE -READ_DATA_FLAG_ALL_OR_NONE = c_core.MOJO_READ_DATA_FLAG_ALL_OR_NONE -READ_DATA_FLAG_DISCARD = c_core.MOJO_READ_DATA_FLAG_DISCARD -READ_DATA_FLAG_QUERY = c_core.MOJO_READ_DATA_FLAG_QUERY -READ_DATA_FLAG_PEEK = c_core.MOJO_READ_DATA_FLAG_PEEK -MAP_BUFFER_FLAG_NONE = c_core.MOJO_MAP_BUFFER_FLAG_NONE - -_WAITMANY_NO_SIGNAL_STATE_ERRORS = [RESULT_INVALID_ARGUMENT, - RESULT_RESOURCE_EXHAUSTED] - -def GetTimeTicksNow(): - """Monotonically increasing tick count representing "right now." - - See mojo/public/c/system/functions.h - """ - return c_core.MojoGetTimeTicksNow() - -cdef class _ScopedMemory: - """Allocate memory at creation, and deallocate it at destruction.""" - cdef void* memory - def __init__(self, size): - self.memory = PyMem_Malloc(size) - - def __dealloc__(self): - PyMem_Free(self.memory) - -cdef class _ScopedBuffer: - """Retrieve pointer to a buffer a creation, and release it at destruction. - """ - cdef Py_buffer _buf - cdef void* buf - cdef Py_ssize_t len - - def __init__(self, obj, flags=PyBUF_CONTIG_RO): - if obj: - if PyObject_GetBuffer(obj, &self._buf, flags) < 0: - raise TypeError('Unable to read buffer.') - self.buf = self._buf.buf - self.len = self._buf.len - else: - self.buf = NULL - self.len = 0 - - def __dealloc__(self): - if self.buf: - PyBuffer_Release(&self._buf) - -def _SliceBuffer(buffer, size): - """Slice the given buffer, reducing it to the given size. - - Return None if None is passed in. - """ - if not buffer: - return buffer - return buffer[:size] - -cdef class _NativeMemoryView(object): - """Create a python buffer wrapping the given memory. - - Will also retain the given handle until this object is deallocated. - """ - cdef void* _memory - cdef uint32_t _size - cdef char _read_only - cdef char _wrapped - cdef object _handle - - def __init__(self, handle): - self._handle = handle - - def __cinit__(self): - self._memory = NULL - self._size = 0 - self._read_only = True - self._wrapped = False - - cdef Wrap(self, - const void* memory, - uint32_t size, - read_only=True): - """Makes this buffer wraps the given memory. - - Must be called before using this buffer, and must only be called once. - """ - assert not self._wrapped - self._wrapped = True - self._memory = <void*>memory - self._size = size - self._read_only = read_only - - # buffer interface (PEP 3118) - def __getbuffer__(self, Py_buffer *view, int flags): - assert self._wrapped - if view == NULL: - return - PyBuffer_FillInfo(view, - self, - self._memory, - self._size, - self._read_only, - flags) - - def __releasebuffer__(self, Py_buffer *view): - assert self._wrapped - pass - - # legacy buffer interface - def __getsegcount__(self, Py_ssize_t *sizes): - assert self._wrapped - if sizes != NULL: - sizes[0] = self._size - return 1 - - def __getreadbuffer__(self, Py_ssize_t index, void **data): - assert self._wrapped - if index != 0: - raise SystemError('Index out of bounds: %d' % index) - data[0] = self._memory - return self._size - - def __getwritebuffer__(self, Py_ssize_t index, void **data): - assert self._wrapped - if index != 0: - raise SystemError('Index out of bounds: %d' % index) - if self._read_only: - raise TypeError('Buffer is read-only.') - data[0] = self._memory - return self._size - -class MojoException(Exception): - """Exception wrapping a mojo result error code.""" - - def __init__(self, mojo_result): - self.mojo_result = mojo_result - -def WaitMany(handles_and_signals, deadline): - """Waits on a list of handles. - - Args: - handles_and_signals: list of tuples of handle and signal. - - See mojo/public/c/system/functions.h - """ - cdef uint32_t length = len(handles_and_signals) - cdef uint32_t result_index = <uint32_t>(-1) - - cdef _ScopedMemory handles_alloc = _ScopedMemory( - sizeof(c_core.MojoHandle) * length) - cdef _ScopedMemory signals_alloc = _ScopedMemory( - sizeof(c_core.MojoHandleSignals) * length) - cdef _ScopedMemory states_alloc = _ScopedMemory( - sizeof(c_core.MojoHandleSignalsState) * length) - cdef c_core.MojoHandle* handles = <c_core.MojoHandle*>handles_alloc.memory - cdef c_core.MojoHandleSignals* signals = ( - <c_core.MojoHandleSignals*>signals_alloc.memory) - cdef c_core.MojoHandleSignalsState* states = ( - <c_core.MojoHandleSignalsState*>states_alloc.memory) - cdef int index = 0 - for (h, s) in handles_and_signals: - handles[index] = (<Handle?>h)._mojo_handle - signals[index] = s - index += 1 - cdef c_core.MojoResult result = c_core.MOJO_RESULT_OK - cdef c_core.MojoDeadline cdeadline = deadline - with nogil: - result = c_core.MojoWaitMany(handles, signals, length, cdeadline, - &result_index, states) - - returned_result_index = None - if result_index != <uint32_t>(-1): - returned_result_index = result_index - - returned_states = None - if result not in _WAITMANY_NO_SIGNAL_STATE_ERRORS: - returned_states = [(states[i].satisfied_signals, - states[i].satisfiable_signals) for i in xrange(length)] - - return (result, returned_result_index, returned_states) - - -cdef class DataPipeTwoPhaseBuffer(object): - """Return value for two phases read and write. - - The buffer field contains the python buffer where data can be read or written. - When done with the buffer, the |end| method must be called with the number of - bytes read or written. - """ - - cdef object _buffer - cdef Handle _handle - cdef char _read - - def __init__(self, handle, buffer, read=True): - self._buffer = buffer - self._handle = handle - self._read = read - - def End(self, num_bytes): - self._buffer = None - cdef c_core.MojoResult result - if self._read: - result = c_core.MojoEndReadData(self._handle._mojo_handle, num_bytes) - else: - result = c_core.MojoEndWriteData(self._handle._mojo_handle, num_bytes) - self._handle = None - return result - - @property - def buffer(self): - return self._buffer - - def __dealloc__(self): - assert not self._buffer - -cdef class MappedBuffer(object): - """Return value for the |map| operation on shared buffer handles. - - The buffer field contains the python buffer where data can be read or written. - When done with the buffer, the |unmap| method must be called. - """ - - cdef object _buffer - cdef object _handle - cdef object _cleanup - - def __init__(self, handle, buffer, cleanup): - self._buffer = buffer - self._handle = handle - self._cleanup = cleanup - - def UnMap(self): - self._buffer = None - cdef c_core.MojoResult result = self._cleanup() - self._cleanup = None - self._handle = None - return result - - @property - def buffer(self): - return self._buffer - - def __dealloc__(self): - if self._buffer: - self.UnMap() - -cdef class Handle(object): - """A mojo object.""" - - cdef c_core.MojoHandle _mojo_handle - - def __init__(self, mojo_handle=c_core.MOJO_HANDLE_INVALID): - self._mojo_handle = mojo_handle - - def _Invalidate(self): - """Invalidate the current handle. - - The close operation is not called. It is the responsability of the caller to - ensure that the handle is not leaked. - """ - self._mojo_handle = c_core.MOJO_HANDLE_INVALID - - def __richcmp__(self, other, op): - if op != Py_EQ and op != Py_NE: - raise TypeError('Handle is not ordered') - cdef int equality - if type(self) is not type(other): - equality = id(self) == id(other) - else: - equality = (<Handle>self)._mojo_handle == (<Handle>other)._mojo_handle - if op == Py_EQ: - return equality - else: - return not equality - - def IsValid(self): - """Returns whether this handle is valid.""" - return self._mojo_handle != c_core.MOJO_HANDLE_INVALID - - def Close(self): - """Closes this handle. - - See mojo/public/c/system/functions.h - """ - cdef c_core.MojoResult result = c_core.MOJO_RESULT_OK - if self.IsValid(): - result = c_core.MojoClose(self._mojo_handle) - self._Invalidate() - return result - - def __dealloc__(self): - self.Close() - - def Wait(self, signals, deadline): - """Waits on the given handle. - - See mojo/public/c/system/functions.h - """ - cdef c_core.MojoHandle handle = self._mojo_handle - cdef c_core.MojoHandleSignals csignals = signals - cdef c_core.MojoDeadline cdeadline = deadline - cdef c_core.MojoHandleSignalsState signal_states - cdef c_core.MojoResult result - with nogil: - result = c_core.MojoWait(handle, csignals, cdeadline, &signal_states) - - returned_states = None - if result not in _WAITMANY_NO_SIGNAL_STATE_ERRORS: - returned_states = (signal_states.satisfied_signals, - signal_states.satisfiable_signals) - - return (result, returned_states) - - def AsyncWait(self, signals, deadline, callback): - cdef c_core.MojoHandle handle = self._mojo_handle - cdef c_core.MojoHandleSignals csignals = signals - cdef c_core.MojoDeadline cdeadline = deadline - wait_id = _ASYNC_WAITER.AsyncWait( - handle, - csignals, - cdeadline, - callback) - def cancel(): - _ASYNC_WAITER.CancelWait(wait_id) - return cancel - - def WriteMessage(self, - buffer=None, - handles=None, - flags=WRITE_MESSAGE_FLAG_NONE): - """Writes a message to the message pipe. - - This method can only be used on a handle obtained from |MessagePipe()|. - - See mojo/public/c/system/message_pipe.h - """ - cdef _ScopedBuffer buffer_as_buffer = _ScopedBuffer(buffer) - cdef uint32_t input_buffer_length = buffer_as_buffer.len - cdef c_core.MojoHandle* input_handles = NULL - cdef uint32_t input_handles_length = 0 - cdef _ScopedMemory handles_alloc = None - if handles: - input_handles_length = len(handles) - handles_alloc = _ScopedMemory(sizeof(c_core.MojoHandle) * - input_handles_length) - input_handles = <c_core.MojoHandle*>handles_alloc.memory - for i in xrange(input_handles_length): - input_handles[i] = (<Handle?>handles[i])._mojo_handle - cdef c_core.MojoResult res = c_core.MojoWriteMessage(self._mojo_handle, - buffer_as_buffer.buf, - input_buffer_length, - input_handles, - input_handles_length, - flags) - if res == c_core.MOJO_RESULT_OK and handles: - # Handles have been transferred. Let's invalidate those. - for handle in handles: - handle._Invalidate() - return res - - def ReadMessage(self, - buffer=None, - max_number_of_handles=0, - flags=READ_MESSAGE_FLAG_NONE): - """Reads a message from the message pipe. - - This method can only be used on a handle obtained from |MessagePipe()|. - - This method returns a triplet of value (code, data, sizes): - - if code is RESULT_OK, sizes will be None, and data will be a pair of - (buffer, handles) where buffer is a view of the input buffer with the read - data, and handles is a list of received handles. - - if code is RESULT_RESOURCE_EXHAUSTED, data will be None and sizes will be - a pair of (buffer_size, handles_size) where buffer_size is the size of the - next message data and handles_size is the number of handles in the next - message. - - if code is any other value, data and sizes will be None. - - See mojo/public/c/system/message_pipe.h - """ - cdef _ScopedBuffer buffer_as_buffer = _ScopedBuffer(buffer, PyBUF_CONTIG) - cdef uint32_t input_buffer_length = buffer_as_buffer.len - cdef c_core.MojoHandle* input_handles = NULL - cdef uint32_t input_handles_length = 0 - cdef _ScopedMemory handles_alloc = None - if max_number_of_handles > 0: - input_handles_length = max_number_of_handles - handles_alloc = _ScopedMemory(sizeof(c_core.MojoHandle) * - input_handles_length) - input_handles = <c_core.MojoHandle*>handles_alloc.memory - cdef res = c_core.MojoReadMessage(self._mojo_handle, - buffer_as_buffer.buf, - &input_buffer_length, - input_handles, - &input_handles_length, - flags) - if res == c_core.MOJO_RESULT_RESOURCE_EXHAUSTED: - return (res, None, (input_buffer_length, input_handles_length)) - if res == c_core.MOJO_RESULT_OK: - returned_handles = [Handle(input_handles[i]) - for i in xrange(input_handles_length)] - return (res, - (_SliceBuffer(buffer, input_buffer_length), returned_handles), - None) - return (res, None, None) - - def WriteData(self, buffer=None, flags=WRITE_DATA_FLAG_NONE): - """ - Writes the given data to the data pipe producer. - - This method can only be used on a producer handle obtained from - |DataPipe()|. - - This method returns a tuple (code, num_bytes). - - If code is RESULT_OK, num_bytes is the number of written bytes. - - Otherwise, num_bytes is None. - - See mojo/public/c/system/data_pipe.h - """ - cdef _ScopedBuffer buffer_as_buffer = _ScopedBuffer(buffer) - cdef uint32_t input_buffer_length = buffer_as_buffer.len - cdef c_core.MojoResult res = c_core.MojoWriteData(self._mojo_handle, - buffer_as_buffer.buf, - &input_buffer_length, - flags) - if res == c_core.MOJO_RESULT_OK: - return (res, input_buffer_length) - return (res, None) - - def BeginWriteData(self, - min_size=None, - flags=WRITE_DATA_FLAG_NONE): - """ - Begins a two-phase write to the data pipe producer. - - This method can only be used on a producer handle obtained from - |DataPipe()|. - - This method returns a tuple (code, two_phase_buffer). - - If code is RESULT_OK, two_phase_buffer is a writable - DataPipeTwoPhaseBuffer - - Otherwise, two_phase_buffer is None. - - See mojo/public/c/system/data_pipe.h - """ - cdef void* out_buffer - cdef uint32_t out_size = 0 - if min_size: - flags |= c_core.MOJO_WRITE_DATA_FLAG_ALL_OR_NONE - out_size = min_size - cdef c_core.MojoResult res = c_core.MojoBeginWriteData(self._mojo_handle, - &out_buffer, - &out_size, - flags) - if res != c_core.MOJO_RESULT_OK: - return (res, None) - cdef _NativeMemoryView view_buffer = _NativeMemoryView(self) - view_buffer.Wrap(out_buffer, out_size, read_only=False) - return (res, DataPipeTwoPhaseBuffer(self, memoryview(view_buffer), False)) - - def ReadData(self, buffer=None, flags=READ_DATA_FLAG_NONE): - """Reads data from the data pipe consumer. - - This method can only be used on a consumer handle obtained from - |DataPipe()|. - - This method returns a tuple (code, buffer) - - if code is RESULT_OK, buffer will be a view of the input buffer with the - read data. - - otherwise, buffer will be None. - - See mojo/public/c/system/data_pipe.h - """ - cdef _ScopedBuffer buffer_as_buffer = _ScopedBuffer(buffer) - cdef uint32_t input_buffer_length = buffer_as_buffer.len - cdef c_core.MojoResult res = c_core.MojoReadData(self._mojo_handle, - buffer_as_buffer.buf, - &input_buffer_length, - flags) - if res == c_core.MOJO_RESULT_OK: - return (res, _SliceBuffer(buffer, input_buffer_length)) - return (res, None) - - def QueryData(self, flags=READ_DATA_FLAG_NONE): - """Queries the amount of data available on the data pipe consumer. - - This method can only be used on a consumer handle obtained from - |DataPipe()|. - - This method returns a tuple (code, num_bytes) - - if code is RESULT_OK, num_bytes will be the number of bytes available on - the data pipe consumer. - - otherwise, num_bytes will be None. - - See mojo/public/c/system/data_pipe.h - """ - cdef uint32_t num_bytes = 0 - cdef c_core.MojoResult res = c_core.MojoReadData( - self._mojo_handle, - NULL, - &num_bytes, - flags|c_core.MOJO_READ_DATA_FLAG_QUERY) - return (res, num_bytes) - - def BeginReadData(self, min_size=None, flags=READ_DATA_FLAG_NONE): - """ - Begins a two-phase read to the data pipe consumer. - - This method can only be used on a consumer handle obtained from - |DataPipe()|. - - This method returns a tuple (code, two_phase_buffer). - - If code is RESULT_OK, two_phase_buffer is a readable - DataPipeTwoPhaseBuffer - - Otherwise, two_phase_buffer is None. - - See mojo/public/c/system/data_pipe.h - """ - cdef const void* out_buffer - cdef uint32_t out_size = 0 - if min_size: - flags |= c_core.MOJO_READ_DATA_FLAG_ALL_OR_NONE - out_size = min_size - cdef c_core.MojoResult res = c_core.MojoBeginReadData(self._mojo_handle, - &out_buffer, - &out_size, - flags) - if res != c_core.MOJO_RESULT_OK: - return (res, None) - cdef _NativeMemoryView view_buffer = _NativeMemoryView(self) - view_buffer.Wrap(out_buffer, out_size, read_only=True) - return (res, DataPipeTwoPhaseBuffer(self, memoryview(view_buffer), True)) - - def Duplicate(self, options=None): - """Duplicate the shared buffer handle. - - This method can only be used on a handle obtained from - |CreateSharedBuffer()| or |Duplicate()|. - - See mojo/public/c/system/buffer.h - """ - cdef c_core.MojoDuplicateBufferHandleOptions coptions - cdef c_core.MojoDuplicateBufferHandleOptions* coptions_ptr = NULL - cdef c_core.MojoHandle cnew_handle = c_core.MOJO_HANDLE_INVALID - if options: - coptions.struct_size = sizeof(c_core.MojoDuplicateBufferHandleOptions) - coptions.flags = options.flags - coptions_ptr = &coptions - cdef c_core.MojoResult result = c_core.MojoDuplicateBufferHandle( - self._mojo_handle, coptions_ptr, &cnew_handle) - new_handle = Handle(cnew_handle) - if result != c_core.MOJO_RESULT_OK: - raise MojoException(result) - return new_handle - - def Map(self, offset, num_bytes, flags=MAP_BUFFER_FLAG_NONE): - """Maps the part (at offset |offset| of length |num_bytes|) of the buffer. - - This method can only be used on a handle obtained from - |CreateSharedBuffer()| or |Duplicate()|. - - This method returns a tuple (code, mapped_buffer). - - If code is RESULT_OK, mapped_buffer is a readable/writable - MappedBuffer - - Otherwise, mapped_buffer is None. - - See mojo/public/c/system/buffer.h - """ - cdef void* buffer - res = c_core.MojoMapBuffer(self._mojo_handle, - offset, - num_bytes, - &buffer, - flags) - if res != c_core.MOJO_RESULT_OK: - return (res, None) - cdef _NativeMemoryView view_buffer = _NativeMemoryView(self) - view_buffer.Wrap(buffer, num_bytes, read_only=False) - return (res, MappedBuffer(self, - memoryview(view_buffer), - lambda: c_core.MojoUnmapBuffer(buffer))) - -class CreateMessagePipeOptions(object): - """Options for creating a message pipe. - - See mojo/public/c/system/message_pipe.h - """ - FLAG_NONE = c_core.MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE - - def __init__(self): - self.flags = CreateMessagePipeOptions.FLAG_NONE - -class MessagePipe(object): - """Creates a message pipe. - - The two ends of the message pipe are accessible with the members handle0 and - handle1. - - See mojo/public/c/system/message_pipe.h - """ - def __init__(self, options=None): - cdef c_core.MojoCreateMessagePipeOptions coptions - cdef c_core.MojoCreateMessagePipeOptions* coptions_ptr = NULL - cdef c_core.MojoHandle chandle0 = c_core.MOJO_HANDLE_INVALID - cdef c_core.MojoHandle chandle1 = c_core.MOJO_HANDLE_INVALID - if options: - coptions.struct_size = sizeof(c_core.MojoCreateMessagePipeOptions) - coptions.flags = options.flags - coptions_ptr = &coptions - cdef c_core.MojoResult result = c_core.MojoCreateMessagePipe(coptions_ptr, - &chandle0, - &chandle1) - self.handle0 = Handle(chandle0) - self.handle1 = Handle(chandle1) - if result != c_core.MOJO_RESULT_OK: - raise c_core.MojoException(result) - - -class CreateDataPipeOptions(object): - """Options for creating a data pipe. - - See mojo/public/c/system/data_pipe.h - """ - FLAG_NONE = c_core.MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE - FLAG_MAY_DISCARD = c_core.MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD - - def __init__(self): - self.flags = CreateDataPipeOptions.FLAG_NONE - self.element_num_bytes = 1 - self.capacity_num_bytes = 0 - -class DataPipe(object): - """Creates a data pipe. - - The producer end of the data pipe is accessible with the member - producer_handle and the consumer end of the data pipe is accessible with the - member cconsumer_handle. - - See mojo/public/c/system/data_pipe.h - """ - def __init__(self, options=None): - cdef c_core.MojoCreateDataPipeOptions coptions - cdef c_core.MojoCreateDataPipeOptions* coptions_ptr = NULL - cdef c_core.MojoHandle cproducer_handle = c_core.MOJO_HANDLE_INVALID - cdef c_core.MojoHandle cconsumer_handle = c_core.MOJO_HANDLE_INVALID - if options: - coptions.struct_size = sizeof(c_core.MojoCreateDataPipeOptions) - coptions.flags = options.flags - coptions.element_num_bytes = options.element_num_bytes - coptions.capacity_num_bytes = options.capacity_num_bytes - coptions_ptr = &coptions - cdef c_core.MojoResult result = c_core.MojoCreateDataPipe(coptions_ptr, - &cproducer_handle, - &cconsumer_handle) - self.producer_handle = Handle(cproducer_handle) - self.consumer_handle = Handle(cconsumer_handle) - if result != c_core.MOJO_RESULT_OK: - raise MojoException(result) - -class CreateSharedBufferOptions(object): - """Options for creating a shared buffer. - - See mojo/public/c/system/buffer.h - """ - FLAG_NONE = c_core.MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE - - def __init__(self): - self.flags = CreateSharedBufferOptions.FLAG_NONE - -def CreateSharedBuffer(num_bytes, options=None): - """Creates a buffer of size |num_bytes| bytes that can be shared. - - See mojo/public/c/system/buffer.h - """ - cdef c_core.MojoCreateSharedBufferOptions coptions - cdef c_core.MojoCreateSharedBufferOptions* coptions_ptr = NULL - cdef c_core.MojoHandle chandle = c_core.MOJO_HANDLE_INVALID - if options: - coptions.struct_size = sizeof(c_core.MojoCreateSharedBufferOptions) - coptions.flags = options.flags - coptions_ptr = &coptions - cdef c_core.MojoResult result = c_core.MojoCreateSharedBuffer(coptions_ptr, - num_bytes, - &chandle) - handle = Handle(chandle) - if result != c_core.MOJO_RESULT_OK: - raise MojoException(result) - return handle - -class DuplicateSharedBufferOptions(object): - """Options for duplicating a shared buffer. - - See mojo/public/c/system/buffer.h - """ - FLAG_NONE = c_core.MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE - - def __init__(self): - self.flags = DuplicateSharedBufferOptions.FLAG_NONE - - -# Keeps a thread local weak reference to the current run loop. -_RUN_LOOPS = threading.local() - - -class RunLoop(object): - """RunLoop to use when using asynchronous operations on handles.""" - - def __init__(self): - self.__run_loop = mojo_system_impl.RunLoop() - _RUN_LOOPS.loop = id(self) - - def __del__(self): - del _RUN_LOOPS.loop - - def Run(self): - """Run the runloop until Quit is called.""" - return self.__run_loop.Run() - - def RunUntilIdle(self): - """Run the runloop until Quit is called or no operation is waiting.""" - return self.__run_loop.RunUntilIdle() - - def Quit(self): - """Quit the runloop.""" - return self.__run_loop.Quit() - - def PostDelayedTask(self, runnable, delay=0): - """ - Post a task on the runloop. This must be called from the thread owning the - runloop. - """ - return self.__run_loop.PostDelayedTask(runnable, delay) - - @staticmethod - def Current(): - if hasattr(_RUN_LOOPS, 'loop'): - return ctypes.cast(_RUN_LOOPS.loop, ctypes.py_object).value - return None - - -_ASYNC_WAITER = mojo_system_impl.AsyncWaiter() diff --git a/mojo/public/python/mojo_system_impl.pyx b/mojo/public/python/mojo_system_impl.pyx deleted file mode 100644 index 3e299c1..0000000 --- a/mojo/public/python/mojo_system_impl.pyx +++ /dev/null @@ -1,75 +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. - -# distutils language = c++ - -cimport c_async_waiter -cimport c_environment -cimport c_export # needed so the init function gets exported -cimport c_thunks - - -from libc.stdint cimport uintptr_t - - -def SetSystemThunks(system_thunks_as_object): - """Bind the basic Mojo Core functions. - """ - cdef const c_thunks.MojoSystemThunks* system_thunks = ( - <const c_thunks.MojoSystemThunks*><uintptr_t>system_thunks_as_object) - c_thunks.MojoSetSystemThunks(system_thunks) - - -cdef class RunLoop(object): - """RunLoop to use when using asynchronous operations on handles.""" - - cdef c_environment.CRunLoop* c_run_loop - - def __init__(self): - assert not <uintptr_t>(c_environment.CRunLoopCurrent()) - self.c_run_loop = new c_environment.CRunLoop() - - def __dealloc__(self): - del self.c_run_loop - - def Run(self): - """Run the runloop until Quit is called.""" - self.c_run_loop.Run() - - def RunUntilIdle(self): - """Run the runloop until Quit is called or no operation is waiting.""" - self.c_run_loop.RunUntilIdle() - - def Quit(self): - """Quit the runloop.""" - self.c_run_loop.Quit() - - def PostDelayedTask(self, runnable, delay=0): - """ - Post a task on the runloop. This must be called from the thread owning the - runloop. - """ - cdef c_environment.CClosure closure = c_environment.BuildClosure(runnable) - self.c_run_loop.PostDelayedTask(closure, delay) - - -# We use a wrapping class to be able to call the C++ class PythonAsyncWaiter -# across module boundaries. -cdef class AsyncWaiter(object): - cdef c_environment.CEnvironment* _cenvironment - cdef c_async_waiter.PythonAsyncWaiter* _c_async_waiter - - def __init__(self): - self._cenvironment = new c_environment.CEnvironment() - self._c_async_waiter = c_environment.NewAsyncWaiter() - - def __dealloc__(self): - del self._c_async_waiter - del self._cenvironment - - def AsyncWait(self, handle, signals, deadline, callback): - return self._c_async_waiter.AsyncWait(handle, signals, deadline, callback) - - def CancelWait(self, wait_id): - self._c_async_waiter.CancelWait(wait_id) diff --git a/mojo/public/python/src/common.cc b/mojo/public/python/src/common.cc deleted file mode 100644 index a80d013..0000000 --- a/mojo/public/python/src/common.cc +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2013 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. - -#include "mojo/public/python/src/common.h" - -#include <Python.h> - -#include "mojo/public/c/environment/async_waiter.h" -#include "mojo/public/cpp/bindings/callback.h" -#include "mojo/public/cpp/bindings/lib/shared_ptr.h" -#include "mojo/public/cpp/environment/logging.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/public/cpp/system/macros.h" -#include "mojo/public/cpp/utility/run_loop.h" - -namespace { - -void AsyncCallbackForwarder(void* closure, MojoResult result) { - mojo::Callback<void(MojoResult)>* callback = - static_cast<mojo::Callback<void(MojoResult)>*>(closure); - // callback will be deleted when it is run. - callback->Run(result); -} - -} // namespace - -namespace mojo { -namespace python { - -ScopedGIL::ScopedGIL() { - state_ = PyGILState_Ensure(); -} - -ScopedGIL::~ScopedGIL() { - PyGILState_Release(state_); -} - -ScopedPyRef::ScopedPyRef(PyObject* object) : object_(object) { -} - -ScopedPyRef::ScopedPyRef(PyObject* object, ScopedPyRefAcquire) - : object_(object) { - Py_XINCREF(object_); -} - -ScopedPyRef::~ScopedPyRef() { - if (object_) { - ScopedGIL acquire_gil; - Py_DECREF(object_); - } -} - -ScopedPyRef::operator PyObject*() const { - return object_; -} - -PythonClosure::PythonClosure(PyObject* callable, const mojo::Closure& quit) - : callable_(callable, kAcquire), quit_(quit) { - MOJO_DCHECK(callable); -} - -PythonClosure::~PythonClosure() {} - -void PythonClosure::Run() const { - ScopedGIL acquire_gil; - ScopedPyRef empty_tuple(PyTuple_New(0)); - if (!empty_tuple) { - quit_.Run(); - return; - } - - ScopedPyRef result(PyObject_CallObject(callable_, empty_tuple)); - if (!result) { - quit_.Run(); - return; - } -} - -Closure::Runnable* NewRunnableFromCallable(PyObject* callable, - const mojo::Closure& quit_closure) { - MOJO_DCHECK(PyCallable_Check(callable)); - - return new PythonClosure(callable, quit_closure); -} - -class PythonAsyncWaiter::AsyncWaiterRunnable - : public mojo::Callback<void(MojoResult)>::Runnable { - public: - AsyncWaiterRunnable(PyObject* callable, - CallbackMap* callbacks, - const mojo::Closure& quit) - : wait_id_(0), - callable_(callable, kAcquire), - callbacks_(callbacks), - quit_(quit) { - MOJO_DCHECK(callable_); - MOJO_DCHECK(callbacks_); - } - - void set_wait_id(MojoAsyncWaitID wait_id) { wait_id_ = wait_id; } - - void Run(MojoResult mojo_result) const override { - MOJO_DCHECK(wait_id_); - - // Remove to reference to this object from PythonAsyncWaiter and ensure this - // object will be destroyed when this method exits. - MOJO_DCHECK(callbacks_->find(wait_id_) != callbacks_->end()); - internal::SharedPtr<mojo::Callback<void(MojoResult)>> self = - (*callbacks_)[wait_id_]; - callbacks_->erase(wait_id_); - - ScopedGIL acquire_gil; - ScopedPyRef args_tuple(Py_BuildValue("(i)", mojo_result)); - if (!args_tuple) { - quit_.Run(); - return; - } - - ScopedPyRef result(PyObject_CallObject(callable_, args_tuple)); - if (!result) { - quit_.Run(); - return; - } - } - - private: - MojoAsyncWaitID wait_id_; - ScopedPyRef callable_; - CallbackMap* callbacks_; - const mojo::Closure quit_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(AsyncWaiterRunnable); -}; - -PythonAsyncWaiter::PythonAsyncWaiter(const mojo::Closure& quit_closure) - : quit_(quit_closure) { - async_waiter_ = Environment::GetDefaultAsyncWaiter(); -} - -PythonAsyncWaiter::~PythonAsyncWaiter() { - for (CallbackMap::const_iterator it = callbacks_.begin(); - it != callbacks_.end(); - ++it) { - async_waiter_->CancelWait(it->first); - } -} - -MojoAsyncWaitID PythonAsyncWaiter::AsyncWait(MojoHandle handle, - MojoHandleSignals signals, - MojoDeadline deadline, - PyObject* callable) { - AsyncWaiterRunnable* runner = - new AsyncWaiterRunnable(callable, &callbacks_, quit_); - internal::SharedPtr<mojo::Callback<void(MojoResult)>> callback( - new mojo::Callback<void(MojoResult)>( - static_cast<mojo::Callback<void(MojoResult)>::Runnable*>(runner))); - MojoAsyncWaitID wait_id = async_waiter_->AsyncWait( - handle, signals, deadline, &AsyncCallbackForwarder, callback.get()); - callbacks_[wait_id] = callback; - runner->set_wait_id(wait_id); - return wait_id; -} - -void PythonAsyncWaiter::CancelWait(MojoAsyncWaitID wait_id) { - if (callbacks_.find(wait_id) != callbacks_.end()) { - async_waiter_->CancelWait(wait_id); - callbacks_.erase(wait_id); - } -} - -} // namespace python -} // namespace mojo diff --git a/mojo/public/python/src/common.h b/mojo/public/python/src/common.h deleted file mode 100644 index 03ed73b..0000000 --- a/mojo/public/python/src/common.h +++ /dev/null @@ -1,103 +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. - -#ifndef MOJO_PUBLIC_PYTHON_SRC_COMMON_H_ -#define MOJO_PUBLIC_PYTHON_SRC_COMMON_H_ - -#include <Python.h> - -#include <map> - -#include "mojo/public/c/environment/async_waiter.h" -#include "mojo/public/cpp/bindings/callback.h" -#include "mojo/public/cpp/bindings/lib/shared_ptr.h" -#include "mojo/public/cpp/system/core.h" - -namespace mojo { -namespace python { - -class ScopedGIL { - public: - ScopedGIL(); - - ~ScopedGIL(); - - private: - PyGILState_STATE state_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedGIL); -}; - -enum ScopedPyRefAcquire { - kAcquire, -}; - -class ScopedPyRef { - public: - explicit ScopedPyRef(PyObject* object); - ScopedPyRef(PyObject* object, ScopedPyRefAcquire); - - ~ScopedPyRef(); - - operator PyObject*() const; - - private: - PyObject* object_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedPyRef); -}; - - -class PythonClosure : public mojo::Closure::Runnable { - public: - PythonClosure(PyObject* callable, const mojo::Closure& quit); - ~PythonClosure(); - - void Run() const override; - - private: - ScopedPyRef callable_; - const mojo::Closure quit_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(PythonClosure); -}; - -// Create a mojo::Closure from a callable python object. -Closure::Runnable* NewRunnableFromCallable(PyObject* callable, - const Closure& quit_closure); - -// AsyncWaiter for python, used to execute a python closure after waiting. If an -// error occurs while executing the closure, the current message loop will be -// exited. See |AsyncWaiter| in mojo/public/c/environment/async_waiter.h for -// more details. -class PythonAsyncWaiter { - public: - explicit PythonAsyncWaiter(const mojo::Closure& quit_closure); - ~PythonAsyncWaiter(); - MojoAsyncWaitID AsyncWait(MojoHandle handle, - MojoHandleSignals signals, - MojoDeadline deadline, - PyObject* callable); - - void CancelWait(MojoAsyncWaitID wait_id); - - private: - class AsyncWaiterRunnable; - - typedef std::map<MojoAsyncWaitID, - internal::SharedPtr<mojo::Callback<void(MojoResult)> > > - CallbackMap; - - CallbackMap callbacks_; - const MojoAsyncWaiter* async_waiter_; - const mojo::Closure quit_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(PythonAsyncWaiter); -}; - -} // namespace python -} // namespace mojo - -#endif // MOJO_PUBLIC_PYTHON_SRC_COMMON_H_ - diff --git a/mojo/public/python/src/python_system_helper.cc b/mojo/public/python/src/python_system_helper.cc deleted file mode 100644 index 0c5a358..0000000 --- a/mojo/public/python/src/python_system_helper.cc +++ /dev/null @@ -1,43 +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. - -#include "mojo/public/python/src/python_system_helper.h" - -#include "Python.h" - -#include "mojo/public/cpp/utility/run_loop.h" -#include "mojo/public/python/src/common.h" - -namespace { -class QuitCurrentRunLoop : public mojo::Closure::Runnable { - public: - void Run() const override { - mojo::RunLoop::current()->Quit(); - } - - static mojo::Closure NewQuitClosure() { - return mojo::Closure( - static_cast<mojo::Closure::Runnable*>(new QuitCurrentRunLoop())); - } -}; - -} // namespace - -namespace mojo { -namespace python { - -Closure BuildClosure(PyObject* callable) { - if (!PyCallable_Check(callable)) - return Closure(); - - return mojo::Closure( - NewRunnableFromCallable(callable, QuitCurrentRunLoop::NewQuitClosure())); -} - -PythonAsyncWaiter* NewAsyncWaiter() { - return new PythonAsyncWaiter(QuitCurrentRunLoop::NewQuitClosure()); -} - -} // namespace python -} // namespace mojo diff --git a/mojo/public/python/src/python_system_helper.h b/mojo/public/python/src/python_system_helper.h deleted file mode 100644 index ff9bb0b..0000000 --- a/mojo/public/python/src/python_system_helper.h +++ /dev/null @@ -1,30 +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. - -#ifndef MOJO_PUBLIC_PYTHON_SRC_PYTHON_SYSTEM_HELPER_H_ -#define MOJO_PUBLIC_PYTHON_SRC_PYTHON_SYSTEM_HELPER_H_ - -// Python must be the first include, as it defines preprocessor variable without -// checking if they already exist. -#include <Python.h> - -#include <map> - -#include "mojo/public/cpp/bindings/callback.h" -#include "mojo/public/python/src/common.h" - - -namespace mojo { -namespace python { -// Create a mojo::Closure from a callable python object. If an error occurs -// while executing callable, the closure will quit the current run loop. -Closure BuildClosure(PyObject* callable); - -// Create a new PythonAsyncWaiter object. Ownership is passed to the caller. -PythonAsyncWaiter* NewAsyncWaiter(); - -} // namespace python -} // namespace mojo - -#endif // MOJO_PUBLIC_PYTHON_SRC_PYTHON_SYSTEM_HELPER_H_ |