tag 719520 patch thanks [ Cyril Brulebois ] > Eric Evans <eev...@debian.org> (2013-08-12): > > In python-coherence, coherence.upnp.core.utils.HeaderAwareHTTPClientFactory > > (coherence/upnp/core/utils.py) sub-classes twisted.web.client.HTTPDownloader > > (from package python-twisted-web), and in the process (uselessly )overrides > > the __init__ method and makes use of a "private" attribute. As a result, it > > broke when that attribute was dropped in a major release of Twisted. > > > > I think this bug is grave. Anything that uses utils.getPage is affected, > > which includes the internal control point; The default config and all of > > the examples fail predictably. > > > > It was reported in 664027[1] in March of 2012, but went unfixed and was > > released as part of wheezy, (the bug priority was "important"). > > > > The attached patch came from the corresponding upstream bug report[2], and > > has been well tested by myself and others (see replies to [1] and [2]). > > > > I just adopted coherence and have uploaded the fix to unstable, is there any > > chance a fix could make its way to stable-proposed-updates as well? > > it looks reasonable to me; please post a debdiff with that patch applied > on top of 0.6.6.2-6, versioned as 0.6.6.2-6+deb7u1 (I don't mind updated > Maintainer/Uploaders in the process), targeting 'wheezy' for a last review.
Great; debdiff attached Thanks! -- Eric Evans eev...@sym-link.com
diff -Nru coherence-0.6.6.2/debian/changelog coherence-0.6.6.2/debian/changelog --- coherence-0.6.6.2/debian/changelog 2011-07-31 21:52:04.000000000 -0500 +++ coherence-0.6.6.2/debian/changelog 2013-09-23 15:41:41.000000000 -0500 @@ -1,3 +1,9 @@ +coherence (0.6.6.2-6+deb7u1) unstable; urgency=low + + * Patch to fix tracebacks for missing attribute (Closes: #664027). + + -- Eric Evans <eev...@debian.org> Mon, 23 Sep 2013 15:41:28 -0500 + coherence (0.6.6.2-6) unstable; urgency=low * added pydist-overrided for dhp2 error concerning python-configobj. diff -Nru coherence-0.6.6.2/debian/control coherence-0.6.6.2/debian/control --- coherence-0.6.6.2/debian/control 2011-08-03 12:17:27.000000000 -0500 +++ coherence-0.6.6.2/debian/control 2013-09-23 15:44:54.000000000 -0500 @@ -1,9 +1,7 @@ Source: coherence Section: python Priority: extra -Maintainer: Arnaud Quette <aque...@debian.org> -Uploaders: Loic Minier <l...@dooz.org>, Charlie Smotherman <cj...@cableone.net>, - Debian Python Modules Team <python-modules-t...@lists.alioth.debian.org> +Maintainer: Eric Evans <eev...@debian.org> Build-Depends: debhelper (>= 7.0.50), python (>= 2.6.6-3), python-setuptools, diff -Nru coherence-0.6.6.2/debian/patches/04_missing_attribute_fix coherence-0.6.6.2/debian/patches/04_missing_attribute_fix --- coherence-0.6.6.2/debian/patches/04_missing_attribute_fix 1969-12-31 18:00:00.000000000 -0600 +++ coherence-0.6.6.2/debian/patches/04_missing_attribute_fix 2013-08-12 08:32:33.000000000 -0500 @@ -0,0 +1,170 @@ +Description: do not override private init + A sub-class of HTTPClientFactory overrides the __init__ method without + calling super's, and changes in a Twisted major release resulted in + breakage. + . + This patch by "marco" (found attached to issue #360 upstream), solves + the bug by eliminating the __init__ override. +Origin: http://coherence.beebits.net/attachment/ticket/360/getPage.patch +Bug: http://coherence.beebits.net/ticket/360 +Bug-Debian: http://bugs.debian.org/664027 +Forwarded: not-needed +Reviewed-By: Eric Evans <eev...@debian.org> +Last-Update: 2013-08-11 + +--- coherence-0.6.6.2.orig/coherence/upnp/core/utils.py ++++ coherence-0.6.6.2/coherence/upnp/core/utils.py +@@ -517,48 +517,14 @@ class HeaderAwareHTTPClientFactory(clien + protocol = myHTTPPageGetter + noisy = False + +- def __init__(self, url, method='GET', postdata=None, headers=None, +- agent="Twisted PageGetter", timeout=0, cookies=None, +- followRedirect=True, redirectLimit=20): +- self.followRedirect = followRedirect +- self.redirectLimit = redirectLimit +- self._redirectCount = 0 +- self.timeout = timeout +- self.agent = agent +- +- if cookies is None: +- cookies = {} +- self.cookies = cookies +- if headers is not None: +- self.headers = InsensitiveDict(headers) +- else: +- self.headers = InsensitiveDict() +- if postdata is not None: +- self.headers.setdefault('Content-Length', len(postdata)) +- # just in case a broken http/1.1 decides to keep connection alive +- self.headers.setdefault("connection", "close") +- self.postdata = postdata +- self.method = method +- +- self.setURL(url) +- +- self.waiting = 1 +- self.deferred = defer.Deferred() +- self.response_headers = None +- + def buildProtocol(self, addr): +- p = protocol.ClientFactory.buildProtocol(self, addr) ++ p = client.HTTPClientFactory.buildProtocol(self, addr) + p.method = self.method + p.followRedirect = self.followRedirect +- if self.timeout: +- timeoutCall = reactor.callLater(self.timeout, p.timeout) +- self.deferred.addBoth(self._cancelTimeout, timeoutCall) + return p + + def page(self, page): +- if self.waiting: +- self.waiting = 0 +- self.deferred.callback((page, self.response_headers)) ++ client.HTTPClientFactory.page(self, (page, self.response_headers)) + + + class HeaderAwareHTTPDownloader(client.HTTPDownloader): +@@ -577,24 +543,22 @@ class HeaderAwareHTTPDownloader(client.H + self.requestedPartial = 0 + + ++ + def getPage(url, contextFactory=None, *args, **kwargs): +- """Download a web page as a string. ++ """ ++ Download a web page as a string. + + Download a page. Return a deferred, which will callback with a + page (as a string) or errback with a description of the error. + + See HTTPClientFactory to see what extra args can be passed. + """ +- scheme, host, port, path = client._parse(url) +- factory = HeaderAwareHTTPClientFactory(url, *args, **kwargs) +- if scheme == 'https': +- from twisted.internet import ssl +- if contextFactory is None: +- contextFactory = ssl.ClientContextFactory() +- reactor.connectSSL(host, port, factory, contextFactory) +- else: +- reactor.connectTCP(host, port, factory) +- return factory.deferred ++ kwargs['agent'] = "Coherence PageGetter" ++ return client._makeGetterFactory( ++ url, ++ HeaderAwareHTTPClientFactory, ++ contextFactory=contextFactory, ++ *args, **kwargs).deferred + + + def downloadPage(url, file, contextFactory=None, *args, **kwargs): +--- coherence-0.6.6.2.orig/coherence/upnp/core/test/test_utils.py ++++ coherence-0.6.6.2/coherence/upnp/core/test/test_utils.py +@@ -9,9 +9,14 @@ + Test cases for L{upnp.core.utils} + """ + ++import os + from twisted.trial import unittest ++from twisted.python.filepath import FilePath ++from twisted.internet import reactor ++from twisted.web import static, server ++from twisted.protocols import policies + +-from coherence.upnp.core.utils import * ++from coherence.upnp.core import utils + + # This data is joined using CRLF pairs. + testChunkedData = ['200', +@@ -121,9 +126,49 @@ class TestUpnpUtils(unittest.TestCase): + based on a test and data provided by Lawrence + """ + testData = '\r\n'.join(testChunkedData) +- newData = de_chunk_payload(testData) ++ newData = utils.de_chunk_payload(testData) + # see whether we can parse the result + self.assertEqual(newData, '\r\n'.join( testChunkedDataResult)) + + ++class TestClient(unittest.TestCase): ++ ++ def _listen(self, site): ++ return reactor.listenTCP(0, site, interface="127.0.0.1") ++ ++ def setUp(self): ++ name = self.mktemp() ++ os.mkdir(name) ++ FilePath(name).child("file").setContent("0123456789") ++ r = static.File(name) ++ self.site = server.Site(r, timeout=None) ++ self.wrapper = policies.WrappingFactory(self.site) ++ self.port = self._listen(self.wrapper) ++ self.portno = self.port.getHost().port ++ ++ def tearDown(self): ++ return self.port.stopListening() ++ ++ def getURL(self, path): ++ return "http://127.0.0.1:%d/%s" % (self.portno, path) ++ ++ def assertResponse(self, original, content, headers): ++ self.assertIsInstance(original, tuple) ++ self.assertEqual(original[0], content) ++ originalHeaders = original[1] ++ for header in headers: ++ self.assertIn(header, originalHeaders) ++ self.assertEqual(originalHeaders[header], headers[header]) ++ ++ def test_getPage(self): ++ content = '0123456789' ++ headers = {'accept-ranges': ['bytes'], ++ 'content-length': ['10'], ++ 'content-type': ['text/html']} ++ d = utils.getPage(self.getURL("file")) ++ d.addCallback(self.assertResponse, content, headers) ++ return d ++ ++ ++ + # $Id:$ diff -Nru coherence-0.6.6.2/debian/patches/series coherence-0.6.6.2/debian/patches/series --- coherence-0.6.6.2/debian/patches/series 2011-07-31 21:52:04.000000000 -0500 +++ coherence-0.6.6.2/debian/patches/series 2013-09-23 15:39:09.000000000 -0500 @@ -1,4 +1,4 @@ 03_last_updated_service_field_workaround 02_string_exception_fix 01_systray_fix - +04_missing_attribute_fix