docs: def parse_value(value, allowed_types, name='value'):
      """Parse a value into one of a number of types.
  
      This function is used to coerce untyped HTTP parameter strings into an
      appropriate type. It tries to coerce the value into each of the allowed
      types, and uses the first that evaluates properly.
  
      Because this is coercing a string into multiple, potentially ambiguous,
      types, it tests things in the order of least ambiguous to most ambiguous:
  
      - The "null" type is checked first. If allowed, and the value is blank
        (""), None will be returned.
      - The "boolean" type is checked next. Values of "true" (case insensitive)
        are True, and values of "false" are False.
      - Numeric types are checked next -- first "integer", then "number".
      - The "array" type is checked next. A value is only considered a valid
        array if it begins with a "[" and can be parsed as JSON.
      - The "object" type is checked next. A value is only considered a valid
        object if it begins with a "{" and can be parsed as JSON.
      - The "string" type is checked last, since any value is a valid string.
        Unicode strings are encoded as UTF-8.
  
      :param str value: Parameter value. Example: "1"
      :param list allowed_types: Types that should be attempted. Example:
          ["integer", "null"]
      :param str name: Parameter name. If not specified, "value" is used.
          Example: "campaign_id"
      :returns: a tuple of a type string and coerced value
      :raises: ParseError if the value cannot be coerced to any of the types
      """
      if not isinstance(value, str):
          raise ValueError('value for %r must be a string' % name)
      if isinstance(allowed_types, str):
          allowed_types = [allowed_types]
  
      # Note that the order of these type considerations is important. Because we
      # have an untyped value that may be one of any given number of types, we
      # need a consistent order of evaluation in cases when there is ambiguity
      # between types.
  
      if 'null' in allowed_types and value == '':
          return 'null', None
  
      # For all of these types, we'll pass the value to the function and it will
      # raise a TypeError or ValueError or return None if it can't be parsed as
      # the given type.
  
      for allowed_type, parser in _parser_funcs:
          if allowed_type in allowed_types:
              try:
                  parsed_value = parser(value)
                  if parsed_value is not None:
                      return allowed_type, parsed_value
              except (TypeError, ValueError):
                  # Ignore any errors, and continue trying other types
                  pass
  
      raise ParseError('%s must be a valid type (%s)' %
                       (name, ', '.join(allowed_types)))