| Index: third_party/google-endpoints/future/types/__init__.py
|
| diff --git a/third_party/google-endpoints/future/types/__init__.py b/third_party/google-endpoints/future/types/__init__.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..71279bbb49267abef9afcbe09e3fe9c8e5f6cda8
|
| --- /dev/null
|
| +++ b/third_party/google-endpoints/future/types/__init__.py
|
| @@ -0,0 +1,258 @@
|
| +"""
|
| +This module contains backports the data types that were significantly changed
|
| +in the transition from Python 2 to Python 3.
|
| +
|
| +- an implementation of Python 3's bytes object (pure Python subclass of
|
| + Python 2's builtin 8-bit str type)
|
| +- an implementation of Python 3's str object (pure Python subclass of
|
| + Python 2's builtin unicode type)
|
| +- a backport of the range iterator from Py3 with slicing support
|
| +
|
| +It is used as follows::
|
| +
|
| + from __future__ import division, absolute_import, print_function
|
| + from builtins import bytes, dict, int, range, str
|
| +
|
| +to bring in the new semantics for these functions from Python 3. And
|
| +then, for example::
|
| +
|
| + b = bytes(b'ABCD')
|
| + assert list(b) == [65, 66, 67, 68]
|
| + assert repr(b) == "b'ABCD'"
|
| + assert [65, 66] in b
|
| +
|
| + # These raise TypeErrors:
|
| + # b + u'EFGH'
|
| + # b.split(u'B')
|
| + # bytes(b',').join([u'Fred', u'Bill'])
|
| +
|
| +
|
| + s = str(u'ABCD')
|
| +
|
| + # These raise TypeErrors:
|
| + # s.join([b'Fred', b'Bill'])
|
| + # s.startswith(b'A')
|
| + # b'B' in s
|
| + # s.find(b'A')
|
| + # s.replace(u'A', b'a')
|
| +
|
| + # This raises an AttributeError:
|
| + # s.decode('utf-8')
|
| +
|
| + assert repr(s) == 'ABCD' # consistent repr with Py3 (no u prefix)
|
| +
|
| +
|
| + for i in range(10**11)[:10]:
|
| + pass
|
| +
|
| +and::
|
| +
|
| + class VerboseList(list):
|
| + def append(self, item):
|
| + print('Adding an item')
|
| + super().append(item) # new simpler super() function
|
| +
|
| +For more information:
|
| +---------------------
|
| +
|
| +- future.types.newbytes
|
| +- future.types.newdict
|
| +- future.types.newint
|
| +- future.types.newobject
|
| +- future.types.newrange
|
| +- future.types.newstr
|
| +
|
| +
|
| +Notes
|
| +=====
|
| +
|
| +range()
|
| +-------
|
| +``range`` is a custom class that backports the slicing behaviour from
|
| +Python 3 (based on the ``xrange`` module by Dan Crosta). See the
|
| +``newrange`` module docstring for more details.
|
| +
|
| +
|
| +super()
|
| +-------
|
| +``super()`` is based on Ryan Kelly's ``magicsuper`` module. See the
|
| +``newsuper`` module docstring for more details.
|
| +
|
| +
|
| +round()
|
| +-------
|
| +Python 3 modifies the behaviour of ``round()`` to use "Banker's Rounding".
|
| +See http://stackoverflow.com/a/10825998. See the ``newround`` module
|
| +docstring for more details.
|
| +
|
| +"""
|
| +
|
| +from __future__ import absolute_import, division, print_function
|
| +
|
| +import functools
|
| +from numbers import Integral
|
| +
|
| +from future import utils
|
| +
|
| +
|
| +# Some utility functions to enforce strict type-separation of unicode str and
|
| +# bytes:
|
| +def disallow_types(argnums, disallowed_types):
|
| + """
|
| + A decorator that raises a TypeError if any of the given numbered
|
| + arguments is of the corresponding given type (e.g. bytes or unicode
|
| + string).
|
| +
|
| + For example:
|
| +
|
| + @disallow_types([0, 1], [unicode, bytes])
|
| + def f(a, b):
|
| + pass
|
| +
|
| + raises a TypeError when f is called if a unicode object is passed as
|
| + `a` or a bytes object is passed as `b`.
|
| +
|
| + This also skips over keyword arguments, so
|
| +
|
| + @disallow_types([0, 1], [unicode, bytes])
|
| + def g(a, b=None):
|
| + pass
|
| +
|
| + doesn't raise an exception if g is called with only one argument a,
|
| + e.g.:
|
| +
|
| + g(b'Byte string')
|
| +
|
| + Example use:
|
| +
|
| + >>> class newbytes(object):
|
| + ... @disallow_types([1], [unicode])
|
| + ... def __add__(self, other):
|
| + ... pass
|
| +
|
| + >>> newbytes('1234') + u'1234' #doctest: +IGNORE_EXCEPTION_DETAIL
|
| + Traceback (most recent call last):
|
| + ...
|
| + TypeError: can't concat 'bytes' to (unicode) str
|
| + """
|
| +
|
| + def decorator(function):
|
| +
|
| + @functools.wraps(function)
|
| + def wrapper(*args, **kwargs):
|
| + # These imports are just for this decorator, and are defined here
|
| + # to prevent circular imports:
|
| + from .newbytes import newbytes
|
| + from .newint import newint
|
| + from .newstr import newstr
|
| +
|
| + errmsg = "argument can't be {0}"
|
| + for (argnum, mytype) in zip(argnums, disallowed_types):
|
| + # Handle the case where the type is passed as a string like 'newbytes'.
|
| + if isinstance(mytype, str) or isinstance(mytype, bytes):
|
| + mytype = locals()[mytype]
|
| +
|
| + # Only restrict kw args only if they are passed:
|
| + if len(args) <= argnum:
|
| + break
|
| +
|
| + # Here we use type() rather than isinstance() because
|
| + # __instancecheck__ is being overridden. E.g.
|
| + # isinstance(b'abc', newbytes) is True on Py2.
|
| + if type(args[argnum]) == mytype:
|
| + raise TypeError(errmsg.format(mytype))
|
| +
|
| + return function(*args, **kwargs)
|
| + return wrapper
|
| + return decorator
|
| +
|
| +
|
| +def no(mytype, argnums=(1,)):
|
| + """
|
| + A shortcut for the disallow_types decorator that disallows only one type
|
| + (in any position in argnums).
|
| +
|
| + Example use:
|
| +
|
| + >>> class newstr(object):
|
| + ... @no('bytes')
|
| + ... def __add__(self, other):
|
| + ... pass
|
| +
|
| + >>> newstr(u'1234') + b'1234' #doctest: +IGNORE_EXCEPTION_DETAIL
|
| + Traceback (most recent call last):
|
| + ...
|
| + TypeError: argument can't be bytes
|
| +
|
| + The object can also be passed directly, but passing the string helps
|
| + to prevent circular import problems.
|
| + """
|
| + if isinstance(argnums, Integral):
|
| + argnums = (argnums,)
|
| + disallowed_types = [mytype] * len(argnums)
|
| + return disallow_types(argnums, disallowed_types)
|
| +
|
| +
|
| +def issubset(list1, list2):
|
| + """
|
| + Examples:
|
| +
|
| + >>> issubset([], [65, 66, 67])
|
| + True
|
| + >>> issubset([65], [65, 66, 67])
|
| + True
|
| + >>> issubset([65, 66], [65, 66, 67])
|
| + True
|
| + >>> issubset([65, 67], [65, 66, 67])
|
| + False
|
| + """
|
| + n = len(list1)
|
| + for startpos in range(len(list2) - n + 1):
|
| + if list2[startpos:startpos+n] == list1:
|
| + return True
|
| + return False
|
| +
|
| +
|
| +if utils.PY3:
|
| + import builtins
|
| + bytes = builtins.bytes
|
| + dict = builtins.dict
|
| + int = builtins.int
|
| + list = builtins.list
|
| + object = builtins.object
|
| + range = builtins.range
|
| + str = builtins.str
|
| +
|
| + # The identity mapping
|
| + newtypes = {bytes: bytes,
|
| + dict: dict,
|
| + int: int,
|
| + list: list,
|
| + object: object,
|
| + range: range,
|
| + str: str}
|
| +
|
| + __all__ = ['newtypes']
|
| +
|
| +else:
|
| +
|
| + from .newbytes import newbytes
|
| + from .newdict import newdict
|
| + from .newint import newint
|
| + from .newlist import newlist
|
| + from .newrange import newrange
|
| + from .newobject import newobject
|
| + from .newstr import newstr
|
| +
|
| + newtypes = {bytes: newbytes,
|
| + dict: newdict,
|
| + int: newint,
|
| + long: newint,
|
| + list: newlist,
|
| + object: newobject,
|
| + range: newrange,
|
| + str: newbytes,
|
| + unicode: newstr}
|
| +
|
| + __all__ = ['newbytes', 'newdict', 'newint', 'newlist', 'newrange', 'newstr', 'newtypes']
|
| +
|
|
|