Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(239)

Unified Diff: tools/telemetry/third_party/gsutil/third_party/protorpc/protorpc/remote.py

Issue 1260493004: Revert "Add gsutil 4.13 to telemetry/third_party" (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tools/telemetry/third_party/gsutil/third_party/protorpc/protorpc/remote.py
diff --git a/tools/telemetry/third_party/gsutil/third_party/protorpc/protorpc/remote.py b/tools/telemetry/third_party/gsutil/third_party/protorpc/protorpc/remote.py
deleted file mode 100644
index b6c97687196bb91cc7940eda42fab93769b75c10..0000000000000000000000000000000000000000
--- a/tools/telemetry/third_party/gsutil/third_party/protorpc/protorpc/remote.py
+++ /dev/null
@@ -1,1247 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2010 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-"""Remote service library.
-
-This module contains classes that are useful for building remote services that
-conform to a standard request and response model. To conform to this model
-a service must be like the following class:
-
- # Each service instance only handles a single request and is then discarded.
- # Make these objects light weight.
- class Service(object):
-
- # It must be possible to construct service objects without any parameters.
- # If your constructor needs extra information you should provide a
- # no-argument factory function to create service instances.
- def __init__(self):
- ...
-
- # Each remote method must use the 'method' decorator, passing the request
- # and response message types. The remote method itself must take a single
- # parameter which is an instance of RequestMessage and return an instance
- # of ResponseMessage.
- @method(RequestMessage, ResponseMessage)
- def remote_method(self, request):
- # Return an instance of ResponseMessage.
-
- # A service object may optionally implement an 'initialize_request_state'
- # method that takes as a parameter a single instance of a RequestState. If
- # a service does not implement this method it will not receive the request
- # state.
- def initialize_request_state(self, state):
- ...
-
-The 'Service' class is provided as a convenient base class that provides the
-above functionality. It implements all required and optional methods for a
-service. It also has convenience methods for creating factory functions that
-can pass persistent global state to a new service instance.
-
-The 'method' decorator is used to declare which methods of a class are
-meant to service RPCs. While this decorator is not responsible for handling
-actual remote method invocations, such as handling sockets, handling various
-RPC protocols and checking messages for correctness, it does attach information
-to methods that responsible classes can examine and ensure the correctness
-of the RPC.
-
-When the method decorator is used on a method, the wrapper method will have a
-'remote' property associated with it. The 'remote' property contains the
-request_type and response_type expected by the methods implementation.
-
-On its own, the method decorator does not provide any support for subclassing
-remote methods. In order to extend a service, one would need to redecorate
-the sub-classes methods. For example:
-
- class MyService(Service):
-
- @method(DoSomethingRequest, DoSomethingResponse)
- def do_stuff(self, request):
- ... implement do_stuff ...
-
- class MyBetterService(MyService):
-
- @method(DoSomethingRequest, DoSomethingResponse)
- def do_stuff(self, request):
- response = super(MyBetterService, self).do_stuff.remote.method(request)
- ... do stuff with response ...
- return response
-
-A Service subclass also has a Stub class that can be used with a transport for
-making RPCs. When a stub is created, it is capable of doing both synchronous
-and asynchronous RPCs if the underlying transport supports it. To make a stub
-using an HTTP transport do:
-
- my_service = MyService.Stub(HttpTransport('<my service URL>'))
-
-For synchronous calls, just call the expected methods on the service stub:
-
- request = DoSomethingRequest()
- ...
- response = my_service.do_something(request)
-
-Each stub instance has an async object that can be used for initiating
-asynchronous RPCs if the underlying protocol transport supports it. To
-make an asynchronous call, do:
-
- rpc = my_service.async.do_something(request)
- response = rpc.get_response()
-"""
-
-from __future__ import with_statement
-import six
-
-__author__ = 'rafek@google.com (Rafe Kaplan)'
-
-import logging
-import sys
-import threading
-from wsgiref import headers as wsgi_headers
-
-from . import message_types
-from . import messages
-from . import protobuf
-from . import protojson
-from . import util
-
-
-__all__ = [
- 'ApplicationError',
- 'MethodNotFoundError',
- 'NetworkError',
- 'RequestError',
- 'RpcError',
- 'ServerError',
- 'ServiceConfigurationError',
- 'ServiceDefinitionError',
-
- 'HttpRequestState',
- 'ProtocolConfig',
- 'Protocols',
- 'RequestState',
- 'RpcState',
- 'RpcStatus',
- 'Service',
- 'StubBase',
- 'check_rpc_status',
- 'get_remote_method_info',
- 'is_error_status',
- 'method',
- 'remote',
-]
-
-
-class ServiceDefinitionError(messages.Error):
- """Raised when a service is improperly defined."""
-
-
-class ServiceConfigurationError(messages.Error):
- """Raised when a service is incorrectly configured."""
-
-
-# TODO: Use error_name to map to specific exception message types.
-class RpcStatus(messages.Message):
- """Status of on-going or complete RPC.
-
- Fields:
- state: State of RPC.
- error_name: Error name set by application. Only set when
- status is APPLICATION_ERROR. For use by application to transmit
- specific reason for error.
- error_message: Error message associated with status.
- """
-
- class State(messages.Enum):
- """Enumeration of possible RPC states.
-
- Values:
- OK: Completed successfully.
- RUNNING: Still running, not complete.
- REQUEST_ERROR: Request was malformed or incomplete.
- SERVER_ERROR: Server experienced an unexpected error.
- NETWORK_ERROR: An error occured on the network.
- APPLICATION_ERROR: The application is indicating an error.
- When in this state, RPC should also set application_error.
- """
- OK = 0
- RUNNING = 1
-
- REQUEST_ERROR = 2
- SERVER_ERROR = 3
- NETWORK_ERROR = 4
- APPLICATION_ERROR = 5
- METHOD_NOT_FOUND_ERROR = 6
-
- state = messages.EnumField(State, 1, required=True)
- error_message = messages.StringField(2)
- error_name = messages.StringField(3)
-
-
-RpcState = RpcStatus.State
-
-
-class RpcError(messages.Error):
- """Base class for RPC errors.
-
- Each sub-class of RpcError is associated with an error value from RpcState
- and has an attribute STATE that refers to that value.
- """
-
- def __init__(self, message, cause=None):
- super(RpcError, self).__init__(message)
- self.cause = cause
-
- @classmethod
- def from_state(cls, state):
- """Get error class from RpcState.
-
- Args:
- state: RpcState value. Can be enum value itself, string or int.
-
- Returns:
- Exception class mapped to value if state is an error. Returns None
- if state is OK or RUNNING.
- """
- return _RPC_STATE_TO_ERROR.get(RpcState(state))
-
-
-class RequestError(RpcError):
- """Raised when wrong request objects received during method invocation."""
-
- STATE = RpcState.REQUEST_ERROR
-
-
-class MethodNotFoundError(RequestError):
- """Raised when unknown method requested by RPC."""
-
- STATE = RpcState.METHOD_NOT_FOUND_ERROR
-
-
-class NetworkError(RpcError):
- """Raised when network error occurs during RPC."""
-
- STATE = RpcState.NETWORK_ERROR
-
-
-class ServerError(RpcError):
- """Unexpected error occured on server."""
-
- STATE = RpcState.SERVER_ERROR
-
-
-class ApplicationError(RpcError):
- """Raised for application specific errors.
-
- Attributes:
- error_name: Application specific error name for exception.
- """
-
- STATE = RpcState.APPLICATION_ERROR
-
- def __init__(self, message, error_name=None):
- """Constructor.
-
- Args:
- message: Application specific error message.
- error_name: Application specific error name. Must be None, string
- or unicode string.
- """
- super(ApplicationError, self).__init__(message)
- self.error_name = error_name
-
- def __str__(self):
- return self.args[0]
-
- def __repr__(self):
- if self.error_name is None:
- error_format = ''
- else:
- error_format = ', %r' % self.error_name
- return '%s(%r%s)' % (type(self).__name__, self.args[0], error_format)
-
-
-_RPC_STATE_TO_ERROR = {
- RpcState.REQUEST_ERROR: RequestError,
- RpcState.NETWORK_ERROR: NetworkError,
- RpcState.SERVER_ERROR: ServerError,
- RpcState.APPLICATION_ERROR: ApplicationError,
- RpcState.METHOD_NOT_FOUND_ERROR: MethodNotFoundError,
-}
-
-class _RemoteMethodInfo(object):
- """Object for encapsulating remote method information.
-
- An instance of this method is associated with the 'remote' attribute
- of the methods 'invoke_remote_method' instance.
-
- Instances of this class are created by the remote decorator and should not
- be created directly.
- """
-
- def __init__(self,
- method,
- request_type,
- response_type):
- """Constructor.
-
- Args:
- method: The method which implements the remote method. This is a
- function that will act as an instance method of a class definition
- that is decorated by '@method'. It must always take 'self' as its
- first parameter.
- request_type: Expected request type for the remote method.
- response_type: Expected response type for the remote method.
- """
- self.__method = method
- self.__request_type = request_type
- self.__response_type = response_type
-
- @property
- def method(self):
- """Original undecorated method."""
- return self.__method
-
- @property
- def request_type(self):
- """Expected request type for remote method."""
- if isinstance(self.__request_type, six.string_types):
- self.__request_type = messages.find_definition(
- self.__request_type,
- relative_to=sys.modules[self.__method.__module__])
- return self.__request_type
-
- @property
- def response_type(self):
- """Expected response type for remote method."""
- if isinstance(self.__response_type, six.string_types):
- self.__response_type = messages.find_definition(
- self.__response_type,
- relative_to=sys.modules[self.__method.__module__])
- return self.__response_type
-
-
-def method(request_type=message_types.VoidMessage,
- response_type=message_types.VoidMessage):
- """Method decorator for creating remote methods.
-
- Args:
- request_type: Message type of expected request.
- response_type: Message type of expected response.
-
- Returns:
- 'remote_method_wrapper' function.
-
- Raises:
- TypeError: if the request_type or response_type parameters are not
- proper subclasses of messages.Message.
- """
- if (not isinstance(request_type, six.string_types) and
- (not isinstance(request_type, type) or
- not issubclass(request_type, messages.Message) or
- request_type is messages.Message)):
- raise TypeError(
- 'Must provide message class for request-type. Found %s',
- request_type)
-
- if (not isinstance(response_type, six.string_types) and
- (not isinstance(response_type, type) or
- not issubclass(response_type, messages.Message) or
- response_type is messages.Message)):
- raise TypeError(
- 'Must provide message class for response-type. Found %s',
- response_type)
-
- def remote_method_wrapper(method):
- """Decorator used to wrap method.
-
- Args:
- method: Original method being wrapped.
-
- Returns:
- 'invoke_remote_method' function responsible for actual invocation.
- This invocation function instance is assigned an attribute 'remote'
- which contains information about the remote method:
- request_type: Expected request type for remote method.
- response_type: Response type returned from remote method.
-
- Raises:
- TypeError: If request_type or response_type is not a subclass of Message
- or is the Message class itself.
- """
-
- def invoke_remote_method(service_instance, request):
- """Function used to replace original method.
-
- Invoke wrapped remote method. Checks to ensure that request and
- response objects are the correct types.
-
- Does not check whether messages are initialized.
-
- Args:
- service_instance: The service object whose method is being invoked.
- This is passed to 'self' during the invocation of the original
- method.
- request: Request message.
-
- Returns:
- Results of calling wrapped remote method.
-
- Raises:
- RequestError: Request object is not of the correct type.
- ServerError: Response object is not of the correct type.
- """
- if not isinstance(request, remote_method_info.request_type):
- raise RequestError('Method %s.%s expected request type %s, '
- 'received %s' %
- (type(service_instance).__name__,
- method.__name__,
- remote_method_info.request_type,
- type(request)))
- response = method(service_instance, request)
- if not isinstance(response, remote_method_info.response_type):
- raise ServerError('Method %s.%s expected response type %s, '
- 'sent %s' %
- (type(service_instance).__name__,
- method.__name__,
- remote_method_info.response_type,
- type(response)))
- return response
-
- remote_method_info = _RemoteMethodInfo(method,
- request_type,
- response_type)
-
- invoke_remote_method.remote = remote_method_info
- invoke_remote_method.__name__ = method.__name__
- return invoke_remote_method
-
- return remote_method_wrapper
-
-
-def remote(request_type, response_type):
- """Temporary backward compatibility alias for method."""
- logging.warning('The remote decorator has been renamed method. It will be '
- 'removed in very soon from future versions of ProtoRPC.')
- return method(request_type, response_type)
-
-
-def get_remote_method_info(method):
- """Get remote method info object from remote method.
-
- Returns:
- Remote method info object if method is a remote method, else None.
- """
- if not callable(method):
- return None
-
- try:
- method_info = method.remote
- except AttributeError:
- return None
-
- if not isinstance(method_info, _RemoteMethodInfo):
- return None
-
- return method_info
-
-
-class StubBase(object):
- """Base class for client side service stubs.
-
- The remote method stubs are created by the _ServiceClass meta-class
- when a Service class is first created. The resulting stub will
- extend both this class and the service class it handles communications for.
-
- Assume that there is a service:
-
- class NewContactRequest(messages.Message):
-
- name = messages.StringField(1, required=True)
- phone = messages.StringField(2)
- email = messages.StringField(3)
-
- class NewContactResponse(message.Message):
-
- contact_id = messages.StringField(1)
-
- class AccountService(remote.Service):
-
- @remote.method(NewContactRequest, NewContactResponse):
- def new_contact(self, request):
- ... implementation ...
-
- A stub of this service can be called in two ways. The first is to pass in a
- correctly initialized NewContactRequest message:
-
- request = NewContactRequest()
- request.name = 'Bob Somebody'
- request.phone = '+1 415 555 1234'
-
- response = account_service_stub.new_contact(request)
-
- The second way is to pass in keyword parameters that correspond with the root
- request message type:
-
- account_service_stub.new_contact(name='Bob Somebody',
- phone='+1 415 555 1234')
-
- The second form will create a request message of the appropriate type.
- """
-
- def __init__(self, transport):
- """Constructor.
-
- Args:
- transport: Underlying transport to communicate with remote service.
- """
- self.__transport = transport
-
- @property
- def transport(self):
- """Transport used to communicate with remote service."""
- return self.__transport
-
-
-class _ServiceClass(type):
- """Meta-class for service class."""
-
- def __new_async_method(cls, remote):
- """Create asynchronous method for Async handler.
-
- Args:
- remote: RemoteInfo to create method for.
- """
- def async_method(self, *args, **kwargs):
- """Asynchronous remote method.
-
- Args:
- self: Instance of StubBase.Async subclass.
-
- Stub methods either take a single positional argument when a full
- request message is passed in, or keyword arguments, but not both.
-
- See docstring for StubBase for more information on how to use remote
- stub methods.
-
- Returns:
- Rpc instance used to represent asynchronous RPC.
- """
- if args and kwargs:
- raise TypeError('May not provide both args and kwargs')
-
- if not args:
- # Construct request object from arguments.
- request = remote.request_type()
- for name, value in six.iteritems(kwargs):
- setattr(request, name, value)
- else:
- # First argument is request object.
- request = args[0]
-
- return self.transport.send_rpc(remote, request)
-
- async_method.__name__ = remote.method.__name__
- async_method = util.positional(2)(async_method)
- async_method.remote = remote
- return async_method
-
- def __new_sync_method(cls, async_method):
- """Create synchronous method for stub.
-
- Args:
- async_method: asynchronous method to delegate calls to.
- """
- def sync_method(self, *args, **kwargs):
- """Synchronous remote method.
-
- Args:
- self: Instance of StubBase.Async subclass.
- args: Tuple (request,):
- request: Request object.
- kwargs: Field values for request. Must be empty if request object
- is provided.
-
- Returns:
- Response message from synchronized RPC.
- """
- return async_method(self.async, *args, **kwargs).response
- sync_method.__name__ = async_method.__name__
- sync_method.remote = async_method.remote
- return sync_method
-
- def __create_async_methods(cls, remote_methods):
- """Construct a dictionary of asynchronous methods based on remote methods.
-
- Args:
- remote_methods: Dictionary of methods with associated RemoteInfo objects.
-
- Returns:
- Dictionary of asynchronous methods with assocaited RemoteInfo objects.
- Results added to AsyncStub subclass.
- """
- async_methods = {}
- for method_name, method in remote_methods.items():
- async_methods[method_name] = cls.__new_async_method(method.remote)
- return async_methods
-
- def __create_sync_methods(cls, async_methods):
- """Construct a dictionary of synchronous methods based on remote methods.
-
- Args:
- async_methods: Dictionary of async methods to delegate calls to.
-
- Returns:
- Dictionary of synchronous methods with assocaited RemoteInfo objects.
- Results added to Stub subclass.
- """
- sync_methods = {}
- for method_name, async_method in async_methods.items():
- sync_methods[method_name] = cls.__new_sync_method(async_method)
- return sync_methods
-
- def __new__(cls, name, bases, dct):
- """Instantiate new service class instance."""
- if StubBase not in bases:
- # Collect existing remote methods.
- base_methods = {}
- for base in bases:
- try:
- remote_methods = base.__remote_methods
- except AttributeError:
- pass
- else:
- base_methods.update(remote_methods)
-
- # Set this class private attribute so that base_methods do not have
- # to be recacluated in __init__.
- dct['_ServiceClass__base_methods'] = base_methods
-
- for attribute, value in dct.items():
- base_method = base_methods.get(attribute, None)
- if base_method:
- if not callable(value):
- raise ServiceDefinitionError(
- 'Must override %s in %s with a method.' % (
- attribute, name))
-
- if get_remote_method_info(value):
- raise ServiceDefinitionError(
- 'Do not use method decorator when overloading remote method %s '
- 'on service %s.' %
- (attribute, name))
-
- base_remote_method_info = get_remote_method_info(base_method)
- remote_decorator = method(
- base_remote_method_info.request_type,
- base_remote_method_info.response_type)
- new_remote_method = remote_decorator(value)
- dct[attribute] = new_remote_method
-
- return type.__new__(cls, name, bases, dct)
-
- def __init__(cls, name, bases, dct):
- """Create uninitialized state on new class."""
- type.__init__(cls, name, bases, dct)
-
- # Only service implementation classes should have remote methods and stub
- # sub classes created. Stub implementations have their own methods passed
- # in to the type constructor.
- if StubBase not in bases:
- # Create list of remote methods.
- cls.__remote_methods = dict(cls.__base_methods)
-
- for attribute, value in dct.items():
- value = getattr(cls, attribute)
- remote_method_info = get_remote_method_info(value)
- if remote_method_info:
- cls.__remote_methods[attribute] = value
-
- # Build asynchronous stub class.
- stub_attributes = {'Service': cls}
- async_methods = cls.__create_async_methods(cls.__remote_methods)
- stub_attributes.update(async_methods)
- async_class = type('AsyncStub', (StubBase, cls), stub_attributes)
- cls.AsyncStub = async_class
-
- # Constructor for synchronous stub class.
- def __init__(self, transport):
- """Constructor.
-
- Args:
- transport: Underlying transport to communicate with remote service.
- """
- super(cls.Stub, self).__init__(transport)
- self.async = cls.AsyncStub(transport)
-
- # Build synchronous stub class.
- stub_attributes = {'Service': cls,
- '__init__': __init__}
- stub_attributes.update(cls.__create_sync_methods(async_methods))
-
- cls.Stub = type('Stub', (StubBase, cls), stub_attributes)
-
- @staticmethod
- def all_remote_methods(cls):
- """Get all remote methods of service.
-
- Returns:
- Dict from method name to unbound method.
- """
- return dict(cls.__remote_methods)
-
-
-class RequestState(object):
- """Request state information.
-
- Properties:
- remote_host: Remote host name where request originated.
- remote_address: IP address where request originated.
- server_host: Host of server within which service resides.
- server_port: Post which service has recevied request from.
- """
-
- @util.positional(1)
- def __init__(self,
- remote_host=None,
- remote_address=None,
- server_host=None,
- server_port=None):
- """Constructor.
-
- Args:
- remote_host: Assigned to property.
- remote_address: Assigned to property.
- server_host: Assigned to property.
- server_port: Assigned to property.
- """
- self.__remote_host = remote_host
- self.__remote_address = remote_address
- self.__server_host = server_host
- self.__server_port = server_port
-
- @property
- def remote_host(self):
- return self.__remote_host
-
- @property
- def remote_address(self):
- return self.__remote_address
-
- @property
- def server_host(self):
- return self.__server_host
-
- @property
- def server_port(self):
- return self.__server_port
-
- def _repr_items(self):
- for name in ['remote_host',
- 'remote_address',
- 'server_host',
- 'server_port']:
- yield name, getattr(self, name)
-
- def __repr__(self):
- """String representation of state."""
- state = [self.__class__.__name__]
- for name, value in self._repr_items():
- if value:
- state.append('%s=%r' % (name, value))
-
- return '<%s>' % (' '.join(state),)
-
-
-class HttpRequestState(RequestState):
- """HTTP request state information.
-
- NOTE: Does not attempt to represent certain types of information from the
- request such as the query string as query strings are not permitted in
- ProtoRPC URLs unless required by the underlying message format.
-
- Properties:
- headers: wsgiref.headers.Headers instance of HTTP request headers.
- http_method: HTTP method as a string.
- service_path: Path on HTTP service where service is mounted. This path
- will not include the remote method name.
- """
-
- @util.positional(1)
- def __init__(self,
- http_method=None,
- service_path=None,
- headers=None,
- **kwargs):
- """Constructor.
-
- Args:
- Same as RequestState, including:
- http_method: Assigned to property.
- service_path: Assigned to property.
- headers: HTTP request headers. If instance of Headers, assigned to
- property without copying. If dict, will convert to name value pairs
- for use with Headers constructor. Otherwise, passed as parameters to
- Headers constructor.
- """
- super(HttpRequestState, self).__init__(**kwargs)
-
- self.__http_method = http_method
- self.__service_path = service_path
-
- # Initialize headers.
- if isinstance(headers, dict):
- header_list = []
- for key, value in sorted(headers.items()):
- if not isinstance(value, list):
- value = [value]
- for item in value:
- header_list.append((key, item))
- headers = header_list
- self.__headers = wsgi_headers.Headers(headers or [])
-
- @property
- def http_method(self):
- return self.__http_method
-
- @property
- def service_path(self):
- return self.__service_path
-
- @property
- def headers(self):
- return self.__headers
-
- def _repr_items(self):
- for item in super(HttpRequestState, self)._repr_items():
- yield item
-
- for name in ['http_method', 'service_path']:
- yield name, getattr(self, name)
-
- yield 'headers', list(self.headers.items())
-
-
-class Service(six.with_metaclass(_ServiceClass, object)):
- """Service base class.
-
- Base class used for defining remote services. Contains reflection functions,
- useful helpers and built-in remote methods.
-
- Services are expected to be constructed via either a constructor or factory
- which takes no parameters. However, it might be required that some state or
- configuration is passed in to a service across multiple requests.
-
- To do this, define parameters to the constructor of the service and use
- the 'new_factory' class method to build a constructor that will transmit
- parameters to the constructor. For example:
-
- class MyService(Service):
-
- def __init__(self, configuration, state):
- self.configuration = configuration
- self.state = state
-
- configuration = MyServiceConfiguration()
- global_state = MyServiceState()
-
- my_service_factory = MyService.new_factory(configuration,
- state=global_state)
-
- The contract with any service handler is that a new service object is created
- to handle each user request, and that the construction does not take any
- parameters. The factory satisfies this condition:
-
- new_instance = my_service_factory()
- assert new_instance.state is global_state
-
- Attributes:
- request_state: RequestState set via initialize_request_state.
- """
-
- __request_state = None
-
- @classmethod
- def all_remote_methods(cls):
- """Get all remote methods for service class.
-
- Built-in methods do not appear in the dictionary of remote methods.
-
- Returns:
- Dictionary mapping method name to remote method.
- """
- return _ServiceClass.all_remote_methods(cls)
-
- @classmethod
- def new_factory(cls, *args, **kwargs):
- """Create factory for service.
-
- Useful for passing configuration or state objects to the service. Accepts
- arbitrary parameters and keywords, however, underlying service must accept
- also accept not other parameters in its constructor.
-
- Args:
- args: Args to pass to service constructor.
- kwargs: Keyword arguments to pass to service constructor.
-
- Returns:
- Factory function that will create a new instance and forward args and
- keywords to the constructor.
- """
-
- def service_factory():
- return cls(*args, **kwargs)
-
- # Update docstring so that it is easier to debug.
- full_class_name = '%s.%s' % (cls.__module__, cls.__name__)
- service_factory.__doc__ = (
- 'Creates new instances of service %s.\n\n'
- 'Returns:\n'
- ' New instance of %s.'
- % (cls.__name__, full_class_name))
-
- # Update name so that it is easier to debug the factory function.
- service_factory.__name__ = '%s_service_factory' % cls.__name__
-
- service_factory.service_class = cls
-
- return service_factory
-
- def initialize_request_state(self, request_state):
- """Save request state for use in remote method.
-
- Args:
- request_state: RequestState instance.
- """
- self.__request_state = request_state
-
- @classmethod
- def definition_name(cls):
- """Get definition name for Service class.
-
- Package name is determined by the global 'package' attribute in the
- module that contains the Service definition. If no 'package' attribute
- is available, uses module name. If no module is found, just uses class
- name as name.
-
- Returns:
- Fully qualified service name.
- """
- try:
- return cls.__definition_name
- except AttributeError:
- outer_definition_name = cls.outer_definition_name()
- if outer_definition_name is None:
- cls.__definition_name = cls.__name__
- else:
- cls.__definition_name = '%s.%s' % (outer_definition_name, cls.__name__)
-
- return cls.__definition_name
-
- @classmethod
- def outer_definition_name(cls):
- """Get outer definition name.
-
- Returns:
- Package for service. Services are never nested inside other definitions.
- """
- return cls.definition_package()
-
- @classmethod
- def definition_package(cls):
- """Get package for service.
-
- Returns:
- Package name for service.
- """
- try:
- return cls.__definition_package
- except AttributeError:
- cls.__definition_package = util.get_package_for_module(cls.__module__)
-
- return cls.__definition_package
-
- @property
- def request_state(self):
- """Request state associated with this Service instance."""
- return self.__request_state
-
-
-def is_error_status(status):
- """Function that determines whether the RPC status is an error.
-
- Args:
- status: Initialized RpcStatus message to check for errors.
- """
- status.check_initialized()
- return RpcError.from_state(status.state) is not None
-
-
-def check_rpc_status(status):
- """Function converts an error status to a raised exception.
-
- Args:
- status: Initialized RpcStatus message to check for errors.
-
- Raises:
- RpcError according to state set on status, if it is an error state.
- """
- status.check_initialized()
- error_class = RpcError.from_state(status.state)
- if error_class is not None:
- if error_class is ApplicationError:
- raise error_class(status.error_message, status.error_name)
- else:
- raise error_class(status.error_message)
-
-
-class ProtocolConfig(object):
- """Configuration for single protocol mapping.
-
- A read-only protocol configuration provides a given protocol implementation
- with a name and a set of content-types that it recognizes.
-
- Properties:
- protocol: The protocol implementation for configuration (usually a module,
- for example, protojson, protobuf, etc.). This is an object that has the
- following attributes:
- CONTENT_TYPE: Used as the default content-type if default_content_type
- is not set.
- ALTERNATIVE_CONTENT_TYPES (optional): A list of alternative
- content-types to the default that indicate the same protocol.
- encode_message: Function that matches the signature of
- ProtocolConfig.encode_message. Used for encoding a ProtoRPC message.
- decode_message: Function that matches the signature of
- ProtocolConfig.decode_message. Used for decoding a ProtoRPC message.
- name: Name of protocol configuration.
- default_content_type: The default content type for the protocol. Overrides
- CONTENT_TYPE defined on protocol.
- alternative_content_types: A list of alternative content-types supported
- by the protocol. Must not contain the default content-type, nor
- duplicates. Overrides ALTERNATIVE_CONTENT_TYPE defined on protocol.
- content_types: A list of all content-types supported by configuration.
- Combination of default content-type and alternatives.
- """
-
- def __init__(self,
- protocol,
- name,
- default_content_type=None,
- alternative_content_types=None):
- """Constructor.
-
- Args:
- protocol: The protocol implementation for configuration.
- name: The name of the protocol configuration.
- default_content_type: The default content-type for protocol. If none
- provided it will check protocol.CONTENT_TYPE.
- alternative_content_types: A list of content-types. If none provided,
- it will check protocol.ALTERNATIVE_CONTENT_TYPES. If that attribute
- does not exist, will be an empty tuple.
-
- Raises:
- ServiceConfigurationError if there are any duplicate content-types.
- """
- self.__protocol = protocol
- self.__name = name
- self.__default_content_type = (default_content_type or
- protocol.CONTENT_TYPE).lower()
- if alternative_content_types is None:
- alternative_content_types = getattr(protocol,
- 'ALTERNATIVE_CONTENT_TYPES',
- ())
- self.__alternative_content_types = tuple(
- content_type.lower() for content_type in alternative_content_types)
- self.__content_types = (
- (self.__default_content_type,) + self.__alternative_content_types)
-
- # Detect duplicate content types in definition.
- previous_type = None
- for content_type in sorted(self.content_types):
- if content_type == previous_type:
- raise ServiceConfigurationError(
- 'Duplicate content-type %s' % content_type)
- previous_type = content_type
-
- @property
- def protocol(self):
- return self.__protocol
-
- @property
- def name(self):
- return self.__name
-
- @property
- def default_content_type(self):
- return self.__default_content_type
-
- @property
- def alternate_content_types(self):
- return self.__alternative_content_types
-
- @property
- def content_types(self):
- return self.__content_types
-
- def encode_message(self, message):
- """Encode message.
-
- Args:
- message: Message instance to encode.
-
- Returns:
- String encoding of Message instance encoded in protocol's format.
- """
- return self.__protocol.encode_message(message)
-
- def decode_message(self, message_type, encoded_message):
- """Decode buffer to Message instance.
-
- Args:
- message_type: Message type to decode data to.
- encoded_message: Encoded version of message as string.
-
- Returns:
- Decoded instance of message_type.
- """
- return self.__protocol.decode_message(message_type, encoded_message)
-
-
-class Protocols(object):
- """Collection of protocol configurations.
-
- Used to describe a complete set of content-type mappings for multiple
- protocol configurations.
-
- Properties:
- names: Sorted list of the names of registered protocols.
- content_types: Sorted list of supported content-types.
- """
-
- __default_protocols = None
- __lock = threading.Lock()
-
- def __init__(self):
- """Constructor."""
- self.__by_name = {}
- self.__by_content_type = {}
-
- def add_protocol_config(self, config):
- """Add a protocol configuration to protocol mapping.
-
- Args:
- config: A ProtocolConfig.
-
- Raises:
- ServiceConfigurationError if protocol.name is already registered
- or any of it's content-types are already registered.
- """
- if config.name in self.__by_name:
- raise ServiceConfigurationError(
- 'Protocol name %r is already in use' % config.name)
- for content_type in config.content_types:
- if content_type in self.__by_content_type:
- raise ServiceConfigurationError(
- 'Content type %r is already in use' % content_type)
-
- self.__by_name[config.name] = config
- self.__by_content_type.update((t, config) for t in config.content_types)
-
- def add_protocol(self, *args, **kwargs):
- """Add a protocol configuration from basic parameters.
-
- Simple helper method that creates and registeres a ProtocolConfig instance.
- """
- self.add_protocol_config(ProtocolConfig(*args, **kwargs))
-
- @property
- def names(self):
- return tuple(sorted(self.__by_name))
-
- @property
- def content_types(self):
- return tuple(sorted(self.__by_content_type))
-
- def lookup_by_name(self, name):
- """Look up a ProtocolConfig by name.
-
- Args:
- name: Name of protocol to look for.
-
- Returns:
- ProtocolConfig associated with name.
-
- Raises:
- KeyError if there is no protocol for name.
- """
- return self.__by_name[name.lower()]
-
- def lookup_by_content_type(self, content_type):
- """Look up a ProtocolConfig by content-type.
-
- Args:
- content_type: Content-type to find protocol configuration for.
-
- Returns:
- ProtocolConfig associated with content-type.
-
- Raises:
- KeyError if there is no protocol for content-type.
- """
- return self.__by_content_type[content_type.lower()]
-
- @classmethod
- def new_default(cls):
- """Create default protocols configuration.
-
- Returns:
- New Protocols instance configured for protobuf and protorpc.
- """
- protocols = cls()
- protocols.add_protocol(protobuf, 'protobuf')
- protocols.add_protocol(protojson.ProtoJson.get_default(), 'protojson')
- return protocols
-
- @classmethod
- def get_default(cls):
- """Get the global default Protocols instance.
-
- Returns:
- Current global default Protocols instance.
- """
- default_protocols = cls.__default_protocols
- if default_protocols is None:
- with cls.__lock:
- default_protocols = cls.__default_protocols
- if default_protocols is None:
- default_protocols = cls.new_default()
- cls.__default_protocols = default_protocols
- return default_protocols
-
- @classmethod
- def set_default(cls, protocols):
- """Set the global default Protocols instance.
-
- Args:
- protocols: A Protocols instance.
-
- Raises:
- TypeError: If protocols is not an instance of Protocols.
- """
- if not isinstance(protocols, Protocols):
- raise TypeError(
- 'Expected value of type "Protocols", found %r' % protocols)
- with cls.__lock:
- cls.__default_protocols = protocols

Powered by Google App Engine
This is Rietveld 408576698