diff -Nru python-debianbts-1.11/debian/changelog python-debianbts-1.11ubuntu0.1/debian/changelog --- python-debianbts-1.11/debian/changelog 2012-04-16 17:45:50.000000000 +0800 +++ python-debianbts-1.11ubuntu0.1/debian/changelog 2015-11-02 13:05:34.000000000 +0800 @@ -1,3 +1,9 @@ +python-debianbts (1.11ubuntu0.1) trusty-proposed; urgency=medium + + * Fix the crashes on BTS query. (LP: #1512200) + + -- Shih-Yuan Lee (FourDollars) Mon, 02 Nov 2015 11:58:03 +0800 + python-debianbts (1.11) unstable; urgency=low * Uploaded lots of changes contributed by Jari Aalto. Thank you very much diff -Nru python-debianbts-1.11/debian/control python-debianbts-1.11ubuntu0.1/debian/control --- python-debianbts-1.11/debian/control 2012-04-16 17:41:54.000000000 +0800 +++ python-debianbts-1.11ubuntu0.1/debian/control 2015-11-02 13:06:05.000000000 +0800 @@ -1,8 +1,9 @@ Source: python-debianbts Section: python Priority: optional -Maintainer: Bastian Venthur -Build-Depends: debhelper (>= 9), python-support (>= 0.6), python +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Bastian Venthur +Build-Depends: debhelper (>= 9), python-support (>= 0.6), python, python-mock Standards-Version: 3.9.3.1 Vcs-Git: git://github.com/venthur/python-debianbts.git Vcs-Browser: http://github.com/venthur/python-debianbts diff -Nru python-debianbts-1.11/src/debianbts.py python-debianbts-1.11ubuntu0.1/src/debianbts.py --- python-debianbts-1.11/src/debianbts.py 2011-02-24 19:05:36.000000000 +0800 +++ python-debianbts-1.11ubuntu0.1/src/debianbts.py 2015-11-02 13:05:34.000000000 +0800 @@ -27,17 +27,24 @@ from datetime import datetime +import os import SOAPpy +# Support running from Debian infrastructure +ca_path = '/etc/ssl/ca-debian' +if os.path.isdir(ca_path): + os.environ['SSL_CERT_DIR'] = ca_path # Setup the soap server # TODO: recognize HTTP proxy environment variable # Default values -URL = 'http://bugs.debian.org/cgi-bin/soap.cgi' +URL = 'https://bugs.debian.org/cgi-bin/soap.cgi' NS = 'Debbugs/SOAP/V1' server = SOAPpy.SOAPProxy(URL, NS) -BTS_URL = 'http://bugs.debian.org/' +BTS_URL = 'https://bugs.debian.org/' +# Max number of bugs to send in a single get_status request +BATCH_SIZE = 500 class Bugreport(object): """Represents a bugreport from Debian's Bug Tracking System. @@ -156,20 +163,28 @@ return val -def get_status(*nr): +def get_status(*nrs): """Returns a list of Bugreport objects.""" - reply = server.get_status(*nr) # If we called get_status with one single bug, we get a single bug, # if we called it with a list of bugs, we get a list, - # No available bugreports returns an enmpy list + # No available bugreports returns an empty list bugs = [] - if not reply: - pass - elif type(reply[0]) == type([]): - for elem in reply[0]: - bugs.append(_parse_status(elem)) - else: - bugs.append(_parse_status(reply[0])) + def parse(n): + if not n: + return [] + elif type(reply[0]) == type([]): + return [_parse_status(elem) for elem in reply[0]] + else: + return [_parse_status(reply[0])] + # Process the input in batches to avoid hitting resource limits on the BTS + for nr in nrs: + if isinstance(nr, list): + for i in range(0, len(nr), BATCH_SIZE): + reply = server.get_status(nr[i:i+BATCH_SIZE]) + bugs.extend(parse(reply)) + else: + reply = server.get_status(nr) + bugs.extend(parse(reply)) return bugs diff -Nru python-debianbts-1.11/test/test_debianbts.py python-debianbts-1.11ubuntu0.1/test/test_debianbts.py --- python-debianbts-1.11/test/test_debianbts.py 2011-02-24 19:05:36.000000000 +0800 +++ python-debianbts-1.11ubuntu0.1/test/test_debianbts.py 2015-11-02 13:05:34.000000000 +0800 @@ -18,7 +18,12 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +import math import unittest +try: + import unittest.mock as mock +except ImportError: + import mock import debianbts as bts @@ -84,6 +89,15 @@ self.assertTrue(i.has_key("msg_num")) self.assertEqual(type(i["msg_num"]), type(int())) + def testStatusBatchesLargeBugCounts(self): + """get_status should perform requests in batches to reduce server load.""" + with mock.patch.object(bts.server, 'get_status') as MockStatus: + MockStatus.return_value = None + nr = bts.BATCH_SIZE + 10.0 + calls = int(math.ceil(nr / bts.BATCH_SIZE)) + bts.get_status([722226] * int(nr)) + self.assertEqual(MockStatus.call_count, calls) + def testComparison(self): self.b1.archived = True self.b2.done = True