Index: tools/telemetry/third_party/gsutil/third_party/protorpc/protorpc/protojson.py |
diff --git a/tools/telemetry/third_party/gsutil/third_party/protorpc/protorpc/protojson.py b/tools/telemetry/third_party/gsutil/third_party/protorpc/protorpc/protojson.py |
deleted file mode 100644 |
index a269fa25996c0fb093e4209a88b0d9a6e4963afb..0000000000000000000000000000000000000000 |
--- a/tools/telemetry/third_party/gsutil/third_party/protorpc/protorpc/protojson.py |
+++ /dev/null |
@@ -1,366 +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. |
-# |
- |
-"""JSON support for message types. |
- |
-Public classes: |
- MessageJSONEncoder: JSON encoder for message objects. |
- |
-Public functions: |
- encode_message: Encodes a message in to a JSON string. |
- decode_message: Merge from a JSON string in to a message. |
-""" |
-import six |
- |
-__author__ = 'rafek@google.com (Rafe Kaplan)' |
- |
-import base64 |
-import binascii |
-import logging |
- |
-from . import message_types |
-from . import messages |
-from . import util |
- |
-__all__ = [ |
- 'ALTERNATIVE_CONTENT_TYPES', |
- 'CONTENT_TYPE', |
- 'MessageJSONEncoder', |
- 'encode_message', |
- 'decode_message', |
- 'ProtoJson', |
-] |
- |
- |
-def _load_json_module(): |
- """Try to load a valid json module. |
- |
- There are more than one json modules that might be installed. They are |
- mostly compatible with one another but some versions may be different. |
- This function attempts to load various json modules in a preferred order. |
- It does a basic check to guess if a loaded version of json is compatible. |
- |
- Returns: |
- Compatible json module. |
- |
- Raises: |
- ImportError if there are no json modules or the loaded json module is |
- not compatible with ProtoRPC. |
- """ |
- first_import_error = None |
- for module_name in ['json', |
- 'simplejson']: |
- try: |
- module = __import__(module_name, {}, {}, 'json') |
- if not hasattr(module, 'JSONEncoder'): |
- message = ('json library "%s" is not compatible with ProtoRPC' % |
- module_name) |
- logging.warning(message) |
- raise ImportError(message) |
- else: |
- return module |
- except ImportError as err: |
- if not first_import_error: |
- first_import_error = err |
- |
- logging.error('Must use valid json library (Python 2.6 json or simplejson)') |
- raise first_import_error |
-json = _load_json_module() |
- |
- |
-# TODO: Rename this to MessageJsonEncoder. |
-class MessageJSONEncoder(json.JSONEncoder): |
- """Message JSON encoder class. |
- |
- Extension of JSONEncoder that can build JSON from a message object. |
- """ |
- |
- def __init__(self, protojson_protocol=None, **kwargs): |
- """Constructor. |
- |
- Args: |
- protojson_protocol: ProtoJson instance. |
- """ |
- super(MessageJSONEncoder, self).__init__(**kwargs) |
- self.__protojson_protocol = protojson_protocol or ProtoJson.get_default() |
- |
- def default(self, value): |
- """Return dictionary instance from a message object. |
- |
- Args: |
- value: Value to get dictionary for. If not encodable, will |
- call superclasses default method. |
- """ |
- if isinstance(value, messages.Enum): |
- return str(value) |
- |
- if six.PY3 and isinstance(value, bytes): |
- return value.decode('utf8') |
- |
- if isinstance(value, messages.Message): |
- result = {} |
- for field in value.all_fields(): |
- item = value.get_assigned_value(field.name) |
- if item not in (None, [], ()): |
- result[field.name] = self.__protojson_protocol.encode_field( |
- field, item) |
- # Handle unrecognized fields, so they're included when a message is |
- # decoded then encoded. |
- for unknown_key in value.all_unrecognized_fields(): |
- unrecognized_field, _ = value.get_unrecognized_field_info(unknown_key) |
- result[unknown_key] = unrecognized_field |
- return result |
- else: |
- return super(MessageJSONEncoder, self).default(value) |
- |
- |
-class ProtoJson(object): |
- """ProtoRPC JSON implementation class. |
- |
- Implementation of JSON based protocol used for serializing and deserializing |
- message objects. Instances of remote.ProtocolConfig constructor or used with |
- remote.Protocols.add_protocol. See the remote.py module for more details. |
- """ |
- |
- CONTENT_TYPE = 'application/json' |
- ALTERNATIVE_CONTENT_TYPES = [ |
- 'application/x-javascript', |
- 'text/javascript', |
- 'text/x-javascript', |
- 'text/x-json', |
- 'text/json', |
- ] |
- |
- def encode_field(self, field, value): |
- """Encode a python field value to a JSON value. |
- |
- Args: |
- field: A ProtoRPC field instance. |
- value: A python value supported by field. |
- |
- Returns: |
- A JSON serializable value appropriate for field. |
- """ |
- if isinstance(field, messages.BytesField): |
- if field.repeated: |
- value = [base64.b64encode(byte) for byte in value] |
- else: |
- value = base64.b64encode(value) |
- elif isinstance(field, message_types.DateTimeField): |
- # DateTimeField stores its data as a RFC 3339 compliant string. |
- if field.repeated: |
- value = [i.isoformat() for i in value] |
- else: |
- value = value.isoformat() |
- return value |
- |
- def encode_message(self, message): |
- """Encode Message instance to JSON string. |
- |
- Args: |
- Message instance to encode in to JSON string. |
- |
- Returns: |
- String encoding of Message instance in protocol JSON format. |
- |
- Raises: |
- messages.ValidationError if message is not initialized. |
- """ |
- message.check_initialized() |
- |
- return json.dumps(message, cls=MessageJSONEncoder, protojson_protocol=self) |
- |
- def decode_message(self, message_type, encoded_message): |
- """Merge JSON structure to Message instance. |
- |
- Args: |
- message_type: Message to decode data to. |
- encoded_message: JSON encoded version of message. |
- |
- Returns: |
- Decoded instance of message_type. |
- |
- Raises: |
- ValueError: If encoded_message is not valid JSON. |
- messages.ValidationError if merged message is not initialized. |
- """ |
- if not encoded_message.strip(): |
- return message_type() |
- |
- dictionary = json.loads(encoded_message) |
- message = self.__decode_dictionary(message_type, dictionary) |
- message.check_initialized() |
- return message |
- |
- def __find_variant(self, value): |
- """Find the messages.Variant type that describes this value. |
- |
- Args: |
- value: The value whose variant type is being determined. |
- |
- Returns: |
- The messages.Variant value that best describes value's type, or None if |
- it's a type we don't know how to handle. |
- """ |
- if isinstance(value, bool): |
- return messages.Variant.BOOL |
- elif isinstance(value, six.integer_types): |
- return messages.Variant.INT64 |
- elif isinstance(value, float): |
- return messages.Variant.DOUBLE |
- elif isinstance(value, six.string_types): |
- return messages.Variant.STRING |
- elif isinstance(value, (list, tuple)): |
- # Find the most specific variant that covers all elements. |
- variant_priority = [None, messages.Variant.INT64, messages.Variant.DOUBLE, |
- messages.Variant.STRING] |
- chosen_priority = 0 |
- for v in value: |
- variant = self.__find_variant(v) |
- try: |
- priority = variant_priority.index(variant) |
- except IndexError: |
- priority = -1 |
- if priority > chosen_priority: |
- chosen_priority = priority |
- return variant_priority[chosen_priority] |
- # Unrecognized type. |
- return None |
- |
- def __decode_dictionary(self, message_type, dictionary): |
- """Merge dictionary in to message. |
- |
- Args: |
- message: Message to merge dictionary in to. |
- dictionary: Dictionary to extract information from. Dictionary |
- is as parsed from JSON. Nested objects will also be dictionaries. |
- """ |
- message = message_type() |
- for key, value in six.iteritems(dictionary): |
- if value is None: |
- try: |
- message.reset(key) |
- except AttributeError: |
- pass # This is an unrecognized field, skip it. |
- continue |
- |
- try: |
- field = message.field_by_name(key) |
- except KeyError: |
- # Save unknown values. |
- variant = self.__find_variant(value) |
- if variant: |
- if key.isdigit(): |
- key = int(key) |
- message.set_unrecognized_field(key, value, variant) |
- else: |
- logging.warning('No variant found for unrecognized field: %s', key) |
- continue |
- |
- # Normalize values in to a list. |
- if isinstance(value, list): |
- if not value: |
- continue |
- else: |
- value = [value] |
- |
- valid_value = [] |
- for item in value: |
- valid_value.append(self.decode_field(field, item)) |
- |
- if field.repeated: |
- existing_value = getattr(message, field.name) |
- setattr(message, field.name, valid_value) |
- else: |
- setattr(message, field.name, valid_value[-1]) |
- return message |
- |
- def decode_field(self, field, value): |
- """Decode a JSON value to a python value. |
- |
- Args: |
- field: A ProtoRPC field instance. |
- value: A serialized JSON value. |
- |
- Return: |
- A Python value compatible with field. |
- """ |
- if isinstance(field, messages.EnumField): |
- try: |
- return field.type(value) |
- except TypeError: |
- raise messages.DecodeError('Invalid enum value "%s"' % (value or '')) |
- |
- elif isinstance(field, messages.BytesField): |
- try: |
- return base64.b64decode(value) |
- except (binascii.Error, TypeError) as err: |
- raise messages.DecodeError('Base64 decoding error: %s' % err) |
- |
- elif isinstance(field, message_types.DateTimeField): |
- try: |
- return util.decode_datetime(value) |
- except ValueError as err: |
- raise messages.DecodeError(err) |
- |
- elif (isinstance(field, messages.MessageField) and |
- issubclass(field.type, messages.Message)): |
- return self.__decode_dictionary(field.type, value) |
- |
- elif (isinstance(field, messages.FloatField) and |
- isinstance(value, (six.integer_types, six.string_types))): |
- try: |
- return float(value) |
- except: |
- pass |
- |
- elif (isinstance(field, messages.IntegerField) and |
- isinstance(value, six.string_types)): |
- try: |
- return int(value) |
- except: |
- pass |
- |
- return value |
- |
- @staticmethod |
- def get_default(): |
- """Get default instanceof ProtoJson.""" |
- try: |
- return ProtoJson.__default |
- except AttributeError: |
- ProtoJson.__default = ProtoJson() |
- return ProtoJson.__default |
- |
- @staticmethod |
- def set_default(protocol): |
- """Set the default instance of ProtoJson. |
- |
- Args: |
- protocol: A ProtoJson instance. |
- """ |
- if not isinstance(protocol, ProtoJson): |
- raise TypeError('Expected protocol of type ProtoJson') |
- ProtoJson.__default = protocol |
- |
-CONTENT_TYPE = ProtoJson.CONTENT_TYPE |
- |
-ALTERNATIVE_CONTENT_TYPES = ProtoJson.ALTERNATIVE_CONTENT_TYPES |
- |
-encode_message = ProtoJson.get_default().encode_message |
- |
-decode_message = ProtoJson.get_default().decode_message |