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

Unified Diff: tools/telemetry/third_party/gsutil/third_party/protorpc/protorpc/protourlencode.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/protourlencode.py
diff --git a/tools/telemetry/third_party/gsutil/third_party/protorpc/protorpc/protourlencode.py b/tools/telemetry/third_party/gsutil/third_party/protorpc/protorpc/protourlencode.py
deleted file mode 100644
index 9f6059e090178f6770a9c84f2a2b7af0a1171585..0000000000000000000000000000000000000000
--- a/tools/telemetry/third_party/gsutil/third_party/protorpc/protorpc/protourlencode.py
+++ /dev/null
@@ -1,563 +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.
-#
-
-"""URL encoding support for messages types.
-
-Protocol support for URL encoded form parameters.
-
-Nested Fields:
- Nested fields are repesented by dot separated names. For example, consider
- the following messages:
-
- class WebPage(Message):
-
- title = StringField(1)
- tags = StringField(2, repeated=True)
-
- class WebSite(Message):
-
- name = StringField(1)
- home = MessageField(WebPage, 2)
- pages = MessageField(WebPage, 3, repeated=True)
-
- And consider the object:
-
- page = WebPage()
- page.title = 'Welcome to NewSite 2010'
-
- site = WebSite()
- site.name = 'NewSite 2010'
- site.home = page
-
- The URL encoded representation of this constellation of objects is.
-
- name=NewSite+2010&home.title=Welcome+to+NewSite+2010
-
- An object that exists but does not have any state can be represented with
- a reference to its name alone with no value assigned to it. For example:
-
- page = WebSite()
- page.name = 'My Empty Site'
- page.home = WebPage()
-
- is represented as:
-
- name=My+Empty+Site&home=
-
- This represents a site with an empty uninitialized home page.
-
-Repeated Fields:
- Repeated fields are represented by the name of and the index of each value
- separated by a dash. For example, consider the following message:
-
- home = Page()
- home.title = 'Nome'
-
- news = Page()
- news.title = 'News'
- news.tags = ['news', 'articles']
-
- instance = WebSite()
- instance.name = 'Super fun site'
- instance.pages = [home, news, preferences]
-
- An instance of this message can be represented as:
-
- name=Super+fun+site&page-0.title=Home&pages-1.title=News&...
- pages-1.tags-0=new&pages-1.tags-1=articles
-
-Helper classes:
-
- URLEncodedRequestBuilder: Used for encapsulating the logic used for building
- a request message from a URL encoded RPC.
-"""
-import six
-
-__author__ = 'rafek@google.com (Rafe Kaplan)'
-
-import cgi
-import re
-import urllib
-
-from . import message_types
-from . import messages
-from . import util
-
-__all__ = ['CONTENT_TYPE',
- 'URLEncodedRequestBuilder',
- 'encode_message',
- 'decode_message',
- ]
-
-CONTENT_TYPE = 'application/x-www-form-urlencoded'
-
-_FIELD_NAME_REGEX = re.compile(r'^([a-zA-Z_][a-zA-Z_0-9]*)(?:-([0-9]+))?$')
-
-
-class URLEncodedRequestBuilder(object):
- """Helper that encapsulates the logic used for building URL encoded messages.
-
- This helper is used to map query parameters from a URL encoded RPC to a
- message instance.
- """
-
- @util.positional(2)
- def __init__(self, message, prefix=''):
- """Constructor.
-
- Args:
- message: Message instance to build from parameters.
- prefix: Prefix expected at the start of valid parameters.
- """
- self.__parameter_prefix = prefix
-
- # The empty tuple indicates the root message, which has no path.
- # __messages is a full cache that makes it very easy to look up message
- # instances by their paths. See make_path for details about what a path
- # is.
- self.__messages = {(): message}
-
- # This is a cache that stores paths which have been checked for
- # correctness. Correctness means that an index is present for repeated
- # fields on the path and absent for non-repeated fields. The cache is
- # also used to check that indexes are added in the right order so that
- # dicontiguous ranges of indexes are ignored.
- self.__checked_indexes = set([()])
-
- def make_path(self, parameter_name):
- """Parse a parameter name and build a full path to a message value.
-
- The path of a method is a tuple of 2-tuples describing the names and
- indexes within repeated fields from the root message (the message being
- constructed by the builder) to an arbitrarily nested message within it.
-
- Each 2-tuple node of a path (name, index) is:
- name: The name of the field that refers to the message instance.
- index: The index within a repeated field that refers to the message
- instance, None if not a repeated field.
-
- For example, consider:
-
- class VeryInner(messages.Message):
- ...
-
- class Inner(messages.Message):
-
- very_inner = messages.MessageField(VeryInner, 1, repeated=True)
-
- class Outer(messages.Message):
-
- inner = messages.MessageField(Inner, 1)
-
- If this builder is building an instance of Outer, that instance is
- referred to in the URL encoded parameters without a path. Therefore
- its path is ().
-
- The child 'inner' is referred to by its path (('inner', None)).
-
- The first child of repeated field 'very_inner' on the Inner instance
- is referred to by (('inner', None), ('very_inner', 0)).
-
- Examples:
- # Correct reference to model where nation is a Message, district is
- # repeated Message and county is any not repeated field type.
- >>> make_path('nation.district-2.county')
- (('nation', None), ('district', 2), ('county', None))
-
- # Field is not part of model.
- >>> make_path('nation.made_up_field')
- None
-
- # nation field is not repeated and index provided.
- >>> make_path('nation-1')
- None
-
- # district field is repeated and no index provided.
- >>> make_path('nation.district')
- None
-
- Args:
- parameter_name: Name of query parameter as passed in from the request.
- in order to make a path, this parameter_name must point to a valid
- field within the message structure. Nodes of the path that refer to
- repeated fields must be indexed with a number, non repeated nodes must
- not have an index.
-
- Returns:
- Parsed version of the parameter_name as a tuple of tuples:
- attribute: Name of attribute associated with path.
- index: Postitive integer index when it is a repeated field, else None.
- Will return None if the parameter_name does not have the right prefix,
- does not point to a field within the message structure, does not have
- an index if it is a repeated field or has an index but is not a repeated
- field.
- """
- if parameter_name.startswith(self.__parameter_prefix):
- parameter_name = parameter_name[len(self.__parameter_prefix):]
- else:
- return None
-
- path = []
- name = []
- message_type = type(self.__messages[()]) # Get root message.
-
- for item in parameter_name.split('.'):
- # This will catch sub_message.real_message_field.not_real_field
- if not message_type:
- return None
-
- item_match = _FIELD_NAME_REGEX.match(item)
- if not item_match:
- return None
- attribute = item_match.group(1)
- index = item_match.group(2)
- if index:
- index = int(index)
-
- try:
- field = message_type.field_by_name(attribute)
- except KeyError:
- return None
-
- if field.repeated != (index is not None):
- return None
-
- if isinstance(field, messages.MessageField):
- message_type = field.message_type
- else:
- message_type = None
-
- # Path is valid so far. Append node and continue.
- path.append((attribute, index))
-
- return tuple(path)
-
- def __check_index(self, parent_path, name, index):
- """Check correct index use and value relative to a given path.
-
- Check that for a given path the index is present for repeated fields
- and that it is in range for the existing list that it will be inserted
- in to or appended to.
-
- Args:
- parent_path: Path to check against name and index.
- name: Name of field to check for existance.
- index: Index to check. If field is repeated, should be a number within
- range of the length of the field, or point to the next item for
- appending.
- """
- # Don't worry about non-repeated fields.
- # It's also ok if index is 0 because that means next insert will append.
- if not index:
- return True
-
- parent = self.__messages.get(parent_path, None)
- value_list = getattr(parent, name, None)
- # If the list does not exist then the index should be 0. Since it is
- # not, path is not valid.
- if not value_list:
- return False
-
- # The index must either point to an element of the list or to the tail.
- return len(value_list) >= index
-
- def __check_indexes(self, path):
- """Check that all indexes are valid and in the right order.
-
- This method must iterate over the path and check that all references
- to indexes point to an existing message or to the end of the list, meaning
- the next value should be appended to the repeated field.
-
- Args:
- path: Path to check indexes for. Tuple of 2-tuples (name, index). See
- make_path for more information.
-
- Returns:
- True if all the indexes of the path are within range, else False.
- """
- if path in self.__checked_indexes:
- return True
-
- # Start with the root message.
- parent_path = ()
-
- for name, index in path:
- next_path = parent_path + ((name, index),)
- # First look in the checked indexes cache.
- if next_path not in self.__checked_indexes:
- if not self.__check_index(parent_path, name, index):
- return False
- self.__checked_indexes.add(next_path)
-
- parent_path = next_path
-
- return True
-
- def __get_or_create_path(self, path):
- """Get a message from the messages cache or create it and add it.
-
- This method will also create any parent messages based on the path.
-
- When a new instance of a given message is created, it is stored in
- __message by its path.
-
- Args:
- path: Path of message to get. Path must be valid, in other words
- __check_index(path) returns true. Tuple of 2-tuples (name, index).
- See make_path for more information.
-
- Returns:
- Message instance if the field being pointed to by the path is a
- message, else will return None for non-message fields.
- """
- message = self.__messages.get(path, None)
- if message:
- return message
-
- parent_path = ()
- parent = self.__messages[()] # Get the root object
-
- for name, index in path:
- field = parent.field_by_name(name)
- next_path = parent_path + ((name, index),)
- next_message = self.__messages.get(next_path, None)
- if next_message is None:
- next_message = field.message_type()
- self.__messages[next_path] = next_message
- if not field.repeated:
- setattr(parent, field.name, next_message)
- else:
- list_value = getattr(parent, field.name, None)
- if list_value is None:
- setattr(parent, field.name, [next_message])
- else:
- list_value.append(next_message)
-
- parent_path = next_path
- parent = next_message
-
- return parent
-
- def add_parameter(self, parameter, values):
- """Add a single parameter.
-
- Adds a single parameter and its value to the request message.
-
- Args:
- parameter: Query string parameter to map to request.
- values: List of values to assign to request message.
-
- Returns:
- True if parameter was valid and added to the message, else False.
-
- Raises:
- DecodeError if the parameter refers to a valid field, and the values
- parameter does not have one and only one value. Non-valid query
- parameters may have multiple values and should not cause an error.
- """
- path = self.make_path(parameter)
-
- if not path:
- return False
-
- # Must check that all indexes of all items in the path are correct before
- # instantiating any of them. For example, consider:
- #
- # class Repeated(object):
- # ...
- #
- # class Inner(object):
- #
- # repeated = messages.MessageField(Repeated, 1, repeated=True)
- #
- # class Outer(object):
- #
- # inner = messages.MessageField(Inner, 1)
- #
- # instance = Outer()
- # builder = URLEncodedRequestBuilder(instance)
- # builder.add_parameter('inner.repeated')
- #
- # assert not hasattr(instance, 'inner')
- #
- # The check is done relative to the instance of Outer pass in to the
- # constructor of the builder. This instance is not referred to at all
- # because all names are assumed to be relative to it.
- #
- # The 'repeated' part of the path is not correct because it is missing an
- # index. Because it is missing an index, it should not create an instance
- # of Repeated. In this case add_parameter will return False and have no
- # side effects.
- #
- # A correct path that would cause a new Inner instance to be inserted at
- # instance.inner and a new Repeated instance to be appended to the
- # instance.inner.repeated list would be 'inner.repeated-0'.
- if not self.__check_indexes(path):
- return False
-
- # Ok to build objects.
- parent_path = path[:-1]
- parent = self.__get_or_create_path(parent_path)
- name, index = path[-1]
- field = parent.field_by_name(name)
-
- if len(values) != 1:
- raise messages.DecodeError(
- 'Found repeated values for field %s.' % field.name)
-
- value = values[0]
-
- if isinstance(field, messages.IntegerField):
- converted_value = int(value)
- elif isinstance(field, message_types.DateTimeField):
- try:
- converted_value = util.decode_datetime(value)
- except ValueError as e:
- raise messages.DecodeError(e)
- elif isinstance(field, messages.MessageField):
- # Just make sure it's instantiated. Assignment to field or
- # appending to list is done in __get_or_create_path.
- self.__get_or_create_path(path)
- return True
- elif isinstance(field, messages.StringField):
- converted_value = value.decode('utf-8')
- elif isinstance(field, messages.BooleanField):
- converted_value = value.lower() == 'true' and True or False
- else:
- try:
- converted_value = field.type(value)
- except TypeError:
- raise messages.DecodeError('Invalid enum value "%s"' % value)
-
- if field.repeated:
- value_list = getattr(parent, field.name, None)
- if value_list is None:
- setattr(parent, field.name, [converted_value])
- else:
- if index == len(value_list):
- value_list.append(converted_value)
- else:
- # Index should never be above len(value_list) because it was
- # verified during the index check above.
- value_list[index] = converted_value
- else:
- setattr(parent, field.name, converted_value)
-
- return True
-
-
-@util.positional(1)
-def encode_message(message, prefix=''):
- """Encode Message instance to url-encoded string.
-
- Args:
- message: Message instance to encode in to url-encoded string.
- prefix: Prefix to append to field names of contained values.
-
- Returns:
- String encoding of Message in URL encoded format.
-
- Raises:
- messages.ValidationError if message is not initialized.
- """
- message.check_initialized()
-
- parameters = []
- def build_message(parent, prefix):
- """Recursively build parameter list for URL response.
-
- Args:
- parent: Message to build parameters for.
- prefix: Prefix to append to field names of contained values.
-
- Returns:
- True if some value of parent was added to the parameters list,
- else False, meaning the object contained no values.
- """
- has_any_values = False
- for field in sorted(parent.all_fields(), key=lambda f: f.number):
- next_value = parent.get_assigned_value(field.name)
- if next_value is None:
- continue
-
- # Found a value. Ultimate return value should be True.
- has_any_values = True
-
- # Normalize all values in to a list.
- if not field.repeated:
- next_value = [next_value]
-
- for index, item in enumerate(next_value):
- # Create a name with an index if it is a repeated field.
- if field.repeated:
- field_name = '%s%s-%s' % (prefix, field.name, index)
- else:
- field_name = prefix + field.name
-
- if isinstance(field, message_types.DateTimeField):
- # DateTimeField stores its data as a RFC 3339 compliant string.
- parameters.append((field_name, item.isoformat()))
- elif isinstance(field, messages.MessageField):
- # Message fields must be recursed in to in order to construct
- # their component parameter values.
- if not build_message(item, field_name + '.'):
- # The nested message is empty. Append an empty value to
- # represent it.
- parameters.append((field_name, ''))
- elif isinstance(field, messages.BooleanField):
- parameters.append((field_name, item and 'true' or 'false'))
- else:
- if isinstance(item, six.text_type):
- item = item.encode('utf-8')
- parameters.append((field_name, str(item)))
-
- return has_any_values
-
- build_message(message, prefix)
-
- # Also add any unrecognized values from the decoded string.
- for key in message.all_unrecognized_fields():
- values, _ = message.get_unrecognized_field_info(key)
- if not isinstance(values, (list, tuple)):
- values = (values,)
- for value in values:
- parameters.append((key, value))
-
- return urllib.urlencode(parameters)
-
-
-def decode_message(message_type, encoded_message, **kwargs):
- """Decode urlencoded content to message.
-
- Args:
- message_type: Message instance to merge URL encoded content into.
- encoded_message: URL encoded message.
- prefix: Prefix to append to field names of contained values.
-
- Returns:
- Decoded instance of message_type.
- """
- message = message_type()
- builder = URLEncodedRequestBuilder(message, **kwargs)
- arguments = cgi.parse_qs(encoded_message, keep_blank_values=True)
- for argument, values in sorted(six.iteritems(arguments)):
- added = builder.add_parameter(argument, values)
- # Save off any unknown values, so they're still accessible.
- if not added:
- message.set_unrecognized_field(argument, values, messages.Variant.STRING)
- message.check_initialized()
- return message

Powered by Google App Engine
This is Rietveld 408576698