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

Side by Side Diff: third_party/google-endpoints/future/utils/__init__.py

Issue 2666783008: Add google-endpoints to third_party/. (Closed)
Patch Set: Created 3 years, 10 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 unified diff | Download patch
OLDNEW
(Empty)
1 """
2 A selection of cross-compatible functions for Python 2 and 3.
3
4 This module exports useful functions for 2/3 compatible code:
5
6 * bind_method: binds functions to classes
7 * ``native_str_to_bytes`` and ``bytes_to_native_str``
8 * ``native_str``: always equal to the native platform string object (because
9 this may be shadowed by imports from future.builtins)
10 * lists: lrange(), lmap(), lzip(), lfilter()
11 * iterable method compatibility:
12 - iteritems, iterkeys, itervalues
13 - viewitems, viewkeys, viewvalues
14
15 These use the original method if available, otherwise they use items,
16 keys, values.
17
18 * types:
19
20 * text_type: unicode in Python 2, str in Python 3
21 * binary_type: str in Python 2, bythes in Python 3
22 * string_types: basestring in Python 2, str in Python 3
23
24 * bchr(c):
25 Take an integer and make a 1-character byte string
26 * bord(c)
27 Take the result of indexing on a byte string and make an integer
28 * tobytes(s)
29 Take a text string, a byte string, or a sequence of characters taken
30 from a byte string, and make a byte string.
31
32 * raise_from()
33 * raise_with_traceback()
34
35 This module also defines these decorators:
36
37 * ``python_2_unicode_compatible``
38 * ``with_metaclass``
39 * ``implements_iterator``
40
41 Some of the functions in this module come from the following sources:
42
43 * Jinja2 (BSD licensed: see
44 https://github.com/mitsuhiko/jinja2/blob/master/LICENSE)
45 * Pandas compatibility module pandas.compat
46 * six.py by Benjamin Peterson
47 * Django
48 """
49
50 import types
51 import sys
52 import numbers
53 import functools
54 import copy
55 import inspect
56
57
58 PY3 = sys.version_info[0] == 3
59 PY2 = sys.version_info[0] == 2
60 PY26 = sys.version_info[0:2] == (2, 6)
61 PY27 = sys.version_info[0:2] == (2, 7)
62 PYPY = hasattr(sys, 'pypy_translation_info')
63
64
65 def python_2_unicode_compatible(cls):
66 """
67 A decorator that defines __unicode__ and __str__ methods under Python
68 2. Under Python 3, this decorator is a no-op.
69
70 To support Python 2 and 3 with a single code base, define a __str__
71 method returning unicode text and apply this decorator to the class, like
72 this::
73
74 >>> from future.utils import python_2_unicode_compatible
75
76 >>> @python_2_unicode_compatible
77 ... class MyClass(object):
78 ... def __str__(self):
79 ... return u'Unicode string: \u5b54\u5b50'
80
81 >>> a = MyClass()
82
83 Then, after this import:
84
85 >>> from future.builtins import str
86
87 the following is ``True`` on both Python 3 and 2::
88
89 >>> str(a) == a.encode('utf-8').decode('utf-8')
90 True
91
92 and, on a Unicode-enabled terminal with the right fonts, these both print th e
93 Chinese characters for Confucius::
94
95 >>> print(a)
96 >>> print(str(a))
97
98 The implementation comes from django.utils.encoding.
99 """
100 if not PY3:
101 cls.__unicode__ = cls.__str__
102 cls.__str__ = lambda self: self.__unicode__().encode('utf-8')
103 return cls
104
105
106 def with_metaclass(meta, *bases):
107 """
108 Function from jinja2/_compat.py. License: BSD.
109
110 Use it like this::
111
112 class BaseForm(object):
113 pass
114
115 class FormType(type):
116 pass
117
118 class Form(with_metaclass(FormType, BaseForm)):
119 pass
120
121 This requires a bit of explanation: the basic idea is to make a
122 dummy metaclass for one level of class instantiation that replaces
123 itself with the actual metaclass. Because of internal type checks
124 we also need to make sure that we downgrade the custom metaclass
125 for one level to something closer to type (that's why __call__ and
126 __init__ comes back from type etc.).
127
128 This has the advantage over six.with_metaclass of not introducing
129 dummy classes into the final MRO.
130 """
131 class metaclass(meta):
132 __call__ = type.__call__
133 __init__ = type.__init__
134 def __new__(cls, name, this_bases, d):
135 if this_bases is None:
136 return type.__new__(cls, name, (), d)
137 return meta(name, bases, d)
138 return metaclass('temporary_class', None, {})
139
140
141 # Definitions from pandas.compat and six.py follow:
142 if PY3:
143 def bchr(s):
144 return bytes([s])
145 def bstr(s):
146 if isinstance(s, str):
147 return bytes(s, 'latin-1')
148 else:
149 return bytes(s)
150 def bord(s):
151 return s
152
153 string_types = str,
154 integer_types = int,
155 class_types = type,
156 text_type = str
157 binary_type = bytes
158
159 else:
160 # Python 2
161 def bchr(s):
162 return chr(s)
163 def bstr(s):
164 return str(s)
165 def bord(s):
166 return ord(s)
167
168 string_types = basestring,
169 integer_types = (int, long)
170 class_types = (type, types.ClassType)
171 text_type = unicode
172 binary_type = str
173
174 ###
175
176 if PY3:
177 def tobytes(s):
178 if isinstance(s, bytes):
179 return s
180 else:
181 if isinstance(s, str):
182 return s.encode('latin-1')
183 else:
184 return bytes(s)
185 else:
186 # Python 2
187 def tobytes(s):
188 if isinstance(s, unicode):
189 return s.encode('latin-1')
190 else:
191 return ''.join(s)
192
193 tobytes.__doc__ = """
194 Encodes to latin-1 (where the first 256 chars are the same as
195 ASCII.)
196 """
197
198 if PY3:
199 def native_str_to_bytes(s, encoding='utf-8'):
200 return s.encode(encoding)
201
202 def bytes_to_native_str(b, encoding='utf-8'):
203 return b.decode(encoding)
204
205 def text_to_native_str(t, encoding=None):
206 return t
207 else:
208 # Python 2
209 def native_str_to_bytes(s, encoding=None):
210 from future.types import newbytes # to avoid a circular import
211 return newbytes(s)
212
213 def bytes_to_native_str(b, encoding=None):
214 return native(b)
215
216 def text_to_native_str(t, encoding='ascii'):
217 """
218 Use this to create a Py2 native string when "from __future__ import
219 unicode_literals" is in effect.
220 """
221 return unicode(t).encode(encoding)
222
223 native_str_to_bytes.__doc__ = """
224 On Py3, returns an encoded string.
225 On Py2, returns a newbytes type, ignoring the ``encoding`` argument.
226 """
227
228 if PY3:
229 # list-producing versions of the major Python iterating functions
230 def lrange(*args, **kwargs):
231 return list(range(*args, **kwargs))
232
233 def lzip(*args, **kwargs):
234 return list(zip(*args, **kwargs))
235
236 def lmap(*args, **kwargs):
237 return list(map(*args, **kwargs))
238
239 def lfilter(*args, **kwargs):
240 return list(filter(*args, **kwargs))
241 else:
242 import __builtin__
243 # Python 2-builtin ranges produce lists
244 lrange = __builtin__.range
245 lzip = __builtin__.zip
246 lmap = __builtin__.map
247 lfilter = __builtin__.filter
248
249
250 def isidentifier(s, dotted=False):
251 '''
252 A function equivalent to the str.isidentifier method on Py3
253 '''
254 if dotted:
255 return all(isidentifier(a) for a in s.split('.'))
256 if PY3:
257 return s.isidentifier()
258 else:
259 import re
260 _name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$")
261 return bool(_name_re.match(s))
262
263
264 def viewitems(obj, **kwargs):
265 """
266 Function for iterating over dictionary items with the same set-like
267 behaviour on Py2.7 as on Py3.
268
269 Passes kwargs to method."""
270 func = getattr(obj, "viewitems", None)
271 if not func:
272 func = obj.items
273 return func(**kwargs)
274
275
276 def viewkeys(obj, **kwargs):
277 """
278 Function for iterating over dictionary keys with the same set-like
279 behaviour on Py2.7 as on Py3.
280
281 Passes kwargs to method."""
282 func = getattr(obj, "viewkeys", None)
283 if not func:
284 func = obj.keys
285 return func(**kwargs)
286
287
288 def viewvalues(obj, **kwargs):
289 """
290 Function for iterating over dictionary values with the same set-like
291 behaviour on Py2.7 as on Py3.
292
293 Passes kwargs to method."""
294 func = getattr(obj, "viewvalues", None)
295 if not func:
296 func = obj.values
297 return func(**kwargs)
298
299
300 def iteritems(obj, **kwargs):
301 """Use this only if compatibility with Python versions before 2.7 is
302 required. Otherwise, prefer viewitems().
303 """
304 func = getattr(obj, "iteritems", None)
305 if not func:
306 func = obj.items
307 return func(**kwargs)
308
309
310 def iterkeys(obj, **kwargs):
311 """Use this only if compatibility with Python versions before 2.7 is
312 required. Otherwise, prefer viewkeys().
313 """
314 func = getattr(obj, "iterkeys", None)
315 if not func:
316 func = obj.keys
317 return func(**kwargs)
318
319
320 def itervalues(obj, **kwargs):
321 """Use this only if compatibility with Python versions before 2.7 is
322 required. Otherwise, prefer viewvalues().
323 """
324 func = getattr(obj, "itervalues", None)
325 if not func:
326 func = obj.values
327 return func(**kwargs)
328
329
330 def bind_method(cls, name, func):
331 """Bind a method to class, python 2 and python 3 compatible.
332
333 Parameters
334 ----------
335
336 cls : type
337 class to receive bound method
338 name : basestring
339 name of method on class instance
340 func : function
341 function to be bound as method
342
343 Returns
344 -------
345 None
346 """
347 # only python 2 has an issue with bound/unbound methods
348 if not PY3:
349 setattr(cls, name, types.MethodType(func, None, cls))
350 else:
351 setattr(cls, name, func)
352
353
354 def getexception():
355 return sys.exc_info()[1]
356
357
358 def _get_caller_globals_and_locals():
359 """
360 Returns the globals and locals of the calling frame.
361
362 Is there an alternative to frame hacking here?
363 """
364 caller_frame = inspect.stack()[2]
365 myglobals = caller_frame[0].f_globals
366 mylocals = caller_frame[0].f_locals
367 return myglobals, mylocals
368
369
370 def _repr_strip(mystring):
371 """
372 Returns the string without any initial or final quotes.
373 """
374 r = repr(mystring)
375 if r.startswith("'") and r.endswith("'"):
376 return r[1:-1]
377 else:
378 return r
379
380
381 if PY3:
382 def raise_from(exc, cause):
383 """
384 Equivalent to:
385
386 raise EXCEPTION from CAUSE
387
388 on Python 3. (See PEP 3134).
389 """
390 myglobals, mylocals = _get_caller_globals_and_locals()
391
392 # We pass the exception and cause along with other globals
393 # when we exec():
394 myglobals = myglobals.copy()
395 myglobals['__python_future_raise_from_exc'] = exc
396 myglobals['__python_future_raise_from_cause'] = cause
397 execstr = "raise __python_future_raise_from_exc from __python_future_rai se_from_cause"
398 exec(execstr, myglobals, mylocals)
399
400 def raise_(tp, value=None, tb=None):
401 """
402 A function that matches the Python 2.x ``raise`` statement. This
403 allows re-raising exceptions with the cls value and traceback on
404 Python 2 and 3.
405 """
406 if value is not None and isinstance(tp, Exception):
407 raise TypeError("instance exception may not have a separate value")
408 if value is not None:
409 exc = tp(value)
410 else:
411 exc = tp
412 if exc.__traceback__ is not tb:
413 raise exc.with_traceback(tb)
414 raise exc
415
416 def raise_with_traceback(exc, traceback=Ellipsis):
417 if traceback == Ellipsis:
418 _, _, traceback = sys.exc_info()
419 raise exc.with_traceback(traceback)
420
421 else:
422 def raise_from(exc, cause):
423 """
424 Equivalent to:
425
426 raise EXCEPTION from CAUSE
427
428 on Python 3. (See PEP 3134).
429 """
430 # Is either arg an exception class (e.g. IndexError) rather than
431 # instance (e.g. IndexError('my message here')? If so, pass the
432 # name of the class undisturbed through to "raise ... from ...".
433 if isinstance(exc, type) and issubclass(exc, Exception):
434 e = exc()
435 # exc = exc.__name__
436 # execstr = "e = " + _repr_strip(exc) + "()"
437 # myglobals, mylocals = _get_caller_globals_and_locals()
438 # exec(execstr, myglobals, mylocals)
439 else:
440 e = exc
441 e.__suppress_context__ = False
442 if isinstance(cause, type) and issubclass(cause, Exception):
443 e.__cause__ = cause()
444 e.__suppress_context__ = True
445 elif cause is None:
446 e.__cause__ = None
447 e.__suppress_context__ = True
448 elif isinstance(cause, BaseException):
449 e.__cause__ = cause
450 e.__suppress_context__ = True
451 else:
452 raise TypeError("exception causes must derive from BaseException")
453 e.__context__ = sys.exc_info()[1]
454 raise e
455
456 exec('''
457 def raise_(tp, value=None, tb=None):
458 raise tp, value, tb
459
460 def raise_with_traceback(exc, traceback=Ellipsis):
461 if traceback == Ellipsis:
462 _, _, traceback = sys.exc_info()
463 raise exc, None, traceback
464 '''.strip())
465
466
467 raise_with_traceback.__doc__ = (
468 """Raise exception with existing traceback.
469 If traceback is not passed, uses sys.exc_info() to get traceback."""
470 )
471
472
473 # Deprecated alias for backward compatibility with ``future`` versions < 0.11:
474 reraise = raise_
475
476
477 def implements_iterator(cls):
478 '''
479 From jinja2/_compat.py. License: BSD.
480
481 Use as a decorator like this::
482
483 @implements_iterator
484 class UppercasingIterator(object):
485 def __init__(self, iterable):
486 self._iter = iter(iterable)
487 def __iter__(self):
488 return self
489 def __next__(self):
490 return next(self._iter).upper()
491
492 '''
493 if PY3:
494 return cls
495 else:
496 cls.next = cls.__next__
497 del cls.__next__
498 return cls
499
500 if PY3:
501 get_next = lambda x: x.next
502 else:
503 get_next = lambda x: x.__next__
504
505
506 def encode_filename(filename):
507 if PY3:
508 return filename
509 else:
510 if isinstance(filename, unicode):
511 return filename.encode('utf-8')
512 return filename
513
514
515 def is_new_style(cls):
516 """
517 Python 2.7 has both new-style and old-style classes. Old-style classes can
518 be pesky in some circumstances, such as when using inheritance. Use this
519 function to test for whether a class is new-style. (Python 3 only has
520 new-style classes.)
521 """
522 return hasattr(cls, '__class__') and ('__dict__' in dir(cls)
523 or hasattr(cls, '__slots__'))
524
525 # The native platform string and bytes types. Useful because ``str`` and
526 # ``bytes`` are redefined on Py2 by ``from future.builtins import *``.
527 native_str = str
528 native_bytes = bytes
529
530
531 def istext(obj):
532 """
533 Deprecated. Use::
534 >>> isinstance(obj, str)
535 after this import:
536 >>> from future.builtins import str
537 """
538 return isinstance(obj, type(u''))
539
540
541 def isbytes(obj):
542 """
543 Deprecated. Use::
544 >>> isinstance(obj, bytes)
545 after this import:
546 >>> from future.builtins import bytes
547 """
548 return isinstance(obj, type(b''))
549
550
551 def isnewbytes(obj):
552 """
553 Equivalent to the result of ``isinstance(obj, newbytes)`` were
554 ``__instancecheck__`` not overridden on the newbytes subclass. In
555 other words, it is REALLY a newbytes instance, not a Py2 native str
556 object?
557 """
558 # TODO: generalize this so that it works with subclasses of newbytes
559 # Import is here to avoid circular imports:
560 from future.types.newbytes import newbytes
561 return type(obj) == newbytes
562
563
564 def isint(obj):
565 """
566 Deprecated. Tests whether an object is a Py3 ``int`` or either a Py2 ``int`` or
567 ``long``.
568
569 Instead of using this function, you can use:
570
571 >>> from future.builtins import int
572 >>> isinstance(obj, int)
573
574 The following idiom is equivalent:
575
576 >>> from numbers import Integral
577 >>> isinstance(obj, Integral)
578 """
579
580 return isinstance(obj, numbers.Integral)
581
582
583 def native(obj):
584 """
585 On Py3, this is a no-op: native(obj) -> obj
586
587 On Py2, returns the corresponding native Py2 types that are
588 superclasses for backported objects from Py3:
589
590 >>> from builtins import str, bytes, int
591
592 >>> native(str(u'ABC'))
593 u'ABC'
594 >>> type(native(str(u'ABC')))
595 unicode
596
597 >>> native(bytes(b'ABC'))
598 b'ABC'
599 >>> type(native(bytes(b'ABC')))
600 bytes
601
602 >>> native(int(10**20))
603 100000000000000000000L
604 >>> type(native(int(10**20)))
605 long
606
607 Existing native types on Py2 will be returned unchanged:
608
609 >>> type(native(u'ABC'))
610 unicode
611 """
612 if hasattr(obj, '__native__'):
613 return obj.__native__()
614 else:
615 return obj
616
617
618 # Implementation of exec_ is from ``six``:
619 if PY3:
620 import builtins
621 exec_ = getattr(builtins, "exec")
622 else:
623 def exec_(code, globs=None, locs=None):
624 """Execute code in a namespace."""
625 if globs is None:
626 frame = sys._getframe(1)
627 globs = frame.f_globals
628 if locs is None:
629 locs = frame.f_locals
630 del frame
631 elif locs is None:
632 locs = globs
633 exec("""exec code in globs, locs""")
634
635
636 # Defined here for backward compatibility:
637 def old_div(a, b):
638 """
639 DEPRECATED: import ``old_div`` from ``past.utils`` instead.
640
641 Equivalent to ``a / b`` on Python 2 without ``from __future__ import
642 division``.
643
644 TODO: generalize this to other objects (like arrays etc.)
645 """
646 if isinstance(a, numbers.Integral) and isinstance(b, numbers.Integral):
647 return a // b
648 else:
649 return a / b
650
651
652 def as_native_str(encoding='utf-8'):
653 '''
654 A decorator to turn a function or method call that returns text, i.e.
655 unicode, into one that returns a native platform str.
656
657 Use it as a decorator like this::
658
659 from __future__ import unicode_literals
660
661 class MyClass(object):
662 @as_native_str(encoding='ascii')
663 def __repr__(self):
664 return next(self._iter).upper()
665 '''
666 if PY3:
667 return lambda f: f
668 else:
669 def encoder(f):
670 @functools.wraps(f)
671 def wrapper(*args, **kwargs):
672 return f(*args, **kwargs).encode(encoding=encoding)
673 return wrapper
674 return encoder
675
676 # listvalues and listitems definitions from Nick Coghlan's (withdrawn)
677 # PEP 496:
678 try:
679 dict.iteritems
680 except AttributeError:
681 # Python 3
682 def listvalues(d):
683 return list(d.values())
684 def listitems(d):
685 return list(d.items())
686 else:
687 # Python 2
688 def listvalues(d):
689 return d.values()
690 def listitems(d):
691 return d.items()
692
693 if PY3:
694 def ensure_new_type(obj):
695 return obj
696 else:
697 def ensure_new_type(obj):
698 from future.types.newbytes import newbytes
699 from future.types.newstr import newstr
700 from future.types.newint import newint
701 from future.types.newdict import newdict
702
703 native_type = type(native(obj))
704
705 # Upcast only if the type is already a native (non-future) type
706 if issubclass(native_type, type(obj)):
707 # Upcast
708 if native_type == str: # i.e. Py2 8-bit str
709 return newbytes(obj)
710 elif native_type == unicode:
711 return newstr(obj)
712 elif native_type == int:
713 return newint(obj)
714 elif native_type == long:
715 return newint(obj)
716 elif native_type == dict:
717 return newdict(obj)
718 else:
719 return obj
720 else:
721 # Already a new type
722 assert type(obj) in [newbytes, newstr]
723 return obj
724
725
726 __all__ = ['PY2', 'PY26', 'PY3', 'PYPY',
727 'as_native_str', 'bind_method', 'bord', 'bstr',
728 'bytes_to_native_str', 'encode_filename', 'ensure_new_type',
729 'exec_', 'get_next', 'getexception', 'implements_iterator',
730 'is_new_style', 'isbytes', 'isidentifier', 'isint',
731 'isnewbytes', 'istext', 'iteritems', 'iterkeys', 'itervalues',
732 'lfilter', 'listitems', 'listvalues', 'lmap', 'lrange',
733 'lzip', 'native', 'native_bytes', 'native_str',
734 'native_str_to_bytes', 'old_div',
735 'python_2_unicode_compatible', 'raise_',
736 'raise_with_traceback', 'reraise', 'text_to_native_str',
737 'tobytes', 'viewitems', 'viewkeys', 'viewvalues',
738 'with_metaclass'
739 ]
OLDNEW
« no previous file with comments | « third_party/google-endpoints/future/types/newstr.py ('k') | third_party/google-endpoints/future/utils/surrogateescape.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698