Update CherryPy to 5.1.0

This commit is contained in:
JonnyWong16 2016-04-23 16:24:41 -07:00
parent f9825410dc
commit b2304992e5
25 changed files with 2383 additions and 130 deletions

View file

@ -56,10 +56,10 @@ with customized or extended components. The core API's are:
These API's are described in the `CherryPy specification <https://bitbucket.org/cherrypy/cherrypy/wiki/CherryPySpec>`_. These API's are described in the `CherryPy specification <https://bitbucket.org/cherrypy/cherrypy/wiki/CherryPySpec>`_.
""" """
__version__ = "3.8.0" __version__ = "5.1.0"
from cherrypy._cpcompat import urljoin as _urljoin, urlencode as _urlencode from cherrypy._cpcompat import urljoin as _urljoin, urlencode as _urlencode
from cherrypy._cpcompat import basestring, unicodestr, set from cherrypy._cpcompat import basestring, unicodestr
from cherrypy._cperror import HTTPError, HTTPRedirect, InternalRedirect from cherrypy._cperror import HTTPError, HTTPRedirect, InternalRedirect
from cherrypy._cperror import NotFound, CherryPyException, TimeoutError from cherrypy._cperror import NotFound, CherryPyException, TimeoutError

View file

@ -110,11 +110,6 @@ def assert_native(n):
if not isinstance(n, nativestr): if not isinstance(n, nativestr):
raise TypeError("n must be a native str (got %s)" % type(n).__name__) raise TypeError("n must be a native str (got %s)" % type(n).__name__)
try:
set = set
except NameError:
from sets import Set as set
try: try:
# Python 3.1+ # Python 3.1+
from base64 import decodebytes as _base64_decodebytes from base64 import decodebytes as _base64_decodebytes
@ -137,17 +132,6 @@ def base64_decode(n, encoding='ISO-8859-1'):
else: else:
return b return b
try:
# Python 2.5+
from hashlib import md5
except ImportError:
from md5 import new as md5
try:
# Python 2.5+
from hashlib import sha1 as sha
except ImportError:
from sha import new as sha
try: try:
sorted = sorted sorted = sorted
@ -333,18 +317,10 @@ except ImportError:
# In Python 3, pickle is the sped-up C version. # In Python 3, pickle is the sped-up C version.
import pickle import pickle
try: import binascii
os.urandom(20)
import binascii
def random20(): def random20():
return binascii.hexlify(os.urandom(20)).decode('ascii') return binascii.hexlify(os.urandom(20)).decode('ascii')
except (AttributeError, NotImplementedError):
import random
# os.urandom not available until Python 2.4. Fall back to random.random.
def random20():
return sha('%s' % random.random()).hexdigest()
try: try:
from _thread import get_ident as get_thread_ident from _thread import get_ident as get_thread_ident

View file

@ -883,7 +883,7 @@ class Popen(object):
startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW
startupinfo.wShowWindow = _subprocess.SW_HIDE startupinfo.wShowWindow = _subprocess.SW_HIDE
comspec = os.environ.get("COMSPEC", "cmd.exe") comspec = os.environ.get("COMSPEC", "cmd.exe")
args = '{} /c "{}"'.format(comspec, args) args = '{0} /c "{1}"'.format(comspec, args)
if (_subprocess.GetVersion() >= 0x80000000 or if (_subprocess.GetVersion() >= 0x80000000 or
os.path.basename(comspec).lower() == "command.com"): os.path.basename(comspec).lower() == "command.com"):
# Win9x, or using command.com on NT. We need to # Win9x, or using command.com on NT. We need to
@ -1029,7 +1029,7 @@ class Popen(object):
elif sig == signal.CTRL_BREAK_EVENT: elif sig == signal.CTRL_BREAK_EVENT:
os.kill(self.pid, signal.CTRL_BREAK_EVENT) os.kill(self.pid, signal.CTRL_BREAK_EVENT)
else: else:
raise ValueError("Unsupported signal: {}".format(sig)) raise ValueError("Unsupported signal: {0}".format(sig))
def terminate(self): def terminate(self):
"""Terminates the process """Terminates the process

View file

@ -119,7 +119,7 @@ style) context manager.
""" """
import cherrypy import cherrypy
from cherrypy._cpcompat import set, basestring from cherrypy._cpcompat import basestring
from cherrypy.lib import reprconf from cherrypy.lib import reprconf
# Deprecated in CherryPy 3.2--remove in 3.3 # Deprecated in CherryPy 3.2--remove in 3.3

View file

@ -18,7 +18,6 @@ except AttributeError:
classtype = type classtype = type
import cherrypy import cherrypy
from cherrypy._cpcompat import set
class PageHandler(object): class PageHandler(object):

View file

@ -296,7 +296,8 @@ class AppResponse(object):
"""Create a Request object using environ.""" """Create a Request object using environ."""
env = self.environ.get env = self.environ.get
local = httputil.Host('', int(env('SERVER_PORT', 80)), local = httputil.Host('',
int(env('SERVER_PORT', 80) or -1),
env('SERVER_NAME', '')) env('SERVER_NAME', ''))
remote = httputil.Host(env('REMOTE_ADDR', ''), remote = httputil.Host(env('REMOTE_ADDR', ''),
int(env('REMOTE_PORT', -1) or -1), int(env('REMOTE_PORT', -1) or -1),

View file

@ -53,15 +53,12 @@ def start(configfiles=None, daemonize=False, environment=None,
cherrypy.server.unsubscribe() cherrypy.server.unsubscribe()
addr = cherrypy.server.bind_addr addr = cherrypy.server.bind_addr
if fastcgi: cls = (
f = servers.FlupFCGIServer(application=cherrypy.tree, servers.FlupFCGIServer if fastcgi else
bindAddress=addr) servers.FlupSCGIServer if scgi else
elif scgi: servers.FlupCGIServer
f = servers.FlupSCGIServer(application=cherrypy.tree, )
bindAddress=addr) f = cls(application=cherrypy.tree, bindAddress=addr)
else:
f = servers.FlupCGIServer(application=cherrypy.tree,
bindAddress=addr)
s = servers.ServerAdapter(engine, httpserver=f, bind_addr=addr) s = servers.ServerAdapter(engine, httpserver=f, bind_addr=addr)
s.subscribe() s.subscribe()

View file

@ -23,10 +23,11 @@ __date__ = 'April 2009'
import time import time
from hashlib import md5
from cherrypy._cpcompat import parse_http_list, parse_keqv_list from cherrypy._cpcompat import parse_http_list, parse_keqv_list
import cherrypy import cherrypy
from cherrypy._cpcompat import md5, ntob from cherrypy._cpcompat import ntob
md5_hex = lambda s: md5(ntob(s)).hexdigest() md5_hex = lambda s: md5(ntob(s)).hexdigest()
qop_auth = 'auth' qop_auth = 'auth'

View file

@ -210,6 +210,7 @@ def extrapolate_statistics(scope):
# -------------------- CherryPy Applications Statistics --------------------- # # -------------------- CherryPy Applications Statistics --------------------- #
import sys
import threading import threading
import time import time
@ -294,6 +295,11 @@ class ByteCountWrapper(object):
average_uriset_time = lambda s: s['Count'] and (s['Sum'] / s['Count']) or 0 average_uriset_time = lambda s: s['Count'] and (s['Sum'] / s['Count']) or 0
def _get_threading_ident():
if sys.version_info >= (3, 3):
return threading.get_ident()
return threading._get_ident()
class StatsTool(cherrypy.Tool): class StatsTool(cherrypy.Tool):
"""Record various information about the current request.""" """Record various information about the current request."""
@ -322,7 +328,7 @@ class StatsTool(cherrypy.Tool):
appstats['Current Requests'] += 1 appstats['Current Requests'] += 1
appstats['Total Requests'] += 1 appstats['Total Requests'] += 1
appstats['Requests'][threading._get_ident()] = { appstats['Requests'][_get_threading_ident()] = {
'Bytes Read': None, 'Bytes Read': None,
'Bytes Written': None, 'Bytes Written': None,
# Use a lambda so the ip gets updated by tools.proxy later # Use a lambda so the ip gets updated by tools.proxy later
@ -339,7 +345,7 @@ class StatsTool(cherrypy.Tool):
debug=False, **kwargs): debug=False, **kwargs):
"""Record the end of a request.""" """Record the end of a request."""
resp = cherrypy.serving.response resp = cherrypy.serving.response
w = appstats['Requests'][threading._get_ident()] w = appstats['Requests'][_get_threading_ident()]
r = cherrypy.request.rfile.bytes_read r = cherrypy.request.rfile.bytes_read
w['Bytes Read'] = r w['Bytes Read'] = r
@ -605,7 +611,13 @@ table.stats2 th {
"""Return ([headers], [rows]) for the given collection.""" """Return ([headers], [rows]) for the given collection."""
# E.g., the 'Requests' dict. # E.g., the 'Requests' dict.
headers = [] headers = []
for record in v.itervalues(): try:
# python2
vals = v.itervalues()
except AttributeError:
# python3
vals = v.values()
for record in vals:
for k3 in record: for k3 in record:
format = formatting.get(k3, missing) format = formatting.get(k3, missing)
if format is None: if format is None:

View file

@ -2,9 +2,10 @@
import logging import logging
import re import re
from hashlib import md5
import cherrypy import cherrypy
from cherrypy._cpcompat import basestring, md5, set, unicodestr from cherrypy._cpcompat import basestring, unicodestr
from cherrypy.lib import httputil as _httputil from cherrypy.lib import httputil as _httputil
from cherrypy.lib import is_iterator from cherrypy.lib import is_iterator
@ -192,11 +193,10 @@ def proxy(base=None, local='X-Forwarded-Host', remote='X-Forwarded-For',
if lbase is not None: if lbase is not None:
base = lbase.split(',')[0] base = lbase.split(',')[0]
if not base: if not base:
base = request.headers.get('Host', '127.0.0.1')
port = request.local.port port = request.local.port
if port == 80: if port != 80:
base = '127.0.0.1' base += ':%s' % port
else:
base = '127.0.0.1:%s' % port
if base.find("://") == -1: if base.find("://") == -1:
# add http:// or https:// if needed # add http:// or https:// if needed

View file

@ -2,7 +2,7 @@ import struct
import time import time
import cherrypy import cherrypy
from cherrypy._cpcompat import basestring, BytesIO, ntob, set, unicodestr from cherrypy._cpcompat import basestring, BytesIO, ntob, unicodestr
from cherrypy.lib import file_generator from cherrypy.lib import file_generator
from cherrypy.lib import is_closable_iterator from cherrypy.lib import is_closable_iterator
from cherrypy.lib import set_vary_header from cherrypy.lib import set_vary_header

View file

@ -62,7 +62,9 @@ __all__ = ("digestAuth", "basicAuth", "doAuth", "checkResponse",
########################################################################## ##########################################################################
import time import time
from cherrypy._cpcompat import base64_decode, ntob, md5 from hashlib import md5
from cherrypy._cpcompat import base64_decode, ntob
from cherrypy._cpcompat import parse_http_list, parse_keqv_list from cherrypy._cpcompat import parse_http_list, parse_keqv_list
MD5 = "MD5" MD5 = "MD5"

View file

@ -8,7 +8,7 @@ You can profile any of your pages as follows::
from cherrypy.lib import profiler from cherrypy.lib import profiler
class Root: class Root:
p = profile.Profiler("/path/to/profile/dir") p = profiler.Profiler("/path/to/profile/dir")
def index(self): def index(self):
self.p.run(self._index) self.p.run(self._index)

View file

@ -281,6 +281,7 @@ class _Builder2:
# Everything else becomes args # Everything else becomes args
else : else :
args.append(self.build(child)) args.append(self.build(child))
return callee(*args, **kwargs) return callee(*args, **kwargs)
def build_Keyword(self, o): def build_Keyword(self, o):
@ -377,7 +378,39 @@ class _Builder3:
def build_Index(self, o): def build_Index(self, o):
return self.build(o.value) return self.build(o.value)
def _build_call35(self, o):
"""
Workaround for python 3.5 _ast.Call signature, docs found here
https://greentreesnakes.readthedocs.org/en/latest/nodes.html
"""
import ast
callee = self.build(o.func)
args = []
if o.args is not None:
for a in o.args:
if isinstance(a, ast.Starred):
args.append(self.build(a.value))
else:
args.append(self.build(a))
kwargs = {}
for kw in o.keywords:
if kw.arg is None: # double asterix `**`
rst = self.build(kw.value)
if not isinstance(rst, dict):
raise TypeError("Invalid argument for call."
"Must be a mapping object.")
# give preference to the keys set directly from arg=value
for k, v in rst.items():
if k not in kwargs:
kwargs[k] = v
else: # defined on the call as: arg=value
kwargs[kw.arg] = self.build(kw.value)
return callee(*args, **kwargs)
def build_Call(self, o): def build_Call(self, o):
if sys.version_info >= (3, 5):
return self._build_call35(o)
callee = self.build(o.func) callee = self.build(o.func)
if o.args is None: if o.args is None:
@ -388,13 +421,16 @@ class _Builder3:
if o.starargs is None: if o.starargs is None:
starargs = () starargs = ()
else: else:
starargs = self.build(o.starargs) starargs = tuple(self.build(o.starargs))
if o.kwargs is None: if o.kwargs is None:
kwargs = {} kwargs = {}
else: else:
kwargs = self.build(o.kwargs) kwargs = self.build(o.kwargs)
if o.keywords is not None: # direct a=b keywords
for kw in o.keywords:
# preference because is a direct keyword against **kwargs
kwargs[kw.arg] = self.build(kw.value)
return callee(*(args + starargs), **kwargs) return callee(*(args + starargs), **kwargs)
def build_List(self, o): def build_List(self, o):

View file

@ -49,7 +49,10 @@ def serve_file(path, content_type=None, disposition=None, name=None,
try: try:
st = os.stat(path) st = os.stat(path)
except OSError: except (OSError, TypeError, ValueError):
# OSError when file fails to stat
# TypeError on Python 2 when there's a null byte
# ValueError on Python 3 when there's a null byte
if debug: if debug:
cherrypy.log('os.stat(%r) failed' % path, 'TOOLS.STATIC') cherrypy.log('os.stat(%r) failed' % path, 'TOOLS.STATIC')
raise cherrypy.NotFound() raise cherrypy.NotFound()

View file

@ -8,7 +8,7 @@ import time
import threading import threading
from cherrypy._cpcompat import basestring, get_daemon, get_thread_ident from cherrypy._cpcompat import basestring, get_daemon, get_thread_ident
from cherrypy._cpcompat import ntob, set, Timer, SetDaemonProperty from cherrypy._cpcompat import ntob, Timer, SetDaemonProperty
# _module__file__base is used by Autoreload to make # _module__file__base is used by Autoreload to make
# absolute any filenames retrieved from sys.modules which are not # absolute any filenames retrieved from sys.modules which are not
@ -109,12 +109,35 @@ class SignalHandler(object):
self.handlers['SIGINT'] = self._jython_SIGINT_handler self.handlers['SIGINT'] = self._jython_SIGINT_handler
self._previous_handlers = {} self._previous_handlers = {}
# used to determine is the process is a daemon in `self._is_daemonized`
self._original_pid = os.getpid()
def _jython_SIGINT_handler(self, signum=None, frame=None): def _jython_SIGINT_handler(self, signum=None, frame=None):
# See http://bugs.jython.org/issue1313 # See http://bugs.jython.org/issue1313
self.bus.log('Keyboard Interrupt: shutting down bus') self.bus.log('Keyboard Interrupt: shutting down bus')
self.bus.exit() self.bus.exit()
def _is_daemonized(self):
"""Return boolean indicating if the current process is
running as a daemon.
The criteria to determine the `daemon` condition is to verify
if the current pid is not the same as the one that got used on
the initial construction of the plugin *and* the stdin is not
connected to a terminal.
The sole validation of the tty is not enough when the plugin
is executing inside other process like in a CI tool
(Buildbot, Jenkins).
"""
if (self._original_pid != os.getpid() and
not os.isatty(sys.stdin.fileno())):
return True
else:
return False
def subscribe(self): def subscribe(self):
"""Subscribe self.handlers to signals.""" """Subscribe self.handlers to signals."""
for sig, func in self.handlers.items(): for sig, func in self.handlers.items():
@ -180,13 +203,13 @@ class SignalHandler(object):
def handle_SIGHUP(self): def handle_SIGHUP(self):
"""Restart if daemonized, else exit.""" """Restart if daemonized, else exit."""
if os.isatty(sys.stdin.fileno()): if self._is_daemonized():
self.bus.log("SIGHUP caught while daemonized. Restarting.")
self.bus.restart()
else:
# not daemonized (may be foreground or background) # not daemonized (may be foreground or background)
self.bus.log("SIGHUP caught but not daemonized. Exiting.") self.bus.log("SIGHUP caught but not daemonized. Exiting.")
self.bus.exit() self.bus.exit()
else:
self.bus.log("SIGHUP caught while daemonized. Restarting.")
self.bus.restart()
try: try:

View file

@ -183,8 +183,7 @@ class ServerAdapter(object):
if not self.httpserver: if not self.httpserver:
return '' return ''
host, port = self.bind_addr host, port = self.bind_addr
if getattr(self.httpserver, 'ssl_certificate', None) or \ if getattr(self.httpserver, 'ssl_adapter', None):
getattr(self.httpserver, 'ssl_adapter', None):
scheme = "https" scheme = "https"
if port != 443: if port != 443:
host += ":%s" % port host += ":%s" % port

View file

@ -68,8 +68,6 @@ import time
import traceback as _traceback import traceback as _traceback
import warnings import warnings
from cherrypy._cpcompat import set
# Here I save the value of os.getcwd(), which, if I am imported early enough, # Here I save the value of os.getcwd(), which, if I am imported early enough,
# will be the directory from which the startup script was run. This is needed # will be the directory from which the startup script was run. This is needed
# by _do_execv(), to change back to the original directory before execv()ing a # by _do_execv(), to change back to the original directory before execv()ing a

View file

@ -0,0 +1,22 @@
# Apache2 server conf file for using CherryPy with mod_fcgid.
# This doesn't have to be "C:/", but it has to be a directory somewhere, and
# MUST match the directory used in the FastCgiExternalServer directive, below.
DocumentRoot "C:/"
ServerName 127.0.0.1
Listen 80
LoadModule fastcgi_module modules/mod_fastcgi.dll
LoadModule rewrite_module modules/mod_rewrite.so
Options ExecCGI
SetHandler fastcgi-script
RewriteEngine On
# Send requests for any URI to our fastcgi handler.
RewriteRule ^(.*)$ /fastcgi.pyc [L]
# The FastCgiExternalServer directive defines filename as an external FastCGI application.
# If filename does not begin with a slash (/) then it is assumed to be relative to the ServerRoot.
# The filename does not have to exist in the local filesystem. URIs that Apache resolves to this
# filename will be handled by this external FastCGI application.
FastCgiExternalServer "C:/fastcgi.pyc" -host 127.0.0.1:8088

View file

@ -0,0 +1,3 @@
[/]
log.error_file: "error.log"
log.access_file: "access.log"

View file

@ -0,0 +1,14 @@
[global]
# Uncomment this when you're done developing
#environment: "production"
server.socket_host: "0.0.0.0"
server.socket_port: 8088
# Uncomment the following lines to run on HTTPS at the same time
#server.2.socket_host: "0.0.0.0"
#server.2.socket_port: 8433
#server.2.ssl_certificate: '../test/test.pem'
#server.2.ssl_private_key: '../test/test.pem'
tree.myapp: cherrypy.Application(scaffold.root, "/", "example.conf")

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

View file

@ -68,7 +68,7 @@ class SSL_fileobject(wsgiserver.CP_fileobject):
time.sleep(self.ssl_retry) time.sleep(self.ssl_retry)
except SSL.WantWriteError: except SSL.WantWriteError:
time.sleep(self.ssl_retry) time.sleep(self.ssl_retry)
except SSL.SysCallError, e: except SSL.SysCallError as e:
if is_reader and e.args == (-1, 'Unexpected EOF'): if is_reader and e.args == (-1, 'Unexpected EOF'):
return "" return ""
@ -76,7 +76,7 @@ class SSL_fileobject(wsgiserver.CP_fileobject):
if is_reader and errnum in wsgiserver.socket_errors_to_ignore: if is_reader and errnum in wsgiserver.socket_errors_to_ignore:
return "" return ""
raise socket.error(errnum) raise socket.error(errnum)
except SSL.Error, e: except SSL.Error as e:
if is_reader and e.args == (-1, 'Unexpected EOF'): if is_reader and e.args == (-1, 'Unexpected EOF'):
return "" return ""

View file

@ -75,7 +75,8 @@ __all__ = ['HTTPRequest', 'HTTPConnection', 'HTTPServer',
'WorkerThread', 'ThreadPool', 'SSLAdapter', 'WorkerThread', 'ThreadPool', 'SSLAdapter',
'CherryPyWSGIServer', 'CherryPyWSGIServer',
'Gateway', 'WSGIGateway', 'WSGIGateway_10', 'WSGIGateway_u0', 'Gateway', 'WSGIGateway', 'WSGIGateway_10', 'WSGIGateway_u0',
'WSGIPathInfoDispatcher', 'get_ssl_adapter_class'] 'WSGIPathInfoDispatcher', 'get_ssl_adapter_class',
'socket_errors_to_ignore']
import os import os
try: try:
@ -83,19 +84,33 @@ try:
except: except:
import Queue as queue import Queue as queue
import re import re
import rfc822 import email.utils
import socket import socket
import sys import sys
import threading
import time
import traceback as traceback_
import operator
from urllib import unquote
import warnings
import errno
import logging
try:
# prefer slower Python-based io module
import _pyio as io
except ImportError:
# Python 2.6
import io
if 'win' in sys.platform and hasattr(socket, "AF_INET6"): if 'win' in sys.platform and hasattr(socket, "AF_INET6"):
if not hasattr(socket, 'IPPROTO_IPV6'): if not hasattr(socket, 'IPPROTO_IPV6'):
socket.IPPROTO_IPV6 = 41 socket.IPPROTO_IPV6 = 41
if not hasattr(socket, 'IPV6_V6ONLY'): if not hasattr(socket, 'IPV6_V6ONLY'):
socket.IPV6_V6ONLY = 27 socket.IPV6_V6ONLY = 27
try:
import cStringIO as StringIO
except ImportError: DEFAULT_BUFFER_SIZE = io.DEFAULT_BUFFER_SIZE
import StringIO
DEFAULT_BUFFER_SIZE = -1
class FauxSocket(object): class FauxSocket(object):
@ -109,23 +124,6 @@ _fileobject_uses_str_type = isinstance(
socket._fileobject(FauxSocket())._rbuf, basestring) socket._fileobject(FauxSocket())._rbuf, basestring)
del FauxSocket # this class is not longer required for anything. del FauxSocket # this class is not longer required for anything.
import threading
import time
import traceback
def format_exc(limit=None):
"""Like print_exc() but return a string. Backport for Python 2.3."""
try:
etype, value, tb = sys.exc_info()
return ''.join(traceback.format_exception(etype, value, tb, limit))
finally:
etype = value = tb = None
import operator
from urllib import unquote
import warnings
if sys.version_info >= (3, 0): if sys.version_info >= (3, 0):
bytestr = bytes bytestr = bytes
@ -165,8 +163,6 @@ ASTERISK = ntob('*')
FORWARD_SLASH = ntob('/') FORWARD_SLASH = ntob('/')
quoted_slash = re.compile(ntob("(?i)%2F")) quoted_slash = re.compile(ntob("(?i)%2F"))
import errno
def plat_specific_errors(*errnames): def plat_specific_errors(*errnames):
"""Return error numbers for all errors in errnames on this platform. """Return error numbers for all errors in errnames on this platform.
@ -210,7 +206,6 @@ comma_separated_headers = [
] ]
import logging
if not hasattr(logging, 'statistics'): if not hasattr(logging, 'statistics'):
logging.statistics = {} logging.statistics = {}
@ -674,6 +669,10 @@ class HTTPRequest(object):
# uri may be an abs_path (including "http://host.domain.tld"); # uri may be an abs_path (including "http://host.domain.tld");
scheme, authority, path = self.parse_request_uri(uri) scheme, authority, path = self.parse_request_uri(uri)
if path is None:
self.simple_response("400 Bad Request",
"Invalid path in Request-URI.")
return False
if NUMBER_SIGN in path: if NUMBER_SIGN in path:
self.simple_response("400 Bad Request", self.simple_response("400 Bad Request",
"Illegal #fragment in Request-URI.") "Illegal #fragment in Request-URI.")
@ -970,7 +969,7 @@ class HTTPRequest(object):
self.rfile.read(remaining) self.rfile.read(remaining)
if "date" not in hkeys: if "date" not in hkeys:
self.outheaders.append(("Date", rfc822.formatdate())) self.outheaders.append(("Date", email.utils.formatdate()))
if "server" not in hkeys: if "server" not in hkeys:
self.outheaders.append(("Server", self.server.server_name)) self.outheaders.append(("Server", self.server.server_name))
@ -1051,7 +1050,7 @@ class CP_fileobject(socket._fileobject):
if size < 0: if size < 0:
# Read until EOF # Read until EOF
# reset _rbuf. we consume it via buf. # reset _rbuf. we consume it via buf.
self._rbuf = StringIO.StringIO() self._rbuf = io.BytesIO()
while True: while True:
data = self.recv(rbufsize) data = self.recv(rbufsize)
if not data: if not data:
@ -1066,12 +1065,12 @@ class CP_fileobject(socket._fileobject):
# return. # return.
buf.seek(0) buf.seek(0)
rv = buf.read(size) rv = buf.read(size)
self._rbuf = StringIO.StringIO() self._rbuf = io.BytesIO()
self._rbuf.write(buf.read()) self._rbuf.write(buf.read())
return rv return rv
# reset _rbuf. we consume it via buf. # reset _rbuf. we consume it via buf.
self._rbuf = StringIO.StringIO() self._rbuf = io.BytesIO()
while True: while True:
left = size - buf_len left = size - buf_len
# recv() will malloc the amount of memory given as its # recv() will malloc the amount of memory given as its
@ -1109,7 +1108,7 @@ class CP_fileobject(socket._fileobject):
buf.seek(0) buf.seek(0)
bline = buf.readline(size) bline = buf.readline(size)
if bline.endswith('\n') or len(bline) == size: if bline.endswith('\n') or len(bline) == size:
self._rbuf = StringIO.StringIO() self._rbuf = io.BytesIO()
self._rbuf.write(buf.read()) self._rbuf.write(buf.read())
return bline return bline
del bline del bline
@ -1120,7 +1119,7 @@ class CP_fileobject(socket._fileobject):
buf.seek(0) buf.seek(0)
buffers = [buf.read()] buffers = [buf.read()]
# reset _rbuf. we consume it via buf. # reset _rbuf. we consume it via buf.
self._rbuf = StringIO.StringIO() self._rbuf = io.BytesIO()
data = None data = None
recv = self.recv recv = self.recv
while data != "\n": while data != "\n":
@ -1132,7 +1131,7 @@ class CP_fileobject(socket._fileobject):
buf.seek(0, 2) # seek end buf.seek(0, 2) # seek end
# reset _rbuf. we consume it via buf. # reset _rbuf. we consume it via buf.
self._rbuf = StringIO.StringIO() self._rbuf = io.BytesIO()
while True: while True:
data = self.recv(self._rbufsize) data = self.recv(self._rbufsize)
if not data: if not data:
@ -1154,11 +1153,11 @@ class CP_fileobject(socket._fileobject):
if buf_len >= size: if buf_len >= size:
buf.seek(0) buf.seek(0)
rv = buf.read(size) rv = buf.read(size)
self._rbuf = StringIO.StringIO() self._rbuf = io.BytesIO()
self._rbuf.write(buf.read()) self._rbuf.write(buf.read())
return rv return rv
# reset _rbuf. we consume it via buf. # reset _rbuf. we consume it via buf.
self._rbuf = StringIO.StringIO() self._rbuf = io.BytesIO()
while True: while True:
data = self.recv(self._rbufsize) data = self.recv(self._rbufsize)
if not data: if not data:
@ -1757,7 +1756,7 @@ class HTTPServer(object):
timeout = 10 timeout = 10
"""The timeout in seconds for accepted connections (default 10).""" """The timeout in seconds for accepted connections (default 10)."""
version = "CherryPy/3.8.0" version = "CherryPy/5.1.0"
"""A version string for the HTTPServer.""" """A version string for the HTTPServer."""
software = None software = None
@ -1884,25 +1883,6 @@ class HTTPServer(object):
if self.software is None: if self.software is None:
self.software = "%s Server" % self.version self.software = "%s Server" % self.version
# SSL backward compatibility
if (self.ssl_adapter is None and
getattr(self, 'ssl_certificate', None) and
getattr(self, 'ssl_private_key', None)):
warnings.warn(
"SSL attributes are deprecated in CherryPy 3.2, and will "
"be removed in CherryPy 3.3. Use an ssl_adapter attribute "
"instead.",
DeprecationWarning
)
try:
from cherrypy.wsgiserver.ssl_pyopenssl import pyOpenSSLAdapter
except ImportError:
pass
else:
self.ssl_adapter = pyOpenSSLAdapter(
self.ssl_certificate, self.ssl_private_key,
getattr(self, 'ssl_certificate_chain', None))
# Select the appropriate socket # Select the appropriate socket
if isinstance(self.bind_addr, basestring): if isinstance(self.bind_addr, basestring):
# AF_UNIX socket # AF_UNIX socket
@ -1915,7 +1895,7 @@ class HTTPServer(object):
# So everyone can access the socket... # So everyone can access the socket...
try: try:
os.chmod(self.bind_addr, 511) # 0777 os.chmod(self.bind_addr, 0o777)
except: except:
pass pass
@ -1984,7 +1964,7 @@ class HTTPServer(object):
sys.stderr.write(msg + '\n') sys.stderr.write(msg + '\n')
sys.stderr.flush() sys.stderr.flush()
if traceback: if traceback:
tblines = format_exc() tblines = traceback_.format_exc()
sys.stderr.write(tblines) sys.stderr.write(tblines)
sys.stderr.flush() sys.stderr.flush()
@ -2186,7 +2166,7 @@ ssl_adapters = {
} }
def get_ssl_adapter_class(name='pyopenssl'): def get_ssl_adapter_class(name='builtin'):
"""Return an SSL adapter class for the given name.""" """Return an SSL adapter class for the given name."""
adapter = ssl_adapters[name.lower()] adapter = ssl_adapters[name.lower()]
if isinstance(adapter, basestring): if isinstance(adapter, basestring):

File diff suppressed because it is too large Load diff