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)
 | |
| 
 |