summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Rivera <rivera@joel.mx>2016-03-02 00:32:16 -0600
committerJoel Rivera <rivera@joel.mx>2016-03-02 00:32:16 -0600
commita466ab7f4dacd8601c1441be63abf88db1a33781 (patch)
treecfc2821c9f8cc6c83f1de52bf8b4e8171ae33ae8
parent304e9e1f883affd097c3b6a724391d2fe3a00ed1 (diff)
parent359f6fc83fa6c763baa345d8247322132da558fa (diff)
downloadcherrypy-a466ab7f4dacd8601c1441be63abf88db1a33781.tar.gz
Fix bug #1382 for Python 3.5 keyword args.
-rw-r--r--CHANGES.txt8
-rw-r--r--cherrypy/__init__.py2
-rw-r--r--cherrypy/lib/cptools.py7
-rw-r--r--cherrypy/lib/reprconf.py6
-rw-r--r--cherrypy/test/test_conn.py40
-rw-r--r--cherrypy/test/test_core.py39
-rw-r--r--cherrypy/test/test_wsgi_unix_socket.py3
-rw-r--r--cherrypy/test/webtest.py47
-rw-r--r--cherrypy/wsgiserver/wsgiserver2.py2
-rw-r--r--cherrypy/wsgiserver/wsgiserver3.py2
-rw-r--r--docs/tutorials.rst4
-rw-r--r--setup.py2
12 files changed, 73 insertions, 89 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 2bc95852..ec5d0a36 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,10 @@
-----
+5.0.1
+-----
+
+* Bugfix for NameError following #94.
+
+-----
5.0.0
-----
@@ -7,6 +13,8 @@
of SSL adapter on Python 2 WSGI servers.
* Default SSL Adapter on Python 2 is the builtin SSL adapter,
matching Python 3 behavior.
+* Pull request #94: In proxy tool, defer to Host header for
+ resolving the base if no base is supplied.
-----
4.0.0
diff --git a/cherrypy/__init__.py b/cherrypy/__init__.py
index ead51acf..7db50c4b 100644
--- a/cherrypy/__init__.py
+++ b/cherrypy/__init__.py
@@ -56,7 +56,7 @@ 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__ = "4.0.1"
+__version__ = "5.0.2"
from cherrypy._cpcompat import urljoin as _urljoin, urlencode as _urlencode
from cherrypy._cpcompat import basestring, unicodestr
diff --git a/cherrypy/lib/cptools.py b/cherrypy/lib/cptools.py
index 38f56195..9be571ba 100644
--- a/cherrypy/lib/cptools.py
+++ b/cherrypy/lib/cptools.py
@@ -193,11 +193,10 @@ def proxy(base=None, local='X-Forwarded-Host', remote='X-Forwarded-For',
if lbase is not None:
base = lbase.split(',')[0]
if not base:
+ base = request.headers.get('Host', '127.0.0.1')
port = request.local.port
- if port == 80:
- base = '127.0.0.1'
- else:
- base = '127.0.0.1:%s' % port
+ if port != 80:
+ base += ':%s' % port
if base.find("://") == -1:
# add http:// or https:// if needed
diff --git a/cherrypy/lib/reprconf.py b/cherrypy/lib/reprconf.py
index e394a561..be1aacb4 100644
--- a/cherrypy/lib/reprconf.py
+++ b/cherrypy/lib/reprconf.py
@@ -378,8 +378,10 @@ class _Builder3:
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"""
+ """
+ Workaround for python 3.5 _ast.Call signature, docs found here
+ https://greentreesnakes.readthedocs.org/en/latest/nodes.html
+ """
callee = self.build(o.func)
args = ()
diff --git a/cherrypy/test/test_conn.py b/cherrypy/test/test_conn.py
index ab830f3c..703e6dfd 100644
--- a/cherrypy/test/test_conn.py
+++ b/cherrypy/test/test_conn.py
@@ -3,16 +3,16 @@
import socket
import sys
import time
-timeout = 1
+import errno
import cherrypy
from cherrypy._cpcompat import HTTPConnection, HTTPSConnection, NotConnected
from cherrypy._cpcompat import BadStatusLine, ntob, tonative, urlopen, unicodestr
from cherrypy.test import webtest
-from cherrypy import _cperror
+timeout = 1
pov = 'pPeErRsSiIsStTeEnNcCeE oOfF vViIsSiIoOnN'
@@ -751,24 +751,31 @@ def setup_upload_server():
'server.accepted_queue_timeout': 0.1,
})
-import errno
-socket_reset_errors = []
-# Not all of these names will be defined for every platform.
-for _ in ("ECONNRESET", "WSAECONNRESET"):
- if _ in dir(errno):
- socket_reset_errors.append(getattr(errno, _))
+reset_names = 'ECONNRESET', 'WSAECONNRESET'
+socket_reset_errors = [
+ getattr(errno, name)
+ for name in reset_names
+ if hasattr(errno, name)
+]
+"reset error numbers available on this platform"
+
+socket_reset_errors += [
+ # Python 3.5 raises an http.client.RemoteDisconnected
+ # with this message
+ "Remote end closed connection without response",
+]
+
class LimitedRequestQueueTests(helper.CPWebCase):
- setup_server = staticmethod(setup_upload_server)
+ setup_server = staticmethod(setup_upload_server)
def test_queue_full(self):
conns = []
overflow_conn = None
-
+
try:
# Make 15 initial requests and leave them open, which should use
# all of wsgiserver's WorkerThreads and fill its Queue.
- import time
for i in range(15):
conn = self.HTTP_CONN(self.HOST, self.PORT)
conn.putrequest("POST", "/upload", skip_host=True)
@@ -777,7 +784,7 @@ class LimitedRequestQueueTests(helper.CPWebCase):
conn.putheader("Content-Length", "4")
conn.endheaders()
conns.append(conn)
-
+
# Now try a 16th conn, which should be closed by the server immediately.
overflow_conn = self.HTTP_CONN(self.HOST, self.PORT)
# Manually connect since httplib won't let us set a timeout
@@ -788,7 +795,7 @@ class LimitedRequestQueueTests(helper.CPWebCase):
overflow_conn.sock.settimeout(5)
overflow_conn.sock.connect(sa)
break
-
+
overflow_conn.putrequest("GET", "/", skip_host=True)
overflow_conn.putheader("Host", self.HOST)
overflow_conn.endheaders()
@@ -799,8 +806,11 @@ class LimitedRequestQueueTests(helper.CPWebCase):
if exc.args[0] in socket_reset_errors:
pass # Expected.
else:
- raise AssertionError("Overflow conn did not get RST. "
- "Got %s instead" % repr(exc.args))
+ tmpl = (
+ "Overflow conn did not get RST. "
+ "Got {exc.args!r} instead"
+ )
+ raise AssertionError(tmpl.format(**locals()))
except BadStatusLine:
# This is a special case in OS X. Linux and Windows will
# RST correctly.
diff --git a/cherrypy/test/test_core.py b/cherrypy/test/test_core.py
index ae4728de..4ebc170a 100644
--- a/cherrypy/test/test_core.py
+++ b/cherrypy/test/test_core.py
@@ -9,6 +9,7 @@ import cherrypy
from cherrypy._cpcompat import IncompleteRead, itervalues, ntob
from cherrypy import _cptools, tools
from cherrypy.lib import httputil, static
+from cherrypy.test._test_decorators import ExposeExamples
favicon_path = os.path.join(os.getcwd(), localDir, "../favicon.ico")
@@ -41,10 +42,7 @@ class CoreRequestHandlingTest(helper.CPWebCase):
baseurl.exposed = True
root = Root()
-
- if sys.version_info >= (2, 5):
- from cherrypy.test._test_decorators import ExposeExamples
- root.expose_dec = ExposeExamples()
+ root.expose_dec = ExposeExamples()
class TestType(type):
@@ -250,11 +248,7 @@ class CoreRequestHandlingTest(helper.CPWebCase):
cherrypy.response.cookie[str(name)] = cookie.value
def multiple(self, names):
- for name in names:
- cookie = cherrypy.request.cookie[name]
- # Python2's SimpleCookie.__setitem__ won't take unicode
- # keys.
- cherrypy.response.cookie[str(name)] = cookie.value
+ list(map(self.single, names))
def append_headers(header_list, debug=False):
if debug:
@@ -554,21 +548,31 @@ class CoreRequestHandlingTest(helper.CPWebCase):
self.getPage("/favicon.ico")
self.assertBody(data)
+ def skip_if_bad_cookies(self):
+ """
+ cookies module fails to reject invalid cookies
+ https://bitbucket.org/cherrypy/cherrypy/issues/1405
+ """
+ cookies = sys.modules.get('http.cookies')
+ _is_legal_key = getattr(cookies, '_is_legal_key', lambda x: False)
+ if not _is_legal_key(','):
+ return
+ issue = 'http://bugs.python.org/issue26302'
+ tmpl = "Broken cookies module ({issue})"
+ self.skip(tmpl.format(**locals()))
+
def testCookies(self):
- if sys.version_info >= (2, 5):
- header_value = lambda x: x
- else:
- header_value = lambda x: x + ';'
+ self.skip_if_bad_cookies()
self.getPage("/cookies/single?name=First",
[('Cookie', 'First=Dinsdale;')])
- self.assertHeader('Set-Cookie', header_value('First=Dinsdale'))
+ self.assertHeader('Set-Cookie', 'First=Dinsdale')
self.getPage("/cookies/multiple?names=First&names=Last",
[('Cookie', 'First=Dinsdale; Last=Piranha;'),
])
- self.assertHeader('Set-Cookie', header_value('First=Dinsdale'))
- self.assertHeader('Set-Cookie', header_value('Last=Piranha'))
+ self.assertHeader('Set-Cookie', 'First=Dinsdale')
+ self.assertHeader('Set-Cookie', 'Last=Piranha')
self.getPage("/cookies/single?name=Something-With%2CComma",
[('Cookie', 'Something-With,Comma=some-value')])
@@ -660,9 +664,6 @@ class CoreRequestHandlingTest(helper.CPWebCase):
self.assertBody('/page1')
def test_expose_decorator(self):
- if not sys.version_info >= (2, 5):
- return self.skip("skipped (Python 2.5+ only) ")
-
# Test @expose
self.getPage("/expose_dec/no_call")
self.assertStatus(200)
diff --git a/cherrypy/test/test_wsgi_unix_socket.py b/cherrypy/test/test_wsgi_unix_socket.py
index 0e98a4c5..0a552bc5 100644
--- a/cherrypy/test/test_wsgi_unix_socket.py
+++ b/cherrypy/test/test_wsgi_unix_socket.py
@@ -2,6 +2,7 @@ import os
import sys
import socket
import atexit
+import tempfile
import cherrypy
from cherrypy.test import helper
@@ -9,7 +10,7 @@ from cherrypy._cpcompat import HTTPConnection
USOCKET_PATH = os.path.join(
- os.path.dirname(os.path.realpath(__file__)),
+ tempfile.gettempdir(),
'cp_test.sock'
)
diff --git a/cherrypy/test/webtest.py b/cherrypy/test/webtest.py
index 1fa3f969..fc3cab49 100644
--- a/cherrypy/test/webtest.py
+++ b/cherrypy/test/webtest.py
@@ -510,48 +510,11 @@ def openURL(url, headers=None, method="GET", body=None,
conn._http_vsn_str = protocol
conn._http_vsn = int("".join([x for x in protocol if x.isdigit()]))
- # skip_accept_encoding argument added in python version 2.4
- if sys.version_info < (2, 4):
- def putheader(self, header, value):
- if header == 'Accept-Encoding' and value == 'identity':
- return
- self.__class__.putheader(self, header, value)
- import new
- conn.putheader = new.instancemethod(
- putheader, conn, conn.__class__)
- conn.putrequest(method.upper(), url, skip_host=True)
- elif not py3k:
- conn.putrequest(method.upper(), url, skip_host=True,
- skip_accept_encoding=True)
- else:
- import http.client
- # Replace the stdlib method, which only accepts ASCII url's
-
- def putrequest(self, method, url):
- if (
- self._HTTPConnection__response and
- self._HTTPConnection__response.isclosed()
- ):
- self._HTTPConnection__response = None
-
- if self._HTTPConnection__state == http.client._CS_IDLE:
- self._HTTPConnection__state = (
- http.client._CS_REQ_STARTED)
- else:
- raise http.client.CannotSendRequest()
-
- self._method = method
- if not url:
- url = ntob('/')
- request = ntob(' ').join(
- (method.encode("ASCII"),
- url,
- self._http_vsn_str.encode("ASCII")))
- self._output(request)
- import types
- conn.putrequest = types.MethodType(putrequest, conn)
-
- conn.putrequest(method.upper(), url)
+ if py3k and isinstance(url, bytes):
+ url = url.decode()
+
+ conn.putrequest(method.upper(), url, skip_host=True,
+ skip_accept_encoding=True)
for key, value in headers:
conn.putheader(key, value.encode("Latin-1"))
diff --git a/cherrypy/wsgiserver/wsgiserver2.py b/cherrypy/wsgiserver/wsgiserver2.py
index a0c0173f..828b243f 100644
--- a/cherrypy/wsgiserver/wsgiserver2.py
+++ b/cherrypy/wsgiserver/wsgiserver2.py
@@ -1756,7 +1756,7 @@ class HTTPServer(object):
timeout = 10
"""The timeout in seconds for accepted connections (default 10)."""
- version = "CherryPy/4.0.1"
+ version = "CherryPy/5.0.2"
"""A version string for the HTTPServer."""
software = None
diff --git a/cherrypy/wsgiserver/wsgiserver3.py b/cherrypy/wsgiserver/wsgiserver3.py
index d410eda4..b3942c90 100644
--- a/cherrypy/wsgiserver/wsgiserver3.py
+++ b/cherrypy/wsgiserver/wsgiserver3.py
@@ -1478,7 +1478,7 @@ class HTTPServer(object):
timeout = 10
"""The timeout in seconds for accepted connections (default 10)."""
- version = "CherryPy/4.0.1"
+ version = "CherryPy/5.0.2"
"""A version string for the HTTPServer."""
software = None
diff --git a/docs/tutorials.rst b/docs/tutorials.rst
index 36994a32..e50fa1dd 100644
--- a/docs/tutorials.rst
+++ b/docs/tutorials.rst
@@ -5,7 +5,7 @@ Tutorials
This tutorial will walk you through basic but complete CherryPy applications
-that will show you common concepts as well as slightly more adavanced ones.
+that will show you common concepts as well as slightly more advanced ones.
.. contents::
:depth: 4
@@ -183,7 +183,7 @@ Tutorial 4: Submit this form
############################
CherryPy is a web framework upon which you build web applications.
-The most traditionnal shape taken by applications is through
+The most traditional shape taken by applications is through
an HTML user-interface speaking to your CherryPy server.
Let's see how to handle HTML forms via the following
diff --git a/setup.py b/setup.py
index d6259541..e7525eb8 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 = "4.0.1"
+version = "5.0.2"
desc = "Object-Oriented HTTP framework"
long_desc = "CherryPy is a pythonic, object-oriented HTTP framework"
classifiers = [