From fdb2260b47c619c4e5b5cc5ab1c91fd5f3265e61 Mon Sep 17 00:00:00 2001 From: Louis Thibault Date: Sat, 13 May 2017 21:07:36 +0200 Subject: [PATCH 1/6] Ensure HTTP path is of type bytes to avoid 404 errors in py3 --- src/twisted/web/resource.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/twisted/web/resource.py b/src/twisted/web/resource.py index 2853b219867..4de8c97282a 100644 --- a/src/twisted/web/resource.py +++ b/src/twisted/web/resource.py @@ -216,6 +216,10 @@ def putChild(self, path, child): @see: L{IResource.putChild} """ + if not isinstance(path, bytes): + emsg = "HTTP paths must be of type bytes (got {0})" + raise TypeError(emsg.format(type(path))) + self.children[path] = child child.server = self.server From 38c132a02530fce3ba7d858e0f98f30230ded3db Mon Sep 17 00:00:00 2001 From: Wim Lewis Date: Thu, 1 Nov 2018 15:16:52 -0700 Subject: [PATCH 2/6] Convert new exception into a DeprecationWarning; add a test. --- src/twisted/web/resource.py | 7 +++++-- src/twisted/web/test/test_resource.py | 26 ++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/twisted/web/resource.py b/src/twisted/web/resource.py index 4de8c97282a..48fbcd2ff56 100644 --- a/src/twisted/web/resource.py +++ b/src/twisted/web/resource.py @@ -217,8 +217,11 @@ def putChild(self, path, child): @see: L{IResource.putChild} """ if not isinstance(path, bytes): - emsg = "HTTP paths must be of type bytes (got {0})" - raise TypeError(emsg.format(type(path))) + warnings.warn( + 'Path segment must be bytes; ' + 'passing {0} will raise an exception in the future.' + .format(type(path)), + DeprecationWarning, 2) self.children[path] = child child.server = self.server diff --git a/src/twisted/web/test/test_resource.py b/src/twisted/web/test/test_resource.py index 952970552e0..245c70ed861 100644 --- a/src/twisted/web/test/test_resource.py +++ b/src/twisted/web/test/test_resource.py @@ -6,6 +6,7 @@ """ from twisted.trial.unittest import TestCase +from twisted.python.compat import _PY3 from twisted.web.error import UnsupportedMethod from twisted.web.resource import ( @@ -175,6 +176,31 @@ def test_dynamicChildren(self): self.assertIdentical(child.request, request) + def test_staticChildPathType(self): + """ + Test that passing the wrong type to putChild results in a warning, + and a failure in Python 3 + """ + resource = Resource() + child = Resource() + sibling = Resource() + resource.putChild(u"foo", child) + warnings = self.flushWarnings([self.test_staticChildPathType]) + self.assertEqual(len(warnings), 1) + self.assertIn("Path segment must be bytes", + warnings[0]['message']) + if _PY3: + # We expect an error here because u"foo" != b"foo" on Py3k + self.assertIsInstance(resource.getChildWithDefault(b"foo", DummyRequest([])), + ErrorPage) + + resource.putChild(None, sibling) + warnings = self.flushWarnings([self.test_staticChildPathType]) + self.assertEqual(len(warnings), 1) + self.assertIn("Path segment must be bytes", + warnings[0]['message']) + + def test_defaultHEAD(self): """ When not otherwise overridden, L{Resource.render} treats a I{HEAD} From 29451a5085a9597dd8f08e683086aeff8880d214 Mon Sep 17 00:00:00 2001 From: Wim Lewis Date: Mon, 25 Feb 2019 21:23:19 -0800 Subject: [PATCH 3/6] Update docstring; clarify wording of the deprecation warning a little. --- src/twisted/web/resource.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/twisted/web/resource.py b/src/twisted/web/resource.py index 48fbcd2ff56..dd5df06b304 100644 --- a/src/twisted/web/resource.py +++ b/src/twisted/web/resource.py @@ -214,14 +214,22 @@ def putChild(self, path, child): intended to have the root of a folder, e.g. /foo/, you want path to be ''. + @param path: A single path component. + @type path: C{bytes} + + @param child: The child resource to register. + @type child: L{IResource} + @see: L{IResource.putChild} """ if not isinstance(path, bytes): warnings.warn( 'Path segment must be bytes; ' - 'passing {0} will raise an exception in the future.' + 'passing {0} has never worked, and ' + 'will raise an exception in the future.' .format(type(path)), - DeprecationWarning, 2) + category=DeprecationWarning, + stacklevel=2) self.children[path] = child child.server = self.server From d3b2d6235d84fd5ea4597f4727902f27a43905e7 Mon Sep 17 00:00:00 2001 From: Wim Lewis Date: Mon, 25 Feb 2019 21:47:49 -0800 Subject: [PATCH 4/6] Rewrap code to appease the linter Add a newsfragment for ticket 9135 / PR 779 --- src/twisted/web/newsfragments/9135.feature | 1 + src/twisted/web/test/test_resource.py | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 src/twisted/web/newsfragments/9135.feature diff --git a/src/twisted/web/newsfragments/9135.feature b/src/twisted/web/newsfragments/9135.feature new file mode 100644 index 00000000000..12a71576177 --- /dev/null +++ b/src/twisted/web/newsfragments/9135.feature @@ -0,0 +1 @@ +t.w.resource.Resource.putChild() now emits a warning when called with a path segment of the wrong type (which can never be returned to a client). diff --git a/src/twisted/web/test/test_resource.py b/src/twisted/web/test/test_resource.py index 245c70ed861..162bf5533ed 100644 --- a/src/twisted/web/test/test_resource.py +++ b/src/twisted/web/test/test_resource.py @@ -191,8 +191,9 @@ def test_staticChildPathType(self): warnings[0]['message']) if _PY3: # We expect an error here because u"foo" != b"foo" on Py3k - self.assertIsInstance(resource.getChildWithDefault(b"foo", DummyRequest([])), - ErrorPage) + self.assertIsInstance( + resource.getChildWithDefault(b"foo", DummyRequest([])), + ErrorPage) resource.putChild(None, sibling) warnings = self.flushWarnings([self.test_staticChildPathType]) From bf5b3bbd419a504a02d1d13331c87fe20540c14d Mon Sep 17 00:00:00 2001 From: Wim Lewis Date: Mon, 4 Mar 2019 22:29:49 -0800 Subject: [PATCH 5/6] Change C{bytes} to L{bytes}, per Twisted's coding standard. --- src/twisted/web/resource.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/twisted/web/resource.py b/src/twisted/web/resource.py index dd5df06b304..147b110ef27 100644 --- a/src/twisted/web/resource.py +++ b/src/twisted/web/resource.py @@ -215,7 +215,7 @@ def putChild(self, path, child): path to be ''. @param path: A single path component. - @type path: C{bytes} + @type path: L{bytes} @param child: The child resource to register. @type child: L{IResource} From 332d056f3c7adaacd67165ea4abc08fc8aae9d55 Mon Sep 17 00:00:00 2001 From: Craig Rodrigues Date: Tue, 19 Mar 2019 23:04:12 -0700 Subject: [PATCH 6/6] Add newsfragment --- src/twisted/web/newsfragments/9135.feature | 1 - src/twisted/web/newsfragments/9135.removal | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 src/twisted/web/newsfragments/9135.feature create mode 100644 src/twisted/web/newsfragments/9135.removal diff --git a/src/twisted/web/newsfragments/9135.feature b/src/twisted/web/newsfragments/9135.feature deleted file mode 100644 index 12a71576177..00000000000 --- a/src/twisted/web/newsfragments/9135.feature +++ /dev/null @@ -1 +0,0 @@ -t.w.resource.Resource.putChild() now emits a warning when called with a path segment of the wrong type (which can never be returned to a client). diff --git a/src/twisted/web/newsfragments/9135.removal b/src/twisted/web/newsfragments/9135.removal new file mode 100644 index 00000000000..ed63c6bbef5 --- /dev/null +++ b/src/twisted/web/newsfragments/9135.removal @@ -0,0 +1 @@ +Passing a path argument to twisted.web.resource.Resource.putChild which is not of type bytes is now deprecated. In the future, passing a non-bytes argument to putChild will return an error.