diff -Nru twisted-news-10.0.0/debian/changelog twisted-news-12.0.0/debian/changelog --- twisted-news-10.0.0/debian/changelog 2012-02-19 01:48:36.000000000 +0000 +++ twisted-news-12.0.0/debian/changelog 2012-02-19 01:34:28.000000000 +0000 @@ -1,3 +1,10 @@ +twisted-news (12.0.0-1~ppa1~lucid1) lucid; urgency=low + + * New upstream version. + * Rebuild package for use in PPA. + + -- Jessica McKellar Sat, 18 Feb 2012 20:33:51 -0500 + twisted-news (10.0.0-1) unstable; urgency=low * New upstream release diff -Nru twisted-news-10.0.0/debian/compat twisted-news-12.0.0/debian/compat --- twisted-news-10.0.0/debian/compat 2012-02-19 01:48:36.000000000 +0000 +++ twisted-news-12.0.0/debian/compat 2012-02-19 01:32:17.000000000 +0000 @@ -1 +1 @@ -5 +7 diff -Nru twisted-news-10.0.0/debian/control twisted-news-12.0.0/debian/control --- twisted-news-10.0.0/debian/control 2012-02-19 01:48:36.000000000 +0000 +++ twisted-news-12.0.0/debian/control 2012-02-19 01:32:54.000000000 +0000 @@ -3,17 +3,16 @@ Priority: optional Maintainer: Matthias Klose Uploaders: Free Ekanayaka -Build-Depends: debhelper (>= 5.0.37.1), python-central (>= 0.6.7), python-all, python-twisted-core (>= 10.0), patch +Build-Depends: debhelper (>=7.0.50~), python-central (>= 0.6.7), python-all, python-twisted-core (>= 12.0), patch XS-Python-Version: all -Standards-Version: 3.8.4 +Standards-Version: 3.9.2 Package: python-twisted-news Architecture: all -Depends: ${python:Depends}, python-twisted-core (>= 10.0), ${misc:Depends} +Depends: ${python:Depends}, python-twisted-core (>= 12.0), ${misc:Depends} Conflicts: python2.3-twisted-news, python2.4-twisted-news Replaces: python2.3-twisted-news, python2.4-twisted-news -XB-Python-Version: ${python:Versions} -Description: An NNTP protocol implementation with client and server +Description: NNTP protocol implementation with client and server Twisted News provides a very basic NNTP server, as well as an NNTP client protocol implementation. Two messages storage systems are supported: the DB-API 2.0 backend stores and indexes messages in any diff -Nru twisted-news-10.0.0/debian/rules twisted-news-12.0.0/debian/rules --- twisted-news-10.0.0/debian/rules 2012-02-19 01:48:36.000000000 +0000 +++ twisted-news-12.0.0/debian/rules 2012-02-19 01:33:20.000000000 +0000 @@ -7,6 +7,8 @@ VER := $(shell /usr/bin/python -c 'import sys; print sys.version[:3]') build: build-stamp +build-arch: build-stamp +build-indep: build-stamp build-stamp: $(PYVERS:%=build-python%) touch $@ build-python%: @@ -25,7 +27,7 @@ install-prereq: build-stamp dh_testdir dh_testroot - dh_clean -k + dh_prep install-python%: install-prereq : # python-twisted-news @@ -77,7 +79,6 @@ dh_testroot dh_installchangelogs -i dh_installdocs -i -A README -# dh_installdocs -ppython-twisted-news doc/examples doc/howto dh_installmenu -i dh_compress -i -X.py dh_fixperms -i diff -Nru twisted-news-10.0.0/debian/source/format twisted-news-12.0.0/debian/source/format --- twisted-news-10.0.0/debian/source/format 1970-01-01 00:00:00.000000000 +0000 +++ twisted-news-12.0.0/debian/source/format 2012-02-19 01:48:36.000000000 +0000 @@ -0,0 +1 @@ +3.0 (quilt) diff -Nru twisted-news-10.0.0/LICENSE twisted-news-12.0.0/LICENSE --- twisted-news-10.0.0/LICENSE 2010-03-09 13:26:32.000000000 +0000 +++ twisted-news-12.0.0/LICENSE 2012-01-23 13:19:44.000000000 +0000 @@ -1,4 +1,4 @@ -Copyright (c) 2001-2010 +Copyright (c) 2001-2012 Allen Short Andy Gayton Andrew Bennetts @@ -12,7 +12,7 @@ Donovan Preston Eric Mangold Eyal Lotem -Itamar Shtull-Trauring +Itamar Turner-Trauring James Knight Jason A. Mobarak Jean-Paul Calderone diff -Nru twisted-news-10.0.0/NEWS twisted-news-12.0.0/NEWS --- twisted-news-10.0.0/NEWS 2010-03-09 13:26:32.000000000 +0000 +++ twisted-news-12.0.0/NEWS 2012-02-10 14:56:39.000000000 +0000 @@ -1,6 +1,43 @@ Ticket numbers in this file can be looked up by visiting http://twistedmatrix.com/trac/ticket/ +Twisted News 12.0.0 (2012-02-10) +================================ + +No significant changes have been made for this release. + + +Twisted News 11.1.0 (2011-11-15) +================================ + +No significant changes have been made for this release. + + +Twisted News 11.0.0 (2011-04-01) +================================ + +No significant changes have been made for this release. + +Other +----- + - #4580 + + +Twisted News 10.2.0 (2010-11-29) +================================ + +Bugfixes +-------- + - twisted.news.database.PickleStorage now invokes the email APIs + correctly, allowing it to actually send moderation emails. (#4528) + + +Twisted News 10.1.0 (2010-06-27) +================================ + +No significant changes have been made for this release. + + Twisted News 10.0.0 (2010-03-01) ================================ diff -Nru twisted-news-10.0.0/README twisted-news-12.0.0/README --- twisted-news-10.0.0/README 2010-03-09 13:26:32.000000000 +0000 +++ twisted-news-12.0.0/README 2012-02-10 14:56:39.000000000 +0000 @@ -1,4 +1,4 @@ -Twisted News 10.0.0 +Twisted News 12.0.0 News depends on Twisted, and, if you want to use the moderation features, Twisted Mail. diff -Nru twisted-news-10.0.0/setup.py twisted-news-12.0.0/setup.py --- twisted-news-10.0.0/setup.py 2010-03-09 13:26:32.000000000 +0000 +++ twisted-news-12.0.0/setup.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2008 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. try: diff -Nru twisted-news-10.0.0/twisted/news/database.py twisted-news-12.0.0/twisted/news/database.py --- twisted-news-10.0.0/twisted/news/database.py 2010-03-09 13:26:32.000000000 +0000 +++ twisted-news-12.0.0/twisted/news/database.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,22 +1,16 @@ -# -*- test-case-name: twisted.news.test.test_news -*- -# Copyright (c) 2001-2008 Twisted Matrix Laboratories. +# -*- test-case-name: twisted.news.test -*- +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. - """ -News server backend implementations - -Maintainer: Jp Calderone - -Future Plans: A PyFramer-based backend and a new backend interface that is -less NNTP specific +News server backend implementations. """ - import getpass, pickle, time, socket import os import StringIO - +from email.Message import Message +from email.Generator import Generator from zope.interface import implements, Interface from twisted.news.nntp import NNTPError @@ -230,8 +224,64 @@ raise NotImplementedError() -class PickleStorage: - """A trivial NewsStorage implementation using pickles + +class _ModerationMixin: + """ + Storage implementations can inherit from this class to get the easy-to-use + C{notifyModerators} method which will take care of sending messages which + require moderation to a list of moderators. + """ + sendmail = staticmethod(smtp.sendmail) + + def notifyModerators(self, moderators, article): + """ + Send an article to a list of group moderators to be moderated. + + @param moderators: A C{list} of C{str} giving RFC 2821 addresses of + group moderators to notify. + + @param article: The article requiring moderation. + @type article: L{Article} + + @return: A L{Deferred} which fires with the result of sending the email. + """ + # Moderated postings go through as long as they have an Approved + # header, regardless of what the value is + group = article.getHeader('Newsgroups') + subject = article.getHeader('Subject') + + if self._sender is None: + # This case should really go away. This isn't a good default. + sender = 'twisted-news@' + socket.gethostname() + else: + sender = self._sender + + msg = Message() + msg['Message-ID'] = smtp.messageid() + msg['From'] = sender + msg['To'] = ', '.join(moderators) + msg['Subject'] = 'Moderate new %s message: %s' % (group, subject) + msg['Content-Type'] = 'message/rfc822' + + payload = Message() + for header, value in article.headers.values(): + payload.add_header(header, value) + payload.set_payload(article.body) + + msg.attach(payload) + + out = StringIO.StringIO() + gen = Generator(out, False) + gen.flatten(msg) + msg = out.getvalue() + + return self.sendmail(self._mailhost, sender, moderators, msg) + + + +class PickleStorage(_ModerationMixin): + """ + A trivial NewsStorage implementation using pickles Contains numerous flaws and is generally unsuitable for any real applications. Consider yourself warned! @@ -241,9 +291,20 @@ sharedDBs = {} - def __init__(self, filename, groups = None, moderators = ()): + def __init__(self, filename, groups=None, moderators=(), + mailhost=None, sender=None): + """ + @param mailhost: A C{str} giving the mail exchange host which will + accept moderation emails from this server. Must accept emails + destined for any address specified as a moderator. + + @param sender: A C{str} giving the address which will be used as the + sender of any moderation email generated by this server. + """ self.datafile = filename self.load(filename, groups, moderators) + self._mailhost = mailhost + self._sender = sender def getModerators(self, groups): @@ -251,22 +312,10 @@ # but the whole messages gets forwarded to the moderator address moderators = [] for group in groups: - moderators.append(self.db['moderators'].get(group, None)) + moderators.extend(self.db['moderators'].get(group, None)) return filter(None, moderators) - def notifyModerators(self, moderators, article): - # Moderated postings go through as long as they have an Approved - # header, regardless of what the value is - article.putHeader('To', ', '.join(moderators)) - return smtp.sendEmail( - 'twisted@' + socket.gethostname(), - moderators, - article.body, - dict(article.headers.values()) - ) - - def listRequest(self): "Returns a list of 4-tuples: (name, max index, min index, flags)" l = self.db['groups'] @@ -366,8 +415,8 @@ def articleExistsRequest(self, id): - for g in self.db.values(): - for a in g.values(): + for group in self.db['groups']: + for a in self.db[group].values(): if a.getHeader('Message-ID') == id: return defer.succeed(1) return defer.succeed(0) @@ -426,7 +475,7 @@ try: self.db = pickle.load(open(filename)) PickleStorage.sharedDBs[filename] = self.db - except IOError, e: + except IOError: self.db = PickleStorage.sharedDBs[filename] = {} self.db['groups'] = groups if groups is not None: @@ -449,16 +498,25 @@ self.articles = {} -class NewsShelf: +class NewsShelf(_ModerationMixin): """ A NewStorage implementation using Twisted's dirdbm persistence module. """ implements(INewsStorage) - def __init__(self, mailhost, path): + def __init__(self, mailhost, path, sender=None): + """ + @param mailhost: A C{str} giving the mail exchange host which will + accept moderation emails from this server. Must accept emails + destined for any address specified as a moderator. + + @param sender: A C{str} giving the address which will be used as the + sender of any moderation email generated by this server. + """ self.path = path - self.mailhost = mailhost + self._mailhost = self.mailhost = mailhost + self._sender = sender if not os.path.exists(path): os.mkdir(path) @@ -517,17 +575,12 @@ def notifyModerator(self, moderator, article): - # Moderated postings go through as long as they have an Approved - # header, regardless of what the value is - print 'To is ', moderator - article.putHeader('To', moderator) - return smtp.sendEmail( - self.mailhost, - 'twisted-news@' + socket.gethostname(), - moderator, - article.body, - dict(article.headers.values()) - ) + """ + Notify a single moderator about an article requiring moderation. + + C{notifyModerators} should be preferred. + """ + return self.notifyModerators([moderator], article) def postRequest(self, message): @@ -541,7 +594,7 @@ # Check for moderated status moderator = self.getModerator(groups) if moderator and not article.getHeader('Approved'): - return self.notifyModerator(moderator, article) + return self.notifyModerators([moderator], article) for group in groups: diff -Nru twisted-news-10.0.0/twisted/news/__init__.py twisted-news-12.0.0/twisted/news/__init__.py --- twisted-news-10.0.0/twisted/news/__init__.py 2010-03-09 13:26:32.000000000 +0000 +++ twisted-news-12.0.0/twisted/news/__init__.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. """ diff -Nru twisted-news-10.0.0/twisted/news/news.py twisted-news-12.0.0/twisted/news/news.py --- twisted-news-10.0.0/twisted/news/news.py 2010-03-09 13:26:32.000000000 +0000 +++ twisted-news-12.0.0/twisted/news/news.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. diff -Nru twisted-news-10.0.0/twisted/news/nntp.py twisted-news-12.0.0/twisted/news/nntp.py --- twisted-news-10.0.0/twisted/news/nntp.py 2010-03-09 13:26:32.000000000 +0000 +++ twisted-news-12.0.0/twisted/news/nntp.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,5 +1,5 @@ # -*- test-case-name: twisted.news.test.test_nntp -*- -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. diff -Nru twisted-news-10.0.0/twisted/news/tap.py twisted-news-12.0.0/twisted/news/tap.py --- twisted-news-10.0.0/twisted/news/tap.py 2010-03-09 13:26:32.000000000 +0000 +++ twisted-news-12.0.0/twisted/news/tap.py 2011-10-18 10:31:11.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. @@ -84,7 +84,11 @@ ["datadir", "d", "news.db", "Root data storage path"], ["mailhost", "m", "localhost", "Host of SMTP server to use"] ] - zsh_actions = {"datadir" : "_dirs", "mailhost" : "_hosts"} + compData = usage.Completions( + optActions={"datadir" : usage.CompleteDirs(), + "mailhost" : usage.CompleteHostnames(), + "interface" : usage.CompleteNetInterfaces()} + ) def __init__(self): usage.Options.__init__(self) diff -Nru twisted-news-10.0.0/twisted/news/test/test_database.py twisted-news-12.0.0/twisted/news/test/test_database.py --- twisted-news-10.0.0/twisted/news/test/test_database.py 1970-01-01 00:00:00.000000000 +0000 +++ twisted-news-12.0.0/twisted/news/test/test_database.py 2011-07-14 19:05:14.000000000 +0000 @@ -0,0 +1,224 @@ +# Copyright (c) Twisted Matrix Laboratories. +# See LICENSE for details. + +""" +Tests for L{twisted.news.database}. +""" + +__metaclass__ = type + +from email.Parser import Parser +from socket import gethostname + +from twisted.trial.unittest import TestCase +from twisted.internet.defer import succeed +from twisted.mail.smtp import messageid +from twisted.news.database import Article, PickleStorage, NewsShelf + + + +class ModerationTestsMixin: + """ + Tests for the moderation features of L{INewsStorage} implementations. + """ + def setUp(self): + self._email = [] + + + def sendmail(self, smtphost, from_addr, to_addrs, msg, + senderDomainName=None, port=25): + """ + Fake of L{twisted.mail.smtp.sendmail} which records attempts to send + email and immediately pretends success. + + Subclasses should arrange for their storage implementation to call this + instead of the real C{sendmail} function. + """ + self._email.append(( + smtphost, from_addr, to_addrs, msg, senderDomainName, port)) + return succeed(None) + + + _messageTemplate = """\ +From: some dude +To: another person +Subject: activities etc +Message-ID: %(articleID)s +Newsgroups: %(newsgroup)s +%(approved)s +Body of the message is such. +""".replace('\n', '\r\n') + + + def getApprovedMessage(self, articleID, group): + """ + Return a C{str} containing an RFC 2822 formatted message including an + I{Approved} header indicating it has passed through moderation. + """ + return self._messageTemplate % { + 'articleID': articleID, + 'newsgroup': group, + 'approved': 'Approved: yup\r\n'} + + + def getUnapprovedMessage(self, articleID, group): + """ + Return a C{str} containing an RFC 2822 formatted message with no + I{Approved} header indicating it may require moderation. + """ + return self._messageTemplate % { + 'articleID': articleID, + 'newsgroup': group, + 'approved': '\r\n'} + + + def getStorage(self, groups, moderators, mailhost, sender): + """ + Override in a subclass to return a L{INewsStorage} provider to test for + correct moderation behavior. + + @param groups: A C{list} of C{str} naming the groups which should exist + in the resulting storage object. + + @param moderators: A C{dict} mapping C{str} each group name to a C{list} + of C{str} giving moderator email (RFC 2821) addresses. + """ + raise NotImplementedError() + + + def test_postApproved(self): + """ + L{INewsStorage.postRequest} posts the message if it includes an + I{Approved} header. + """ + group = "example.group" + moderator = "alice@example.com" + mailhost = "127.0.0.1" + sender = "bob@example.org" + articleID = messageid() + storage = self.getStorage( + [group], {group: [moderator]}, mailhost, sender) + message = self.getApprovedMessage(articleID, group) + result = storage.postRequest(message) + + def cbPosted(ignored): + self.assertEqual(self._email, []) + exists = storage.articleExistsRequest(articleID) + exists.addCallback(self.assertTrue) + return exists + result.addCallback(cbPosted) + return result + + + def test_postModerated(self): + """ + L{INewsStorage.postRequest} forwards a message to the moderator if it + does not include an I{Approved} header. + """ + group = "example.group" + moderator = "alice@example.com" + mailhost = "127.0.0.1" + sender = "bob@example.org" + articleID = messageid() + storage = self.getStorage( + [group], {group: [moderator]}, mailhost, sender) + message = self.getUnapprovedMessage(articleID, group) + result = storage.postRequest(message) + + def cbModerated(ignored): + self.assertEqual(len(self._email), 1) + self.assertEqual(self._email[0][0], mailhost) + self.assertEqual(self._email[0][1], sender) + self.assertEqual(self._email[0][2], [moderator]) + self._checkModeratorMessage( + self._email[0][3], sender, moderator, group, message) + self.assertEqual(self._email[0][4], None) + self.assertEqual(self._email[0][5], 25) + exists = storage.articleExistsRequest(articleID) + exists.addCallback(self.assertFalse) + return exists + result.addCallback(cbModerated) + return result + + + def _checkModeratorMessage(self, messageText, sender, moderator, group, postingText): + p = Parser() + msg = p.parsestr(messageText) + headers = dict(msg.items()) + del headers['Message-ID'] + self.assertEqual( + headers, + {'From': sender, + 'To': moderator, + 'Subject': 'Moderate new %s message: activities etc' % (group,), + 'Content-Type': 'message/rfc822'}) + + posting = p.parsestr(postingText) + attachment = msg.get_payload()[0] + + for header in ['from', 'to', 'subject', 'message-id', 'newsgroups']: + self.assertEqual(posting[header], attachment[header]) + + self.assertEqual(posting.get_payload(), attachment.get_payload()) + + + +class PickleStorageTests(ModerationTestsMixin, TestCase): + """ + Tests for L{PickleStorage}. + """ + def getStorage(self, groups, moderators, mailhost, sender): + """ + Create and return a L{PickleStorage} instance configured to require + moderation. + """ + storageFilename = self.mktemp() + storage = PickleStorage( + storageFilename, groups, moderators, mailhost, sender) + storage.sendmail = self.sendmail + self.addCleanup(PickleStorage.sharedDBs.pop, storageFilename) + return storage + + + +class NewsShelfTests(ModerationTestsMixin, TestCase): + """ + Tests for L{NewsShelf}. + """ + def getStorage(self, groups, moderators, mailhost, sender): + """ + Create and return a L{NewsShelf} instance configured to require + moderation. + """ + storageFilename = self.mktemp() + shelf = NewsShelf(mailhost, storageFilename, sender) + for name in groups: + shelf.addGroup(name, 'm') # Dial 'm' for moderator + for address in moderators.get(name, []): + shelf.addModerator(name, address) + shelf.sendmail = self.sendmail + return shelf + + + def test_notifyModerator(self): + """ + L{NewsShelf.notifyModerator} sends a moderation email to a single + moderator. + """ + shelf = NewsShelf('example.com', self.mktemp(), 'alice@example.com') + shelf.sendmail = self.sendmail + shelf.notifyModerator('bob@example.org', Article('Foo: bar', 'Some text')) + self.assertEqual(len(self._email), 1) + + + def test_defaultSender(self): + """ + If no sender is specified to L{NewsShelf.notifyModerators}, a default + address based on the system hostname is used for both the envelope and + RFC 2822 sender addresses. + """ + shelf = NewsShelf('example.com', self.mktemp()) + shelf.sendmail = self.sendmail + shelf.notifyModerators(['bob@example.org'], Article('Foo: bar', 'Some text')) + self.assertEqual(self._email[0][1], 'twisted-news@' + gethostname()) + self.assertIn('From: twisted-news@' + gethostname(), self._email[0][3]) diff -Nru twisted-news-10.0.0/twisted/news/test/test_news.py twisted-news-12.0.0/twisted/news/test/test_news.py --- twisted-news-10.0.0/twisted/news/test/test_news.py 2010-03-09 13:26:32.000000000 +0000 +++ twisted-news-12.0.0/twisted/news/test/test_news.py 2011-07-14 19:05:14.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. import sys, types @@ -50,10 +50,10 @@ def cbArticle(result): self.failUnless(isinstance(result, tuple), 'callback result is wrong type: ' + str(result)) - self.assertEquals(len(result), 3, + self.assertEqual(len(result), 3, 'callback result list should have three entries: ' + str(result)) - self.assertEquals(result[1], MESSAGE_ID, + self.assertEqual(result[1], MESSAGE_ID, "callback result Message-Id doesn't match: %s vs %s" % (MESSAGE_ID, result[1])) body = result[2].read() @@ -76,11 +76,11 @@ return d def cbHead(result): - self.assertEquals(result[1], MESSAGE_ID, + self.assertEqual(result[1], MESSAGE_ID, "callback result Message-Id doesn't match: %s vs %s" % (MESSAGE_ID, result[1])) - self.assertEquals(result[2][-2:], '\r\n', + self.assertEqual(result[2][-2:], '\r\n', "headers must be \\r\\n terminated.") d.addCallback(cbArticle) @@ -99,7 +99,7 @@ def cbBody(result): body = result[2].read() - self.assertEquals(body[0:4], 'this', + self.assertEqual(body[0:4], 'this', "message body has been altered: " + pformat(body[0:4])) diff -Nru twisted-news-10.0.0/twisted/news/test/test_nntp.py twisted-news-12.0.0/twisted/news/test/test_nntp.py --- twisted-news-10.0.0/twisted/news/test/test_nntp.py 2010-03-09 13:26:32.000000000 +0000 +++ twisted-news-12.0.0/twisted/news/test/test_nntp.py 2011-07-14 19:05:14.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2001-2004 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.trial import unittest @@ -36,39 +36,39 @@ def __init__(self): nntp.NNTPClient.__init__(self) - def assertEquals(self, foo, bar): + def assertEqual(self, foo, bar): if foo != bar: raise AssertionError("%r != %r!" % (foo, bar)) - + def connectionMade(self): nntp.NNTPClient.connectionMade(self) self.fetchSubscriptions() def gotSubscriptions(self, subscriptions): - self.assertEquals(len(subscriptions), len(SUBSCRIPTIONS)) + self.assertEqual(len(subscriptions), len(SUBSCRIPTIONS)) for s in subscriptions: assert s in SUBSCRIPTIONS self.fetchGroups() - + def gotAllGroups(self, info): - self.assertEquals(len(info), len(ALL_GROUPS)) - self.assertEquals(info[0], ALL_GROUPS[0]) - + self.assertEqual(len(info), len(ALL_GROUPS)) + self.assertEqual(info[0], ALL_GROUPS[0]) + self.fetchGroup('alt.test.nntp') - - + + def getAllGroupsFailed(self, error): raise AssertionError("fetchGroups() failed: %s" % (error,)) def gotGroup(self, info): - self.assertEquals(len(info), 6) - self.assertEquals(info, GROUP) - + self.assertEqual(len(info), 6) + self.assertEqual(info, GROUP) + self.postArticle(POST_STRING) - - + + def getSubscriptionsFailed(self, error): raise AssertionError("fetchSubscriptions() failed: %s" % (error,)) @@ -84,17 +84,17 @@ def postedOk(self): self.fetchArticle(1) - + def gotArticle(self, info): origBody = POST_STRING.split('\n\n')[1] newBody = info.split('\n\n', 1)[1] - self.assertEquals(origBody, newBody) - + self.assertEqual(origBody, newBody) + # We're done self.transport.loseConnection() - - + + def getArticleFailed(self, error): raise AssertionError("fetchArticle() failed: %s" % (error,)) @@ -105,7 +105,7 @@ self.server.factory = self self.backend = database.NewsShelf(None, 'news.db') self.backend.addGroup('alt.test.nntp', 'y') - + for s in SUBSCRIPTIONS: self.backend.addSubscription(s) diff -Nru twisted-news-10.0.0/twisted/news/_version.py twisted-news-12.0.0/twisted/news/_version.py --- twisted-news-10.0.0/twisted/news/_version.py 2010-03-09 13:26:32.000000000 +0000 +++ twisted-news-12.0.0/twisted/news/_version.py 2012-02-10 14:56:39.000000000 +0000 @@ -1,3 +1,3 @@ # This is an auto-generated file. Do not edit it. from twisted.python import versions -version = versions.Version('twisted.news', 10, 0, 0) +version = versions.Version('twisted.news', 12, 0, 0) diff -Nru twisted-news-10.0.0/twisted/plugins/twisted_news.py twisted-news-12.0.0/twisted/plugins/twisted_news.py --- twisted-news-10.0.0/twisted/plugins/twisted_news.py 2010-03-09 13:26:32.000000000 +0000 +++ twisted-news-12.0.0/twisted/plugins/twisted_news.py 2011-02-14 04:45:15.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright (c) 2001-2008 Twisted Matrix Laboratories. +# Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. from twisted.application.service import ServiceMaker