You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
160 lines
4.9 KiB
160 lines
4.9 KiB
# -*- coding: utf-8 -*-
|
|
"""
|
|
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
|
|
|
|
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,)
|
|
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:
|
|
def reraise(t, value, tb=None): # pylint:disable=unused-argument
|
|
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
|
|
|