summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason R. Coombs <jaraco@jaraco.com>2016-04-30 11:45:18 -0400
committerJason R. Coombs <jaraco@jaraco.com>2016-04-30 11:45:18 -0400
commitbaf1cfad6a76e98adc078f36a70a5ceecd6138fb (patch)
tree61ccef2f4f66a3fb56863db1d03098deb24c4439
parent32a163ca17e1c3d78945ad2214e6c1fb5a8e0bf1 (diff)
parent7f77d77d18234382582c8a3a3e2a526841e900ba (diff)
downloadcherrypy-baf1cfad6a76e98adc078f36a70a5ceecd6138fb.tar.gz
Merge https://bitbucket.org/cherrypy/cherrypy/pull-requests/125/
-rw-r--r--.travis.yml20
-rw-r--r--CHANGES.txt15
-rw-r--r--CONTRIBUTING.txt2
-rw-r--r--cherrypy/__init__.py13
-rw-r--r--cherrypy/_cpdispatch.py4
-rw-r--r--cherrypy/_cpreqbody.py2
-rw-r--r--cherrypy/_cptools.py4
-rw-r--r--cherrypy/lib/caching.py2
-rw-r--r--cherrypy/lib/httputil.py2
-rw-r--r--cherrypy/lib/sessions.py2
-rw-r--r--cherrypy/process/wspbus.py6
-rw-r--r--cherrypy/test/test_config_server.py2
-rw-r--r--cherrypy/test/test_conn.py2
-rw-r--r--cherrypy/test/test_core.py4
-rw-r--r--cherrypy/test/test_http.py4
-rw-r--r--cherrypy/test/test_mime.py2
-rw-r--r--cherrypy/test/test_objectmapping.py4
-rw-r--r--cherrypy/test/test_proxy.py2
-rw-r--r--cherrypy/test/test_request_obj.py10
-rw-r--r--cherrypy/test/test_xmlrpc.py2
-rw-r--r--cherrypy/wsgiserver/ssl_builtin.py27
-rw-r--r--cherrypy/wsgiserver/wsgiserver2.py32
-rw-r--r--cherrypy/wsgiserver/wsgiserver3.py32
-rw-r--r--docs/install.rst6
-rw-r--r--docs/tutorials.rst3
-rw-r--r--release.py62
-rw-r--r--setup.cfg26
-rw-r--r--setup.py2
28 files changed, 168 insertions, 126 deletions
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 00000000..18b91098
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,20 @@
+language: python
+python:
+- 2.6
+- 2.7
+- 3.2
+- 3.3
+- 3.4
+- 3.5
+script:
+- nosetests -s .
+deploy:
+ provider: pypi
+ on:
+ tags: true
+ all_branches: true
+ python: 3.5
+ user: jaraco
+ password:
+ secure: CQqUvtssQ4wmRluPcxh6m5lIXi83Qu9dAFAvZLS/+AQNIG78XECXv5xFTEdGSLX9yncKDpDKI3xRJeCKyO4OJUN0t6W1MRycY72+R63i9e9wPjfvtRqYH1TBT+no7jj/DHqXIrWSlpjRNAt4XXeSv7OzKWT4PmTNkNQSKyS1DWCmZGlbCKlV774Z9PbrfltflxL0V6DiX6ZfoY1THBO4rIopjMk/MPLgS5zvwLgXVbT9sK/DcPOgOq47iSLCs0oScbwiFzYW4DbcVZrBMv4ALtQTjk6ZEaBQ7KtKgsyxgi/ToVhjRxYg4rwvhjsyjixUdECLUqL3WgWfzW/lo82lhb79ERwhnjf1DvPNexlXhv9hHwHsFROpaOmM0nyDJsJg0rCNPVfO4SpBHEnd/ujlHO6yorHj0S54jZWqqDwD5gN19v3hEMT48Pc8uvazE9K1kMQbNXEzqn+SJjVB+DG7qK5Jm9Kk7ZC4R88hJAJNsR+SlFCXMGzkS9WUefUGLHQFfezZk43sMPIXMnh9d2XqCQo4QpUawdg3pwaTukFfyaHlK39CIHhZNas5D/UFL5spQPAAkH1IMcPILiSUwYYnXIJFWJIiulfEQalJroAQjrzvst/NVB8BbeYuCfmVLVOZw8Y6GOYONGgiXjT3nfmw/dN+uw+GY3EgAV5jl+fa434=
+ distributions: release
diff --git a/CHANGES.txt b/CHANGES.txt
index 2652b6d6..af9c7322 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,18 @@
+5.3.0
+-----
+
+* #1202: Add support for specifying a certificate authority when
+ serving SSL using the built-in SSL support.
+* Use ssl.create_default_context when available.
+* #1392: Catch platform-specific socket errors on OS X.
+* #1386: Fix parsing of URIs containing ``://`` in the path part.
+
+5.2.0
+-----
+
+* #1410: Moved hosting to Github (
+ `cherrypy/cherrypy <https://github.com/cherrypy/cherrypy>`_.
+
5.1.0
-----
diff --git a/CONTRIBUTING.txt b/CONTRIBUTING.txt
index 6c653f75..c321e13a 100644
--- a/CONTRIBUTING.txt
+++ b/CONTRIBUTING.txt
@@ -3,4 +3,4 @@ CherryPy is a community-maintained, open-source project hosted at Bitbucket.
To contribute, first read `How to write the perfect pull request
<http://blog.jaraco.com/2014/04/how-to-write-perfect-pull-request.html>`_
and file your contribution with the `CherryPy Project page
-<https://bitbucket.org/cherrypy/cherrypy>`_.
+<https://github.com/cherrypy/cherrypy>`_.
diff --git a/cherrypy/__init__.py b/cherrypy/__init__.py
index 6e2f9bdb..30a8cadf 100644
--- a/cherrypy/__init__.py
+++ b/cherrypy/__init__.py
@@ -56,7 +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>`_.
"""
-__version__ = "5.1.0"
+try:
+ import pkg_resources
+except ImportError:
+ pass
from cherrypy._cpcompat import urljoin as _urljoin, urlencode as _urlencode
from cherrypy._cpcompat import basestring, unicodestr
@@ -88,6 +91,12 @@ except ImportError:
engine = process.bus
+try:
+ __version__ = pkg_resources.require('cherrypy')[0].version
+except Exception:
+ __version__ = 'unknown'
+
+
# Timeout monitor. We add two channels to the engine
# to which cherrypy.Application will publish.
engine.listeners['before_request'] = set()
@@ -318,7 +327,7 @@ class _GlobalLogManager(_cplogging.LogManager):
"""Log the given message to the app.log or global log as appropriate.
"""
# Do NOT use try/except here. See
- # https://bitbucket.org/cherrypy/cherrypy/issue/945
+ # https://github.com/cherrypy/cherrypy/issues/945
if hasattr(request, 'app') and hasattr(request.app, 'log'):
log = request.app.log
else:
diff --git a/cherrypy/_cpdispatch.py b/cherrypy/_cpdispatch.py
index 710bb3fd..2cb03c7e 100644
--- a/cherrypy/_cpdispatch.py
+++ b/cherrypy/_cpdispatch.py
@@ -422,7 +422,7 @@ class Dispatcher(object):
object_trail.insert(
i + 1, ["default", defhandler, conf, segleft])
request.config = set_conf()
- # See https://bitbucket.org/cherrypy/cherrypy/issue/613
+ # See https://github.com/cherrypy/cherrypy/issues/613
request.is_index = path.endswith("/")
return defhandler, fullpath[fullpath_len - segleft:-1]
@@ -675,7 +675,7 @@ def VirtualHost(next_dispatcher=Dispatcher(), use_x_forwarded_host=True,
result = next_dispatcher(path_info)
# Touch up staticdir config. See
- # https://bitbucket.org/cherrypy/cherrypy/issue/614.
+ # https://github.com/cherrypy/cherrypy/issues/614.
section = request.config.get('tools.staticdir.section')
if section:
section = section[len(prefix):]
diff --git a/cherrypy/_cpreqbody.py b/cherrypy/_cpreqbody.py
index d2dbbc92..13a8adb7 100644
--- a/cherrypy/_cpreqbody.py
+++ b/cherrypy/_cpreqbody.py
@@ -940,7 +940,7 @@ class RequestBody(Entity):
# Don't parse the request body at all if the client didn't provide
# a Content-Type header. See
- # https://bitbucket.org/cherrypy/cherrypy/issue/790
+ # https://github.com/cherrypy/cherrypy/issues/790
default_content_type = ''
"""This defines a default ``Content-Type`` to use if no Content-Type header
is given. The empty string is used for RequestBody, which results in the
diff --git a/cherrypy/_cptools.py b/cherrypy/_cptools.py
index 06a56e87..af76ae06 100644
--- a/cherrypy/_cptools.py
+++ b/cherrypy/_cptools.py
@@ -271,7 +271,7 @@ class SessionTool(Tool):
body. This is off by default for safety reasons; for example,
a large upload would block the session, denying an AJAX
progress meter
- (`issue <https://bitbucket.org/cherrypy/cherrypy/issue/630>`_).
+ (`issue <https://github.com/cherrypy/cherrypy/issues/630>`_).
When 'explicit' (or any other value), you need to call
cherrypy.session.acquire_lock() yourself before using
@@ -376,7 +376,7 @@ class XMLRPCController(object):
body = subhandler(*(vpath + rpcparams), **params)
else:
- # https://bitbucket.org/cherrypy/cherrypy/issue/533
+ # https://github.com/cherrypy/cherrypy/issues/533
# if a method is not found, an xmlrpclib.Fault should be returned
# raising an exception here will do that; see
# cherrypy.lib.xmlrpcutil.on_error
diff --git a/cherrypy/lib/caching.py b/cherrypy/lib/caching.py
index fab6b569..375d5f0e 100644
--- a/cherrypy/lib/caching.py
+++ b/cherrypy/lib/caching.py
@@ -353,7 +353,7 @@ def get(invalid_methods=("POST", "PUT", "DELETE"), debug=False, **kwargs):
return False
# Copy the response headers. See
- # https://bitbucket.org/cherrypy/cherrypy/issue/721.
+ # https://github.com/cherrypy/cherrypy/issues/721.
response.headers = rh = httputil.HeaderMap()
for k in h:
dict.__setitem__(rh, k, dict.__getitem__(h, k))
diff --git a/cherrypy/lib/httputil.py b/cherrypy/lib/httputil.py
index 69a18d45..f249e6dd 100644
--- a/cherrypy/lib/httputil.py
+++ b/cherrypy/lib/httputil.py
@@ -13,7 +13,7 @@ from cherrypy._cpcompat import basestring, bytestr, iteritems, nativestr
from cherrypy._cpcompat import reversed, sorted, unicodestr, unquote_qs
response_codes = BaseHTTPRequestHandler.responses.copy()
-# From https://bitbucket.org/cherrypy/cherrypy/issue/361
+# From https://github.com/cherrypy/cherrypy/issues/361
response_codes[500] = ('Internal Server Error',
'The server encountered an unexpected condition '
'which prevented it from fulfilling the request.')
diff --git a/cherrypy/lib/sessions.py b/cherrypy/lib/sessions.py
index 37556363..e9605cb8 100644
--- a/cherrypy/lib/sessions.py
+++ b/cherrypy/lib/sessions.py
@@ -182,7 +182,7 @@ class Session(object):
cherrypy.log('Expired or malicious session %r; '
'making a new one' % id, 'TOOLS.SESSIONS')
# Expired or malicious session. Make a new one.
- # See https://bitbucket.org/cherrypy/cherrypy/issue/709.
+ # See https://github.com/cherrypy/cherrypy/issues/709.
self.id = None
self.missing = True
self._regenerate()
diff --git a/cherrypy/process/wspbus.py b/cherrypy/process/wspbus.py
index c9de3511..9c9a2739 100644
--- a/cherrypy/process/wspbus.py
+++ b/cherrypy/process/wspbus.py
@@ -85,7 +85,7 @@ class ChannelFailures(Exception):
def __init__(self, *args, **kwargs):
# Don't use 'super' here; Exceptions are old-style in Py2.4
- # See https://bitbucket.org/cherrypy/cherrypy/issue/959
+ # See https://github.com/cherrypy/cherrypy/issues/959
Exception.__init__(self, *args, **kwargs)
self._exceptions = list()
@@ -317,10 +317,10 @@ class Bus(object):
raise
# Waiting for ALL child threads to finish is necessary on OS X.
- # See https://bitbucket.org/cherrypy/cherrypy/issue/581.
+ # See https://github.com/cherrypy/cherrypy/issues/581.
# It's also good to let them all shut down before allowing
# the main thread to call atexit handlers.
- # See https://bitbucket.org/cherrypy/cherrypy/issue/751.
+ # See https://github.com/cherrypy/cherrypy/issues/751.
self.log("Waiting for child threads to terminate...")
for t in threading.enumerate():
# Validate the we're not trying to join the MainThread
diff --git a/cherrypy/test/test_config_server.py b/cherrypy/test/test_config_server.py
index 40504d8f..f4f574de 100644
--- a/cherrypy/test/test_config_server.py
+++ b/cherrypy/test/test_config_server.py
@@ -93,7 +93,7 @@ class ServerConfigTests(helper.CPWebCase):
self.getPage("/", headers=[('From', "x" * 500)])
self.assertStatus(413)
- # Test for https://bitbucket.org/cherrypy/cherrypy/issue/421
+ # Test for https://github.com/cherrypy/cherrypy/issues/421
# (Incorrect border condition in readline of SizeCheckWrapper).
# This hangs in rev 891 and earlier.
lines256 = "x" * 248
diff --git a/cherrypy/test/test_conn.py b/cherrypy/test/test_conn.py
index 6577e03a..3e0cbc16 100644
--- a/cherrypy/test/test_conn.py
+++ b/cherrypy/test/test_conn.py
@@ -205,7 +205,7 @@ class ConnectionCloseTests(helper.CPWebCase):
self.assertRaises(NotConnected, self.getPage, "/")
# Try HEAD. See
- # https://bitbucket.org/cherrypy/cherrypy/issue/864.
+ # https://github.com/cherrypy/cherrypy/issues/864.
self.getPage("/stream", method='HEAD')
self.assertStatus('200 OK')
self.assertBody('')
diff --git a/cherrypy/test/test_core.py b/cherrypy/test/test_core.py
index 4ebc170a..16a0219d 100644
--- a/cherrypy/test/test_core.py
+++ b/cherrypy/test/test_core.py
@@ -403,7 +403,7 @@ class CoreRequestHandlingTest(helper.CPWebCase):
self.assertStatus(('302 Found', '303 See Other'))
# check injection protection
- # See https://bitbucket.org/cherrypy/cherrypy/issue/1003
+ # See https://github.com/cherrypy/cherrypy/issues/1003
self.getPage(
"/redirect/custom?"
"code=303&url=/foobar/%0d%0aSet-Cookie:%20somecookie=someval")
@@ -551,7 +551,7 @@ class CoreRequestHandlingTest(helper.CPWebCase):
def skip_if_bad_cookies(self):
"""
cookies module fails to reject invalid cookies
- https://bitbucket.org/cherrypy/cherrypy/issues/1405
+ https://github.com/cherrypy/cherrypy/issues/1405
"""
cookies = sys.modules.get('http.cookies')
_is_legal_key = getattr(cookies, '_is_legal_key', lambda x: False)
diff --git a/cherrypy/test/test_http.py b/cherrypy/test/test_http.py
index 0df589fa..46ae226c 100644
--- a/cherrypy/test/test_http.py
+++ b/cherrypy/test/test_http.py
@@ -150,7 +150,7 @@ class HTTPTests(helper.CPWebCase):
def test_post_filename_with_commas(self):
'''Testing that we can handle filenames with commas. This was
reported as a bug in:
- https://bitbucket.org/cherrypy/cherrypy/issue/1146/'''
+ https://github.com/cherrypy/cherrypy/issues/1146/'''
# We'll upload a bunch of files with differing names.
for fname in ['boop.csv', 'foo, bar.csv', 'bar, xxxx.csv', 'file"name.csv']:
files = [('myfile', fname, 'yunyeenyunyue')]
@@ -200,7 +200,7 @@ class HTTPTests(helper.CPWebCase):
c = self.make_connection()
c.putrequest('GET', '/')
c.putheader('Content-Type', 'text/plain')
- # See https://bitbucket.org/cherrypy/cherrypy/issue/941
+ # See https://github.com/cherrypy/cherrypy/issues/941
c._output(ntob('Re, 1.2.3.4#015#012'))
c.endheaders()
diff --git a/cherrypy/test/test_mime.py b/cherrypy/test/test_mime.py
index f5f2b9fb..ca2f9c63 100644
--- a/cherrypy/test/test_mime.py
+++ b/cherrypy/test/test_mime.py
@@ -74,7 +74,7 @@ This is the <strong>HTML</strong> version
'--X',
# Test a param with more than one value.
# See
- # https://bitbucket.org/cherrypy/cherrypy/issue/1028
+ # https://github.com/cherrypy/cherrypy/issues/1028
'Content-Disposition: form-data; name="baz"',
'',
'111',
diff --git a/cherrypy/test/test_objectmapping.py b/cherrypy/test/test_objectmapping.py
index e80a7a71..a24e84e1 100644
--- a/cherrypy/test/test_objectmapping.py
+++ b/cherrypy/test/test_objectmapping.py
@@ -281,7 +281,7 @@ class ObjectMappingTest(helper.CPWebCase):
# Make sure /foobar maps to Root.foobar and not to the app
# mounted at /foo. See
- # https://bitbucket.org/cherrypy/cherrypy/issue/573
+ # https://github.com/cherrypy/cherrypy/issues/573
self.getPage("/foobar")
self.assertBody("bar")
@@ -332,7 +332,7 @@ class ObjectMappingTest(helper.CPWebCase):
self.assertBody("default for dir1, param is:('dir2', '5', '3', 'sir')")
# test that extra positional args raises an 404 Not Found
- # See https://bitbucket.org/cherrypy/cherrypy/issue/733.
+ # See https://github.com/cherrypy/cherrypy/issues/733.
self.getPage("/dir1/dir2/script_name/extra/stuff")
self.assertStatus(404)
diff --git a/cherrypy/test/test_proxy.py b/cherrypy/test/test_proxy.py
index 821a4e52..bdc5eada 100644
--- a/cherrypy/test/test_proxy.py
+++ b/cherrypy/test/test_proxy.py
@@ -131,7 +131,7 @@ class ProxyTest(helper.CPWebCase):
self.assertBody(expected)
# Test trailing slash (see
- # https://bitbucket.org/cherrypy/cherrypy/issue/562).
+ # https://github.com/cherrypy/cherrypy/issues/562).
self.getPage("/xhost/", headers=[('X-Host', 'www.example.test')])
self.assertHeader('Location', "%s://www.example.test/xhost"
% self.scheme)
diff --git a/cherrypy/test/test_request_obj.py b/cherrypy/test/test_request_obj.py
index a74ddddf..58736b54 100644
--- a/cherrypy/test/test_request_obj.py
+++ b/cherrypy/test/test_request_obj.py
@@ -184,7 +184,7 @@ class RequestObjectTests(helper.CPWebCase):
return cherrypy.request.headers[headername]
def doubledheaders(self):
- # From https://bitbucket.org/cherrypy/cherrypy/issue/165:
+ # From https://github.com/cherrypy/cherrypy/issues/165:
# "header field names should not be case sensitive sayes the
# rfc. if i set a headerfield in complete lowercase i end up
# with two header fields, one in lowercase, the other in
@@ -643,7 +643,7 @@ class RequestObjectTests(helper.CPWebCase):
"en;q=0.7")
# Test malformed header parsing. See
- # https://bitbucket.org/cherrypy/cherrypy/issue/763.
+ # https://github.com/cherrypy/cherrypy/issues/763.
self.getPage("/headerelements/get_elements?headername=Content-Type",
# Note the illegal trailing ";"
headers=[('Content-Type', 'text/html; charset=utf-8;')])
@@ -652,7 +652,7 @@ class RequestObjectTests(helper.CPWebCase):
def test_repeated_headers(self):
# Test that two request headers are collapsed into one.
- # See https://bitbucket.org/cherrypy/cherrypy/issue/542.
+ # See https://github.com/cherrypy/cherrypy/issues/542.
self.getPage("/headers/Accept-Charset",
headers=[("Accept-Charset", "iso-8859-5"),
("Accept-Charset", "unicode-1-1;q=0.8")])
@@ -738,7 +738,7 @@ class RequestObjectTests(helper.CPWebCase):
self.assertBody(b)
# Request a PUT method with a file body but no Content-Type.
- # See https://bitbucket.org/cherrypy/cherrypy/issue/790.
+ # See https://github.com/cherrypy/cherrypy/issues/790.
b = ntob("one thing on top of another")
self.persistent = True
try:
@@ -757,7 +757,7 @@ class RequestObjectTests(helper.CPWebCase):
self.persistent = False
# Request a PUT method with no body whatsoever (not an empty one).
- # See https://bitbucket.org/cherrypy/cherrypy/issue/650.
+ # See https://github.com/cherrypy/cherrypy/issues/650.
# Provide a C-T or webtest will provide one (and a C-L) for us.
h = [("Content-Type", "text/plain")]
self.getPage("/method/reachable", headers=h, method="PUT")
diff --git a/cherrypy/test/test_xmlrpc.py b/cherrypy/test/test_xmlrpc.py
index 8f091ff1..4beed0a3 100644
--- a/cherrypy/test/test_xmlrpc.py
+++ b/cherrypy/test/test_xmlrpc.py
@@ -163,7 +163,7 @@ class XmlRpcTest(helper.CPWebCase):
else:
self.fail("Expected xmlrpclib.Fault")
- # https://bitbucket.org/cherrypy/cherrypy/issue/533
+ # https://github.com/cherrypy/cherrypy/issues/533
# if a method is not found, an xmlrpclib.Fault should be raised
try:
proxy.non_method()
diff --git a/cherrypy/wsgiserver/ssl_builtin.py b/cherrypy/wsgiserver/ssl_builtin.py
index 2c74ad84..3faf7039 100644
--- a/cherrypy/wsgiserver/ssl_builtin.py
+++ b/cherrypy/wsgiserver/ssl_builtin.py
@@ -33,6 +33,14 @@ class BuiltinSSLAdapter(wsgiserver.SSLAdapter):
private_key = None
"""The filename of the server's private key file."""
+
+ certificate_chain = None
+ """The filename of the certificate chain file."""
+
+ """The ssl.SSLContext that will be used to wrap sockets where available
+ (on Python > 2.7.9 / 3.3)
+ """
+ context = None
def __init__(self, certificate, private_key, certificate_chain=None):
if ssl is None:
@@ -40,6 +48,12 @@ class BuiltinSSLAdapter(wsgiserver.SSLAdapter):
self.certificate = certificate
self.private_key = private_key
self.certificate_chain = certificate_chain
+ if hasattr(ssl, 'create_default_context'):
+ self.context = ssl.create_default_context(
+ purpose=ssl.Purpose.CLIENT_AUTH,
+ cafile=certificate_chain
+ )
+ self.context.load_cert_chain(certificate, private_key)
def bind(self, sock):
"""Wrap and return the given socket."""
@@ -48,10 +62,15 @@ class BuiltinSSLAdapter(wsgiserver.SSLAdapter):
def wrap(self, sock):
"""Wrap and return the given socket, plus WSGI environ entries."""
try:
- s = ssl.wrap_socket(sock, do_handshake_on_connect=True,
- server_side=True, certfile=self.certificate,
- keyfile=self.private_key,
- ssl_version=ssl.PROTOCOL_SSLv23)
+ if self.context is not None:
+ s = self.context.wrap_socket(sock,do_handshake_on_connect=True,
+ server_side=True)
+ else:
+ s = ssl.wrap_socket(sock, do_handshake_on_connect=True,
+ server_side=True, certfile=self.certificate,
+ keyfile=self.private_key,
+ ssl_version=ssl.PROTOCOL_SSLv23,
+ ca_certs=self.certificate_chain)
except ssl.SSLError:
e = sys.exc_info()[1]
if e.errno == ssl.SSL_ERROR_EOF:
diff --git a/cherrypy/wsgiserver/wsgiserver2.py b/cherrypy/wsgiserver/wsgiserver2.py
index 7bcf216f..a386d73d 100644
--- a/cherrypy/wsgiserver/wsgiserver2.py
+++ b/cherrypy/wsgiserver/wsgiserver2.py
@@ -103,6 +103,10 @@ except ImportError:
# Python 2.6
import io
+try:
+ import pkg_resources
+except ImportError:
+ pass
if 'win' in sys.platform and hasattr(socket, "AF_INET6"):
if not hasattr(socket, 'IPPROTO_IPV6'):
@@ -114,6 +118,12 @@ if 'win' in sys.platform and hasattr(socket, "AF_INET6"):
DEFAULT_BUFFER_SIZE = io.DEFAULT_BUFFER_SIZE
+try:
+ cp_version = pkg_resources.require('cherrypy')[0].version
+except Exception:
+ cp_version = 'unknown'
+
+
class FauxSocket(object):
"""Faux socket with the minimal interface required by pypy"""
@@ -192,6 +202,8 @@ socket_errors_to_ignore = plat_specific_errors(
)
socket_errors_to_ignore.append("timed out")
socket_errors_to_ignore.append("The read operation timed out")
+if sys.platform == 'darwin':
+ socket_errors_to_ignore.append(plat_specific_errors("EPROTOTYPE"))
socket_errors_nonblocking = plat_specific_errors(
'EAGAIN', 'EWOULDBLOCK', 'WSAEWOULDBLOCK')
@@ -298,7 +310,7 @@ class SizeCheckWrapper(object):
self.bytes_read += len(data)
self._check_length()
res.append(data)
- # See https://bitbucket.org/cherrypy/cherrypy/issue/421
+ # See https://github.com/cherrypy/cherrypy/issues/421
if len(data) < 256 or data[-1:] == LF:
return EMPTY.join(res)
@@ -798,7 +810,7 @@ class HTTPRequest(object):
if self.inheaders.get("Expect", "") == "100-continue":
# Don't use simple_response here, because it emits headers
# we don't want. See
- # https://bitbucket.org/cherrypy/cherrypy/issue/951
+ # https://github.com/cherrypy/cherrypy/issues/951
msg = self.server.protocol + " 100 Continue\r\n\r\n"
try:
self.conn.wfile.sendall(msg)
@@ -1361,7 +1373,7 @@ class HTTPConnection(object):
# Don't error if we're between requests; only error
# if 1) no request has been started at all, or 2) we're
# in the middle of a request.
- # See https://bitbucket.org/cherrypy/cherrypy/issue/853
+ # See https://github.com/cherrypy/cherrypy/issues/853
if (not request_seen) or (req and req.started_request):
# Don't bother writing the 408 if the response
# has already started being written.
@@ -1654,7 +1666,7 @@ class ThreadPool(object):
except (AssertionError,
# Ignore repeated Ctrl-C.
# See
- # https://bitbucket.org/cherrypy/cherrypy/issue/691.
+ # https://github.com/cherrypy/cherrypy/issues/691.
KeyboardInterrupt):
pass
@@ -1754,7 +1766,7 @@ class HTTPServer(object):
timeout = 10
"""The timeout in seconds for accepted connections (default 10)."""
- version = "CherryPy/5.1.0"
+ version = "CherryPy/" + cp_version
"""A version string for the HTTPServer."""
software = None
@@ -1979,7 +1991,7 @@ class HTTPServer(object):
# If listening on the IPV6 any address ('::' = IN6ADDR_ANY),
# activate dual-stack. See
- # https://bitbucket.org/cherrypy/cherrypy/issue/871.
+ # https://github.com/cherrypy/cherrypy/issues/871.
if (hasattr(socket, 'AF_INET6') and family == socket.AF_INET6
and self.bind_addr[0] in ('::', '::0', '::0.0.0.0')):
try:
@@ -2073,15 +2085,15 @@ class HTTPServer(object):
# the call, and I *think* I'm reading it right that Python
# will then go ahead and poll for and handle the signal
# elsewhere. See
- # https://bitbucket.org/cherrypy/cherrypy/issue/707.
+ # https://github.com/cherrypy/cherrypy/issues/707.
return
if x.args[0] in socket_errors_nonblocking:
# Just try again. See
- # https://bitbucket.org/cherrypy/cherrypy/issue/479.
+ # https://github.com/cherrypy/cherrypy/issues/479.
return
if x.args[0] in socket_errors_to_ignore:
# Our socket was closed.
- # See https://bitbucket.org/cherrypy/cherrypy/issue/686.
+ # See https://github.com/cherrypy/cherrypy/issues/686.
return
raise
@@ -2114,7 +2126,7 @@ class HTTPServer(object):
if x.args[0] not in socket_errors_to_ignore:
# Changed to use error code and not message
# See
- # https://bitbucket.org/cherrypy/cherrypy/issue/860.
+ # https://github.com/cherrypy/cherrypy/issues/860.
raise
else:
# Note that we're explicitly NOT using AI_PASSIVE,
diff --git a/cherrypy/wsgiserver/wsgiserver3.py b/cherrypy/wsgiserver/wsgiserver3.py
index b7ee36e3..7b89489e 100644
--- a/cherrypy/wsgiserver/wsgiserver3.py
+++ b/cherrypy/wsgiserver/wsgiserver3.py
@@ -101,6 +101,10 @@ except ImportError:
# Python 2.6
import io
+try:
+ import pkg_resources
+except ImportError:
+ pass
if 'win' in sys.platform and hasattr(socket, "AF_INET6"):
if not hasattr(socket, 'IPPROTO_IPV6'):
@@ -112,6 +116,12 @@ if 'win' in sys.platform and hasattr(socket, "AF_INET6"):
DEFAULT_BUFFER_SIZE = io.DEFAULT_BUFFER_SIZE
+try:
+ cp_version = pkg_resources.require('cherrypy')[0].version
+except Exception:
+ cp_version = 'unknown'
+
+
if sys.version_info >= (3, 0):
bytestr = bytes
unicodestr = str
@@ -178,6 +188,8 @@ socket_errors_to_ignore = plat_specific_errors(
)
socket_errors_to_ignore.append("timed out")
socket_errors_to_ignore.append("The read operation timed out")
+if sys.platform == 'darwin':
+ socket_errors_to_ignore.append(plat_specific_errors("EPROTOTYPE"))
socket_errors_nonblocking = plat_specific_errors(
'EAGAIN', 'EWOULDBLOCK', 'WSAEWOULDBLOCK')
@@ -284,7 +296,7 @@ class SizeCheckWrapper(object):
self.bytes_read += len(data)
self._check_length()
res.append(data)
- # See https://bitbucket.org/cherrypy/cherrypy/issue/421
+ # See https://github.com/cherrypy/cherrypy/issues/421
if len(data) < 256 or data[-1:] == LF:
return EMPTY.join(res)
@@ -787,7 +799,7 @@ class HTTPRequest(object):
if self.inheaders.get(b"Expect", b"") == b"100-continue":
# Don't use simple_response here, because it emits headers
# we don't want. See
- # https://bitbucket.org/cherrypy/cherrypy/issue/951
+ # https://github.com/cherrypy/cherrypy/issues/951
msg = self.server.protocol.encode(
'ascii') + b" 100 Continue\r\n\r\n"
try:
@@ -1090,7 +1102,7 @@ class HTTPConnection(object):
# Don't error if we're between requests; only error
# if 1) no request has been started at all, or 2) we're
# in the middle of a request.
- # See https://bitbucket.org/cherrypy/cherrypy/issue/853
+ # See https://github.com/cherrypy/cherrypy/issues/853
if (not request_seen) or (req and req.started_request):
# Don't bother writing the 408 if the response
# has already started being written.
@@ -1379,7 +1391,7 @@ class ThreadPool(object):
except (AssertionError,
# Ignore repeated Ctrl-C.
# See
- # https://bitbucket.org/cherrypy/cherrypy/issue/691.
+ # https://github.com/cherrypy/cherrypy/issues/691.
KeyboardInterrupt):
pass
@@ -1479,7 +1491,7 @@ class HTTPServer(object):
timeout = 10
"""The timeout in seconds for accepted connections (default 10)."""
- version = "CherryPy/5.1.0"
+ version = "CherryPy/" + cp_version
"""A version string for the HTTPServer."""
software = None
@@ -1704,7 +1716,7 @@ class HTTPServer(object):
# If listening on the IPV6 any address ('::' = IN6ADDR_ANY),
# activate dual-stack. See
- # https://bitbucket.org/cherrypy/cherrypy/issue/871.
+ # https://github.com/cherrypy/cherrypy/issues/871.
if (hasattr(socket, 'AF_INET6') and family == socket.AF_INET6
and self.bind_addr[0] in ('::', '::0', '::0.0.0.0')):
try:
@@ -1798,15 +1810,15 @@ class HTTPServer(object):
# the call, and I *think* I'm reading it right that Python
# will then go ahead and poll for and handle the signal
# elsewhere. See
- # https://bitbucket.org/cherrypy/cherrypy/issue/707.
+ # https://github.com/cherrypy/cherrypy/issues/707.
return
if x.args[0] in socket_errors_nonblocking:
# Just try again. See
- # https://bitbucket.org/cherrypy/cherrypy/issue/479.
+ # https://github.com/cherrypy/cherrypy/issues/479.
return
if x.args[0] in socket_errors_to_ignore:
# Our socket was closed.
- # See https://bitbucket.org/cherrypy/cherrypy/issue/686.
+ # See https://github.com/cherrypy/cherrypy/issues/686.
return
raise
@@ -1839,7 +1851,7 @@ class HTTPServer(object):
if x.args[0] not in socket_errors_to_ignore:
# Changed to use error code and not message
# See
- # https://bitbucket.org/cherrypy/cherrypy/issue/860.
+ # https://github.com/cherrypy/cherrypy/issues/860.
raise
else:
# Note that we're explicitly NOT using AI_PASSIVE,
diff --git a/docs/install.rst b/docs/install.rst
index 68dd9692..dec9c007 100644
--- a/docs/install.rst
+++ b/docs/install.rst
@@ -6,7 +6,7 @@ CherryPy is a pure Python library. This has various consequences:
- It can run anywhere Python runs
- It does not require a C compiler
- - It can run on various implementations of the Python language: `CPython <http://python.org/>`_,
+ - It can run on various implementations of the Python language: `CPython <http://python.org/>`_,
`IronPython <http://ironpython.net/>`_, `Jython <http://www.jython.org/>`_ and `PyPy <http://pypy.org/>`_
.. contents::
@@ -45,11 +45,11 @@ CherryPy can be easily installed via common Python package managers such as setu
$ pip install cherrypy
-You may also get the latest CherryPy version by grabbing the source code from BitBucket:
+You may also get the latest CherryPy version by grabbing the source code from Github:
.. code-block:: bash
- $ hg clone https://bitbucket.org/cherrypy/cherrypy
+ $ git clone https://github.com/cherrypy/cherrypy
$ cd cherrypy
$ python setup.py install
diff --git a/docs/tutorials.rst b/docs/tutorials.rst
index e50fa1dd..fc695dfb 100644
--- a/docs/tutorials.rst
+++ b/docs/tutorials.rst
@@ -915,10 +915,11 @@ First, let's see how our HTML code has changed:
<link href="/static/css/style.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/react.js"></script>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
</head>
<body>
<div id="generator"></div>
- <script type="text/javascript" src="static/js/gen.js"></script>
+ <script type="text/babel" src="static/js/gen.js"></script>
</body>
</html>
diff --git a/release.py b/release.py
deleted file mode 100644
index 14af0069..00000000
--- a/release.py
+++ /dev/null
@@ -1,62 +0,0 @@
-"""
-Use jaraco.packaging with this script to cut a release. After installing
-jaraco.packaging, invoke:
-
-python -m jaraco.packaging.release
-"""
-
-from __future__ import print_function
-
-import sys
-import os
-import shutil
-import importlib
-import textwrap
-
-files_with_versions = (
- 'setup.py',
- 'cherrypy/__init__.py',
- 'cherrypy/wsgiserver/wsgiserver2.py',
- 'cherrypy/wsgiserver/wsgiserver3.py',
-)
-
-
-def check_wheel():
- """
- Ensure 'wheel' is installed (required for bdist_wheel).
- """
- try:
- importlib.import_module('wheel')
- except ImportError:
- print("CherryPy requires 'wheel' be installed to produce wheels.",
- file=sys.stderr)
- raise SystemExit(5)
-
-
-def before_upload():
- check_wheel()
- remove_files()
-
-test_info = textwrap.dedent("""
- Run tests with `nosetests -s ./` on Windows, Linux, and Mac on at least
- Python 2.4, 2.5, 2.7, and 3.2.
- """).lstrip()
-
-dist_commands = 'sdist', 'bdist_wheel'
-
-
-def remove_files():
- if os.path.isfile('MANIFEST'):
- os.remove('MANIFEST')
- if os.path.isdir('dist'):
- shutil.rmtree('dist')
-
-
-def announce():
- print('Distributions have been uploaded.')
- print('Please ask in IRC for others to help you test this release.')
- print("Please confirm that the distro installs properly "
- "with `easy_install CherryPy=={version}`.".format(**globals()))
- print("Please change the Wiki: Home page (news), CherryPyDownload")
- print("Please announce the release on newsgroups, mailing lists, "
- "and IRC /topic.")
diff --git a/setup.cfg b/setup.cfg
index cd62b8dd..13afd86f 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,8 +1,24 @@
+[bumpversion]
+current_version = 5.2.0
+commit = True
+tag = True
+
+[aliases]
+clean_egg_info = egg_info -RDb ''
+release = clean_egg_info sdist bdist_wheel
+
[sdist]
-formats=gztar,zip
+formats = gztar,zip
[nosetests]
-where=cherrypy
-logging-filter=cherrypy
-verbosity=2
-nocapture=True
+where = cherrypy
+logging-filter = cherrypy
+verbosity = 2
+nocapture = True
+
+[egg_info]
+tag_build = .post
+tag_date = 1
+
+[bumpversion:file:setup.py]
+
diff --git a/setup.py b/setup.py
index 21cd5401..d4267e09 100644
--- a/setup.py
+++ b/setup.py
@@ -36,7 +36,7 @@ class cherrypy_build_py(build_py):
# arguments for the setup command
###############################################################################
name = "CherryPy"
-version = "5.1.0"
+version = "5.2.0"
desc = "Object-Oriented HTTP framework"
long_desc = "CherryPy is a pythonic, object-oriented HTTP framework"
classifiers = [