aboutsummaryrefslogtreecommitdiffstats
path: root/python/gevent/_compat.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/gevent/_compat.py')
-rw-r--r--python/gevent/_compat.py116
1 files changed, 114 insertions, 2 deletions
diff --git a/python/gevent/_compat.py b/python/gevent/_compat.py
index 96f5f93..22bad70 100644
--- a/python/gevent/_compat.py
+++ b/python/gevent/_compat.py
@@ -5,12 +5,19 @@ internal gevent python 2/python 3 bridges. Not for external use.
from __future__ import print_function, absolute_import, division
-
import sys
+import os
+
PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] >= 3
PYPY = hasattr(sys, 'pypy_version_info')
+WIN = sys.platform.startswith("win")
+LINUX = sys.platform.startswith('linux')
+OSX = sys.platform == 'darwin'
+
+
+PURE_PYTHON = PYPY or os.getenv('PURE_PYTHON')
## Types
@@ -18,13 +25,20 @@ if PY3:
string_types = (str,)
integer_types = (int,)
text_type = str
+ native_path_types = (str, bytes)
+ thread_mod_name = '_thread'
else:
import __builtin__ # pylint:disable=import-error
- string_types = __builtin__.basestring,
+ string_types = (__builtin__.basestring,)
text_type = __builtin__.unicode
integer_types = (int, __builtin__.long)
+ native_path_types = string_types
+ thread_mod_name = 'thread'
+def NativeStrIO():
+ import io
+ return io.BytesIO() if str is bytes else io.StringIO()
## Exceptions
if PY3:
@@ -32,17 +46,115 @@ if PY3:
if value.__traceback__ is not tb and tb is not None:
raise value.with_traceback(tb)
raise value
+ def exc_clear():
+ pass
else:
from gevent._util_py2 import reraise # pylint:disable=import-error,no-name-in-module
reraise = reraise # export
+ exc_clear = sys.exc_clear
+
+## import locks
+try:
+ # In Python 3.4 and newer in CPython and PyPy3,
+ # imp.acquire_lock and imp.release_lock are delegated to
+ # '_imp'. (Which is also used by importlib.) 'imp' itself is
+ # deprecated. Avoid that warning.
+ import _imp as imp
+except ImportError:
+ import imp
+imp_acquire_lock = imp.acquire_lock
+imp_release_lock = imp.release_lock
## Functions
if PY3:
iteritems = dict.items
itervalues = dict.values
xrange = range
+ izip = zip
+
else:
iteritems = dict.iteritems # python 3: pylint:disable=no-member
itervalues = dict.itervalues # python 3: pylint:disable=no-member
xrange = __builtin__.xrange
+ from itertools import izip # python 3: pylint:disable=no-member,no-name-in-module
+ izip = izip
+
+# fspath from 3.6 os.py, but modified to raise the same exceptions as the
+# real native implementation.
+# Define for testing
+def _fspath(path):
+ """
+ Return the path representation of a path-like object.
+
+ If str or bytes is passed in, it is returned unchanged. Otherwise the
+ os.PathLike interface is used to get the path representation. If the
+ path representation is not str or bytes, TypeError is raised. If the
+ provided path is not str, bytes, or os.PathLike, TypeError is raised.
+ """
+ if isinstance(path, native_path_types):
+ return path
+
+ # Work from the object's type to match method resolution of other magic
+ # methods.
+ path_type = type(path)
+ try:
+ path_type_fspath = path_type.__fspath__
+ except AttributeError:
+ raise TypeError("expected str, bytes or os.PathLike object, "
+ "not " + path_type.__name__)
+
+ path_repr = path_type_fspath(path)
+ if isinstance(path_repr, native_path_types):
+ return path_repr
+
+ raise TypeError("expected {}.__fspath__() to return str or bytes, "
+ "not {}".format(path_type.__name__,
+ type(path_repr).__name__))
+try:
+ from os import fspath # pylint: disable=unused-import,no-name-in-module
+except ImportError:
+ # if not available, use the Python version as transparently as
+ # possible
+ fspath = _fspath
+ fspath.__name__ = 'fspath'
+
+try:
+ from os import fsencode # pylint: disable=unused-import,no-name-in-module
+except ImportError:
+ encoding = sys.getfilesystemencoding() or ('utf-8' if not WIN else 'mbcs')
+ errors = 'strict' if WIN and encoding == 'mbcs' else 'surrogateescape'
+
+ # Added in 3.2, so this is for Python 2.7. Note that it doesn't have
+ # sys.getfilesystemencodeerrors(), which was added in 3.6
+ def fsencode(filename):
+ """Encode filename (an os.PathLike, bytes, or str) to the filesystem
+ encoding with 'surrogateescape' error handler, return bytes unchanged.
+ On Windows, use 'strict' error handler if the file system encoding is
+ 'mbcs' (which is the default encoding).
+ """
+ filename = fspath(filename) # Does type-checking of `filename`.
+ if isinstance(filename, bytes):
+ return filename
+
+ try:
+ return filename.encode(encoding, errors)
+ except LookupError:
+ # Can't encode it, and the error handler doesn't
+ # exist. Probably on Python 2 with an astral character.
+ # Not sure how to handle this.
+ raise UnicodeEncodeError("Can't encode path to filesystem encoding")
+
+
+## Clocks
+try:
+ # Python 3.3+ (PEP 418)
+ from time import perf_counter
+ perf_counter = perf_counter
+except ImportError:
+ import time
+
+ if sys.platform == "win32":
+ perf_counter = time.clock
+ else:
+ perf_counter = time.time