Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/wand/compat.py : 38%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1""":mod:`wand.compat` --- Compatibility layer
2~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4This module provides several subtle things to support
5multiple Python versions (2.6, 2.7, 3.3+) and VM implementations
6(CPython, PyPy).
8"""
9import collections
10try:
11 import collections.abc
12except ImportError:
13 pass
14import contextlib
15import io
16import sys
17import types
19__all__ = ('PY3', 'abc', 'binary', 'binary_type', 'encode_filename',
20 'file_types', 'nested', 'string_type', 'text', 'text_type',
21 'xrange')
24#: (:class:`bool`) Whether it is Python 3.x or not.
25PY3 = sys.version_info >= (3,)
27#: (:class:`module`) Module containing abstract base classes.
28#: :mod:`collections` in Python 2 and :mod:`collections.abc` in Python 3.
29abc = collections.abc if PY3 else collections
31#: (:class:`type`) Type for representing binary data. :class:`str` in Python 2
32#: and :class:`bytes` in Python 3.
33binary_type = bytes if PY3 else str
35#: (:class:`type`) Type for text data. :class:`basestring` in Python 2
36#: and :class:`str` in Python 3.
37string_type = str if PY3 else basestring # noqa
39#: (:class:`type`) Type for representing Unicode textual data.
40#: :class:`unicode` in Python 2 and :class:`str` in Python 3.
41text_type = str if PY3 else unicode # noqa
44def binary(string, var=None):
45 """Makes ``string`` to :class:`str` in Python 2.
46 Makes ``string`` to :class:`bytes` in Python 3.
48 :param string: a string to cast it to :data:`binary_type`
49 :type string: :class:`bytes`, :class:`str`, :class:`unicode`
50 :param var: an optional variable name to be used for error message
51 :type var: :class:`str`
53 """
54 if isinstance(string, text_type):
55 return string.encode()
56 elif isinstance(string, binary_type):
57 return string
58 if var:
59 raise TypeError('{0} must be a string, not {1!r}'.format(var, string))
60 raise TypeError('expected a string, not ' + repr(string))
63if PY3:
64 def text(string):
65 if isinstance(string, bytes):
66 return string.decode('utf-8')
67 return string
68else:
69 def text(string):
70 """Makes ``string`` to :class:`str` in Python 3.
71 Does nothing in Python 2.
73 :param string: a string to cast it to :data:`text_type`
74 :type string: :class:`bytes`, :class:`str`, :class:`unicode`
76 """
77 return string
80#: The :func:`xrange()` function. Alias for :func:`range()` in Python 3.
81xrange = range if PY3 else xrange # noqa
84#: (:class:`type`, :class:`tuple`) Types for file objects that have
85#: ``fileno()``.
86file_types = io.RawIOBase if PY3 else (io.RawIOBase, types.FileType)
89def encode_filename(filename):
90 """If ``filename`` is a :data:`text_type`, encode it to
91 :data:`binary_type` according to filesystem's default encoding.
93 .. versionchanged:: 0.5.3
94 Added support for PEP-519 https://github.com/emcconville/wand/pull/339
95 """
96 if hasattr(filename, "__fspath__"): # PEP 519
97 filename = filename.__fspath__()
98 if isinstance(filename, text_type):
99 return filename.encode(sys.getfilesystemencoding())
100 return filename
103try:
104 nested = contextlib.nested
105except AttributeError:
106 # http://hg.python.org/cpython/file/v2.7.6/Lib/contextlib.py#l88
107 @contextlib.contextmanager
108 def nested(*managers):
109 exits = []
110 vars = []
111 exc = (None, None, None)
112 try:
113 for mgr in managers:
114 exit = mgr.__exit__
115 enter = mgr.__enter__
116 vars.append(enter())
117 exits.append(exit)
118 yield vars
119 except: # noqa: E722
120 exc = sys.exc_info()
121 finally:
122 while exits:
123 exit = exits.pop()
124 try:
125 if exit(*exc):
126 exc = (None, None, None)
127 except: # noqa: E722
128 exc = sys.exc_info()
129 if exc != (None, None, None):
130 # PEP 3109
131 e = exc[0](exc[1])
132 e.__traceback__ = e[2]
133 raise e