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.
298 lines
9.1 KiB
298 lines
9.1 KiB
import sys
|
|
|
|
from gunicorn import six
|
|
|
|
PY26 = (sys.version_info[:2] == (2, 6))
|
|
PY33 = (sys.version_info >= (3, 3))
|
|
|
|
|
|
def _check_if_pyc(fname):
|
|
"""Return True if the extension is .pyc, False if .py
|
|
and None if otherwise"""
|
|
from imp import find_module
|
|
from os.path import realpath, dirname, basename, splitext
|
|
|
|
# Normalize the file-path for the find_module()
|
|
filepath = realpath(fname)
|
|
dirpath = dirname(filepath)
|
|
module_name = splitext(basename(filepath))[0]
|
|
|
|
# Validate and fetch
|
|
try:
|
|
fileobj, fullpath, (_, _, pytype) = find_module(module_name, [dirpath])
|
|
except ImportError:
|
|
raise IOError("Cannot find config file. "
|
|
"Path maybe incorrect! : {0}".format(filepath))
|
|
return pytype, fileobj, fullpath
|
|
|
|
|
|
def _get_codeobj(pyfile):
|
|
""" Returns the code object, given a python file """
|
|
from imp import PY_COMPILED, PY_SOURCE
|
|
|
|
result, fileobj, fullpath = _check_if_pyc(pyfile)
|
|
|
|
# WARNING:
|
|
# fp.read() can blowup if the module is extremely large file.
|
|
# Lookout for overflow errors.
|
|
try:
|
|
data = fileobj.read()
|
|
finally:
|
|
fileobj.close()
|
|
|
|
# This is a .pyc file. Treat accordingly.
|
|
if result is PY_COMPILED:
|
|
# .pyc format is as follows:
|
|
# 0 - 4 bytes: Magic number, which changes with each create of .pyc file.
|
|
# First 2 bytes change with each marshal of .pyc file. Last 2 bytes is "\r\n".
|
|
# 4 - 8 bytes: Datetime value, when the .py was last changed.
|
|
# 8 - EOF: Marshalled code object data.
|
|
# So to get code object, just read the 8th byte onwards till EOF, and
|
|
# UN-marshal it.
|
|
import marshal
|
|
code_obj = marshal.loads(data[8:])
|
|
|
|
elif result is PY_SOURCE:
|
|
# This is a .py file.
|
|
code_obj = compile(data, fullpath, 'exec')
|
|
|
|
else:
|
|
# Unsupported extension
|
|
raise Exception("Input file is unknown format: {0}".format(fullpath))
|
|
|
|
# Return code object
|
|
return code_obj
|
|
|
|
if six.PY3:
|
|
def execfile_(fname, *args):
|
|
if fname.endswith(".pyc"):
|
|
code = _get_codeobj(fname)
|
|
else:
|
|
code = compile(open(fname, 'rb').read(), fname, 'exec')
|
|
return six.exec_(code, *args)
|
|
|
|
def bytes_to_str(b):
|
|
if isinstance(b, six.text_type):
|
|
return b
|
|
return str(b, 'latin1')
|
|
|
|
import urllib.parse
|
|
|
|
def unquote_to_wsgi_str(string):
|
|
return _unquote_to_bytes(string).decode('latin-1')
|
|
|
|
_unquote_to_bytes = urllib.parse.unquote_to_bytes
|
|
|
|
else:
|
|
def execfile_(fname, *args):
|
|
""" Overriding PY2 execfile() implementation to support .pyc files """
|
|
if fname.endswith(".pyc"):
|
|
return six.exec_(_get_codeobj(fname), *args)
|
|
return execfile(fname, *args)
|
|
|
|
def bytes_to_str(s):
|
|
if isinstance(s, unicode):
|
|
return s.encode('utf-8')
|
|
return s
|
|
|
|
import urllib
|
|
unquote_to_wsgi_str = urllib.unquote
|
|
|
|
|
|
# The following code adapted from trollius.py33_exceptions
|
|
def _wrap_error(exc, mapping, key):
|
|
if key not in mapping:
|
|
return
|
|
new_err_cls = mapping[key]
|
|
new_err = new_err_cls(*exc.args)
|
|
|
|
# raise a new exception with the original traceback
|
|
six.reraise(new_err_cls, new_err,
|
|
exc.__traceback__ if hasattr(exc, '__traceback__') else sys.exc_info()[2])
|
|
|
|
if PY33:
|
|
import builtins
|
|
|
|
BlockingIOError = builtins.BlockingIOError
|
|
BrokenPipeError = builtins.BrokenPipeError
|
|
ChildProcessError = builtins.ChildProcessError
|
|
ConnectionRefusedError = builtins.ConnectionRefusedError
|
|
ConnectionResetError = builtins.ConnectionResetError
|
|
InterruptedError = builtins.InterruptedError
|
|
ConnectionAbortedError = builtins.ConnectionAbortedError
|
|
PermissionError = builtins.PermissionError
|
|
FileNotFoundError = builtins.FileNotFoundError
|
|
ProcessLookupError = builtins.ProcessLookupError
|
|
|
|
def wrap_error(func, *args, **kw):
|
|
return func(*args, **kw)
|
|
else:
|
|
import errno
|
|
import select
|
|
import socket
|
|
|
|
class BlockingIOError(OSError):
|
|
pass
|
|
|
|
class BrokenPipeError(OSError):
|
|
pass
|
|
|
|
class ChildProcessError(OSError):
|
|
pass
|
|
|
|
class ConnectionRefusedError(OSError):
|
|
pass
|
|
|
|
class InterruptedError(OSError):
|
|
pass
|
|
|
|
class ConnectionResetError(OSError):
|
|
pass
|
|
|
|
class ConnectionAbortedError(OSError):
|
|
pass
|
|
|
|
class PermissionError(OSError):
|
|
pass
|
|
|
|
class FileNotFoundError(OSError):
|
|
pass
|
|
|
|
class ProcessLookupError(OSError):
|
|
pass
|
|
|
|
_MAP_ERRNO = {
|
|
errno.EACCES: PermissionError,
|
|
errno.EAGAIN: BlockingIOError,
|
|
errno.EALREADY: BlockingIOError,
|
|
errno.ECHILD: ChildProcessError,
|
|
errno.ECONNABORTED: ConnectionAbortedError,
|
|
errno.ECONNREFUSED: ConnectionRefusedError,
|
|
errno.ECONNRESET: ConnectionResetError,
|
|
errno.EINPROGRESS: BlockingIOError,
|
|
errno.EINTR: InterruptedError,
|
|
errno.ENOENT: FileNotFoundError,
|
|
errno.EPERM: PermissionError,
|
|
errno.EPIPE: BrokenPipeError,
|
|
errno.ESHUTDOWN: BrokenPipeError,
|
|
errno.EWOULDBLOCK: BlockingIOError,
|
|
errno.ESRCH: ProcessLookupError,
|
|
}
|
|
|
|
def wrap_error(func, *args, **kw):
|
|
"""
|
|
Wrap socket.error, IOError, OSError, select.error to raise new specialized
|
|
exceptions of Python 3.3 like InterruptedError (PEP 3151).
|
|
"""
|
|
try:
|
|
return func(*args, **kw)
|
|
except (socket.error, IOError, OSError) as exc:
|
|
if hasattr(exc, 'winerror'):
|
|
_wrap_error(exc, _MAP_ERRNO, exc.winerror)
|
|
# _MAP_ERRNO does not contain all Windows errors.
|
|
# For some errors like "file not found", exc.errno should
|
|
# be used (ex: ENOENT).
|
|
_wrap_error(exc, _MAP_ERRNO, exc.errno)
|
|
raise
|
|
except select.error as exc:
|
|
if exc.args:
|
|
_wrap_error(exc, _MAP_ERRNO, exc.args[0])
|
|
raise
|
|
|
|
if PY26:
|
|
from urlparse import (
|
|
_parse_cache, MAX_CACHE_SIZE, clear_cache, _splitnetloc, SplitResult,
|
|
scheme_chars,
|
|
)
|
|
|
|
def urlsplit(url, scheme='', allow_fragments=True):
|
|
"""Parse a URL into 5 components:
|
|
<scheme>://<netloc>/<path>?<query>#<fragment>
|
|
Return a 5-tuple: (scheme, netloc, path, query, fragment).
|
|
Note that we don't break the components up in smaller bits
|
|
(e.g. netloc is a single string) and we don't expand % escapes."""
|
|
allow_fragments = bool(allow_fragments)
|
|
key = url, scheme, allow_fragments, type(url), type(scheme)
|
|
cached = _parse_cache.get(key, None)
|
|
if cached:
|
|
return cached
|
|
if len(_parse_cache) >= MAX_CACHE_SIZE: # avoid runaway growth
|
|
clear_cache()
|
|
netloc = query = fragment = ''
|
|
i = url.find(':')
|
|
if i > 0:
|
|
if url[:i] == 'http': # optimize the common case
|
|
scheme = url[:i].lower()
|
|
url = url[i+1:]
|
|
if url[:2] == '//':
|
|
netloc, url = _splitnetloc(url, 2)
|
|
if (('[' in netloc and ']' not in netloc) or
|
|
(']' in netloc and '[' not in netloc)):
|
|
raise ValueError("Invalid IPv6 URL")
|
|
if allow_fragments and '#' in url:
|
|
url, fragment = url.split('#', 1)
|
|
if '?' in url:
|
|
url, query = url.split('?', 1)
|
|
v = SplitResult(scheme, netloc, url, query, fragment)
|
|
_parse_cache[key] = v
|
|
return v
|
|
for c in url[:i]:
|
|
if c not in scheme_chars:
|
|
break
|
|
else:
|
|
# make sure "url" is not actually a port number (in which case
|
|
# "scheme" is really part of the path)
|
|
rest = url[i+1:]
|
|
if not rest or any(c not in '0123456789' for c in rest):
|
|
# not a port number
|
|
scheme, url = url[:i].lower(), rest
|
|
|
|
if url[:2] == '//':
|
|
netloc, url = _splitnetloc(url, 2)
|
|
if (('[' in netloc and ']' not in netloc) or
|
|
(']' in netloc and '[' not in netloc)):
|
|
raise ValueError("Invalid IPv6 URL")
|
|
if allow_fragments and '#' in url:
|
|
url, fragment = url.split('#', 1)
|
|
if '?' in url:
|
|
url, query = url.split('?', 1)
|
|
v = SplitResult(scheme, netloc, url, query, fragment)
|
|
_parse_cache[key] = v
|
|
return v
|
|
|
|
else:
|
|
from gunicorn.six.moves.urllib.parse import urlsplit
|
|
|
|
|
|
import inspect
|
|
|
|
if hasattr(inspect, 'signature'):
|
|
positionals = (
|
|
inspect.Parameter.POSITIONAL_ONLY,
|
|
inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
|
)
|
|
|
|
def get_arity(f):
|
|
sig = inspect.signature(f)
|
|
arity = 0
|
|
|
|
for param in sig.parameters.values():
|
|
if param.kind in positionals:
|
|
arity += 1
|
|
|
|
return arity
|
|
else:
|
|
def get_arity(f):
|
|
return len(inspect.getargspec(f)[0])
|
|
|
|
|
|
try:
|
|
import html
|
|
|
|
def html_escape(s):
|
|
return html.escape(s)
|
|
except ImportError:
|
|
import cgi
|
|
|
|
def html_escape(s):
|
|
return cgi.escape(s, quote=True)
|
|
|