From 83391b8af8dbf866c004fe8a13d920337ca74aa1 Mon Sep 17 00:00:00 2001 From: richard Date: Thu, 12 Mar 2009 02:52:56 +0000 Subject: [PATCH] Add compatibility package to allow us to deal with Python versions 2.3 through to 2.6. Outstanding issues noted in roundup/anypy/TODO.txt git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/roundup/trunk@4181 57a73879-2fb5-44c3-a270-3262357dd7e2 --- CHANGES.txt | 1 + doc/upgrading.txt | 16 ++ roundup/admin.py | 2 +- roundup/anypy/README.txt | 57 +++++++ roundup/anypy/TODO.txt | 27 ++++ roundup/anypy/__init__.py | 7 + roundup/anypy/hashlib_.py | 11 ++ roundup/anypy/sets_.py | 30 ++++ roundup/backends/indexer_common.py | 10 +- roundup/backends/indexer_rdbms.py | 26 ++-- roundup/hyperdb.py | 13 +- roundup/install_util.py | 7 +- roundup/password.py | 32 ++-- scripts/import_sf.py | 26 ++-- setup.py | 1 + .../classic/detectors/nosyreaction.py | 7 +- test/db_test_base.py | 22 +-- test/test_anypy_hashlib.py | 139 ++++++++++++++++++ test/test_hyperdbvals.py | 5 +- 19 files changed, 370 insertions(+), 69 deletions(-) create mode 100644 roundup/anypy/README.txt create mode 100644 roundup/anypy/TODO.txt create mode 100644 roundup/anypy/__init__.py create mode 100644 roundup/anypy/hashlib_.py create mode 100644 roundup/anypy/sets_.py create mode 100644 test/test_anypy_hashlib.py diff --git a/CHANGES.txt b/CHANGES.txt index 0cf9de6..5df3f55 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -10,6 +10,7 @@ Fixes: - HTML file uploads served as application/octet-stream - New item action reject creation of new users - Item retirement was not being controlled +- Roundup is now compatible with Python 2.6 - XXX need to include Stefan's changes in here too diff --git a/doc/upgrading.txt b/doc/upgrading.txt index 02a0489..39f27f4 100644 --- a/doc/upgrading.txt +++ b/doc/upgrading.txt @@ -61,6 +61,22 @@ Should be replaced with:: +Fix for Python 2.6+ users +------------------------- + +If you use Python 2.6 you should edit your tracker's +``detectors/nosyreaction.py`` file to change:: + + import sets + +at the top to:: + + from roundup.anypy.sets_ import set + +and then all instances of ``sets.Set()`` to ``set()`` in the later code. + + + Trackers currently allowing HTML file uploading ----------------------------------------------- diff --git a/roundup/admin.py b/roundup/admin.py index 14b7c42..91273bc 100644 --- a/roundup/admin.py +++ b/roundup/admin.py @@ -729,7 +729,7 @@ Erase it? Y/N: """)) print _('%(key)s: %(value)s')%locals() def do_display(self, args): - """Usage: display designator[,designator]* + ''"""Usage: display designator[,designator]* Show the property values for the given node(s). This lists the properties and their associated values for the given diff --git a/roundup/anypy/README.txt b/roundup/anypy/README.txt new file mode 100644 index 0000000..7b0fe72 --- /dev/null +++ b/roundup/anypy/README.txt @@ -0,0 +1,57 @@ +roundup.anypy package - Python version compatibility layer +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Roundup currently supports Python 2.3 to 2.6; however, some modules +have been introduced, while others have been deprecated. The modules +in this package provide the functionalities which are used by Roundup + +- adapting the most recent Python usage +- using new built-in functionality +- avoiding deprecation warnings + +Use the modules in this package to preserve Roundup's compatibility. + +sets_: sets compatibility module +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Since Python 2.4, there is a built-in type 'set'; therefore, the 'sets' +module is deprecated since version 2.6. As far as Roundup is concerned, +the usage is identical; see +http://docs.python.org/library/sets.html#comparison-to-the-built-in-set-types + +Uses the built-in type 'set' if available, and thus avoids +deprecation warnings. Simple usage: + +Change all:: + from sets import Set + +to:: + from roundup.anypy.sets_ import set + +and use 'set' instead of 'Set' (or sets.Set, respectively). +To avoid unnecessary imports, you can:: + + try: + set + except NameError: + from roundup.anypy.sets_ import set + +hashlib_: md5/sha/hashlib compatibility +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The md5 and sha modules are deprecated since Python 2.6; the hashlib +module, introduced with Python 2.5, is recommended instead. + +Change all:: + import md5 + md5.md5(), md5.new() + import sha + sha.sha(), sha.new() + +to:: + from roundup.anypy.hashlib_ import md5 + md5() + from roundup.anypy.hashlib_ import sha1 + sha1() + +# vim: si diff --git a/roundup/anypy/TODO.txt b/roundup/anypy/TODO.txt new file mode 100644 index 0000000..12103ae --- /dev/null +++ b/roundup/anypy/TODO.txt @@ -0,0 +1,27 @@ +Python compatiblity TODO +~~~~~~~~~~~~~~~~~~~~~~~~ + +- the popen2 module is deprecated as of Python 2.6; + the subprocess module is available since Python 2.4, + thus a roundup.anypy.subprocess_ module is needed + +- the MimeWriter module is deprecated as of Python 2.6. The email package is + available since Python 2.2, thus we should manage without a ...email_ + module; however, it has suffered some API changes over the time + (http://docs.python.org/library/email.html#package-history), + so this is not sure. + + Here's an incomplete replacement table: + + MimeWriter usage checked for + -> email usage Python ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~ + MimeWriter.MimeWriter + -> email.Message.Message (2.3) + + MimeWriter.MimeWrite.addheader + -> email.Message.Message.add_header (2.3) + +- test.test_sqlite.sqliteDBTest.testStringUnicode fails + +# vim: si diff --git a/roundup/anypy/__init__.py b/roundup/anypy/__init__.py new file mode 100644 index 0000000..21eee1e --- /dev/null +++ b/roundup/anypy/__init__.py @@ -0,0 +1,7 @@ +""" +roundup.anypy - compatibility layer for any Python 2.3+ +""" +VERSION = '.'.join(map(str, + (0, + 1, # hashlib_, sets_ + ))) diff --git a/roundup/anypy/hashlib_.py b/roundup/anypy/hashlib_.py new file mode 100644 index 0000000..9365b97 --- /dev/null +++ b/roundup/anypy/hashlib_.py @@ -0,0 +1,11 @@ +""" +anypy.hashlib_: encapsulation of hashlib/md5/sha1/sha +""" + +try: + from hashlib import md5, sha1 # new in Python 2.5 +except ImportError: + from md5 import md5 # deprecated in Python 2.6 + from sha import sha as sha1 # deprecated in Python 2.6 + +# vim: ts=8 sts=4 sw=4 si diff --git a/roundup/anypy/sets_.py b/roundup/anypy/sets_.py new file mode 100644 index 0000000..e1f2f30 --- /dev/null +++ b/roundup/anypy/sets_.py @@ -0,0 +1,30 @@ +""" +anypy.sets_: sets compatibility module + +uses the built-in type 'set' if available, and thus avoids +deprecation warnings. Simple usage: + +Change all + from sets import Set +to + from roundup.anypy.sets_ import set + +and use 'set' instead of 'Set'. +To avoid unnecessary imports, you can: + + try: + set + except NameError: + from roundup.anypy.sets_ import set + +see: +http://docs.python.org/library/sets.html#comparison-to-the-built-in-set-types + +""" + +try: + set = set # built-in since Python 2.4 +except NameError, TypeError: + from sets import Set as set # deprecated as of Python 2.6 + +# vim: ts=8 sts=4 sw=4 si et diff --git a/roundup/backends/indexer_common.py b/roundup/backends/indexer_common.py index 496475d..5b5dd60 100644 --- a/roundup/backends/indexer_common.py +++ b/roundup/backends/indexer_common.py @@ -1,5 +1,7 @@ #$Id: indexer_common.py,v 1.11 2008-09-11 19:41:07 schlatterbeck Exp $ -import re, sets +import re +# Python 2.3 ... 2.6 compatibility: +from roundup.anypy.sets_ import set from roundup import hyperdb @@ -17,7 +19,7 @@ def _isLink(propclass): class Indexer: def __init__(self, db): - self.stopwords = sets.Set(STOPWORDS) + self.stopwords = set(STOPWORDS) for word in db.config[('main', 'indexer_stopwords')]: self.stopwords.add(word) @@ -28,11 +30,11 @@ class Indexer: return self.find(search_terms) def search(self, search_terms, klass, ignore={}): - '''Display search results looking for [search, terms] associated + """Display search results looking for [search, terms] associated with the hyperdb Class "klass". Ignore hits on {class: property}. "dre" is a helper, not an argument. - ''' + """ # do the index lookup hits = self.getHits(search_terms, klass) if not hits: diff --git a/roundup/backends/indexer_rdbms.py b/roundup/backends/indexer_rdbms.py index 2547300..b992c70 100644 --- a/roundup/backends/indexer_rdbms.py +++ b/roundup/backends/indexer_rdbms.py @@ -1,9 +1,11 @@ #$Id: indexer_rdbms.py,v 1.18 2008-09-01 00:43:02 richard Exp $ -''' This implements the full-text indexer over two RDBMS tables. The first +""" This implements the full-text indexer over two RDBMS tables. The first is a mapping of words to occurance IDs. The second maps the IDs to (Class, propname, itemid) instances. -''' -import re, sets +""" +import re +# Python 2.3 ... 2.6 compatibility: +from roundup.anypy.sets_ import set from roundup.backends.indexer_common import Indexer as IndexerBase @@ -14,27 +16,27 @@ class Indexer(IndexerBase): self.reindex = 0 def close(self): - '''close the indexing database''' + """close the indexing database""" # just nuke the circular reference self.db = None def save_index(self): - '''Save the changes to the index.''' + """Save the changes to the index.""" # not necessary - the RDBMS connection will handle this for us pass def force_reindex(self): - '''Force a reindexing of the database. This essentially + """Force a reindexing of the database. This essentially empties the tables ids and index and sets a flag so - that the databases are reindexed''' + that the databases are reindexed""" self.reindex = 1 def should_reindex(self): - '''returns True if the indexes need to be rebuilt''' + """returns True if the indexes need to be rebuilt""" return self.reindex def add_text(self, identifier, text, mime_type='text/plain'): - ''' "identifier" is (classname, itemid, property) ''' + """ "identifier" is (classname, itemid, property) """ if mime_type != 'text/plain': return @@ -65,7 +67,7 @@ class Indexer(IndexerBase): text = unicode(text, "utf-8", "replace").upper() wordlist = [w.encode("utf-8", "replace") for w in re.findall(r'(?u)\b\w{2,25}\b', text)] - words = sets.Set() + words = set() for word in wordlist: if self.is_stopword(word): continue if len(word) > 25: continue @@ -77,10 +79,10 @@ class Indexer(IndexerBase): self.db.cursor.executemany(sql, words) def find(self, wordlist): - '''look up all the words in the wordlist. + """look up all the words in the wordlist. If none are found return an empty dictionary * more rules here - ''' + """ if not wordlist: return [] diff --git a/roundup/hyperdb.py b/roundup/hyperdb.py index 856f2d4..91a9fef 100644 --- a/roundup/hyperdb.py +++ b/roundup/hyperdb.py @@ -22,7 +22,8 @@ __docformat__ = 'restructuredtext' # standard python modules import os, re, shutil, weakref -from sets import Set +# Python 2.3 ... 2.6 compatibility: +from roundup.anypy.sets_ import set # roundup modules import date, password @@ -193,7 +194,7 @@ class Multilink(_Pointer): # definitely in the new list (in case of e.g. # =A,+B, which should replace the old # list with A,B) - set = 1 + do_set = 1 newvalue = [] for item in value: item = item.strip() @@ -206,10 +207,10 @@ class Multilink(_Pointer): if item.startswith('-'): remove = 1 item = item[1:] - set = 0 + do_set = 0 elif item.startswith('+'): item = item[1:] - set = 0 + do_set = 0 # look up the value itemid = convertLinkValue(db, propname, self, item) @@ -228,7 +229,7 @@ class Multilink(_Pointer): # that's it, set the new Multilink property value, # or overwrite it completely - if set: + if do_set: value = newvalue else: value = curvalue @@ -487,7 +488,7 @@ class Proptree(object): v = self._val if not isinstance(self._val, type([])): v = [self._val] - vals = Set(v) + vals = set(v) vals.intersection_update(val) self._val = [v for v in vals] else: diff --git a/roundup/install_util.py b/roundup/install_util.py index 2e59a5b..51becb0 100644 --- a/roundup/install_util.py +++ b/roundup/install_util.py @@ -21,7 +21,8 @@ """ __docformat__ = 'restructuredtext' -import os, sha, shutil +import os, shutil +from roundup.anypy.hashlib_ import sha1 sgml_file_types = [".xml", ".ent", ".html"] hash_file_types = [".py", ".sh", ".conf", ".cgi"] @@ -59,7 +60,7 @@ def checkDigest(filename): del lines[-1] # calculate current digest - digest = sha.new() + digest = sha1() for line in lines: digest.update(line) @@ -74,7 +75,7 @@ class DigestFile: def __init__(self, filename): self.filename = filename - self.digest = sha.new() + self.digest = sha1() self.file = open(self.filename, "w") def write(self, data): diff --git a/roundup/password.py b/roundup/password.py index 6a555bb..201a6a9 100644 --- a/roundup/password.py +++ b/roundup/password.py @@ -21,26 +21,26 @@ """ __docformat__ = 'restructuredtext' -import sha, md5, re, string, random +import re, string, random +from roundup.anypy.hashlib_ import md5, sha1 try: import crypt -except: +except ImportError: crypt = None - pass class PasswordValueError(ValueError): - ''' The password value is not valid ''' + """ The password value is not valid """ pass def encodePassword(plaintext, scheme, other=None): - '''Encrypt the plaintext password. - ''' + """Encrypt the plaintext password. + """ if plaintext is None: plaintext = "" if scheme == 'SHA': - s = sha.sha(plaintext).hexdigest() + s = sha1(plaintext).hexdigest() elif scheme == 'MD5': - s = md5.md5(plaintext).hexdigest() + s = md5(plaintext).hexdigest() elif scheme == 'crypt' and crypt is not None: if other is not None: salt = other @@ -59,7 +59,7 @@ def generatePassword(length=8): return ''.join([random.choice(chars) for x in range(length)]) class Password: - '''The class encapsulates a Password property type value in the database. + """The class encapsulates a Password property type value in the database. The encoding of the password is one if None, 'SHA', 'MD5' or 'plaintext'. The encodePassword function is used to actually encode the password from @@ -79,13 +79,13 @@ class Password: 1 >>> 'not sekrit' != p 1 - ''' + """ default_scheme = 'SHA' # new encryptions use this scheme pwre = re.compile(r'{(\w+)}(.+)') def __init__(self, plaintext=None, scheme=None, encrypted=None): - '''Call setPassword if plaintext is not None.''' + """Call setPassword if plaintext is not None.""" if scheme is None: scheme = self.default_scheme if plaintext is not None: @@ -98,9 +98,9 @@ class Password: self.plaintext = None def unpack(self, encrypted, scheme=None): - '''Set the password info from the scheme: string + """Set the password info from the scheme: string (the inverse of __str__) - ''' + """ m = self.pwre.match(encrypted) if m: self.scheme = m.group(1) @@ -111,7 +111,7 @@ class Password: self.setPassword(encrypted, scheme) def setPassword(self, plaintext, scheme=None): - '''Sets encrypts plaintext.''' + """Sets encrypts plaintext.""" if scheme is None: scheme = self.default_scheme self.scheme = scheme @@ -119,7 +119,7 @@ class Password: self.plaintext = plaintext def __cmp__(self, other): - '''Compare this password against another password.''' + """Compare this password against another password.""" # check to see if we're comparing instances if isinstance(other, Password): if self.scheme != other.scheme: @@ -133,7 +133,7 @@ class Password: self.password)) def __str__(self): - '''Stringify the encrypted password for database storage.''' + """Stringify the encrypted password for database storage.""" if self.password is None: raise ValueError, 'Password not set' return '{%s}%s'%(self.scheme, self.password) diff --git a/scripts/import_sf.py b/scripts/import_sf.py index c5ab933..b64b616 100644 --- a/scripts/import_sf.py +++ b/scripts/import_sf.py @@ -1,4 +1,4 @@ -''' Import tracker data from Sourceforge.NET +""" Import tracker data from Sourceforge.NET This script needs four steps to work: @@ -19,9 +19,11 @@ This script needs four steps to work: roundup-admin -i import /tmp/imported And you're done! -''' +""" -import sys, sets, os, csv, time, urllib2, httplib, mimetypes, urlparse +import sys, os, csv, time, urllib2, httplib, mimetypes, urlparse +# Python 2.3 ... 2.6 compatibility: +from roundup.anypy.sets_ import set try: import cElementTree as ElementTree @@ -53,8 +55,8 @@ def get_url(aid): def fetch_files(xml_file, file_dir): """ Fetch files referenced in the xml_file into the dir file_dir. """ root = ElementTree.parse(xml_file).getroot() - to_fetch = sets.Set() - deleted = sets.Set() + to_fetch = set() + deleted = set() for artifact in root.find('artifacts'): for field in artifact.findall('field'): if field.get('name') == 'artifact_id': @@ -73,7 +75,7 @@ def fetch_files(xml_file, file_dir): deleted.add((aid, fid)) to_fetch = to_fetch - deleted - got = sets.Set(os.listdir(file_dir)) + got = set(os.listdir(file_dir)) to_fetch = to_fetch - got # load cached urls (sigh) @@ -122,10 +124,10 @@ def import_xml(tracker_home, xml_file, file_dir): # parse out the XML artifacts = [] - categories = sets.Set() - users = sets.Set() - add_files = sets.Set() - remove_files = sets.Set() + categories = set() + users = set() + add_files = set() + remove_files = set() for artifact in root.find('artifacts'): d = {} op = {} @@ -254,7 +256,7 @@ def import_xml(tracker_home, xml_file, file_dir): else: d['status'] = unread - nosy = sets.Set() + nosy = set() for message in artifact.get('messages', []): authid = users[message['user_name']] if not message['body']: continue @@ -338,7 +340,7 @@ def import_xml(tracker_home, xml_file, file_dir): f.close() def convert_message(content, id): - ''' Strip off the useless sf message header crap ''' + """ Strip off the useless sf message header crap """ if content[:14] == 'Logged In: YES': return '\n'.join(content.splitlines()[3:]).strip() return content diff --git a/setup.py b/setup.py index 3a02097..e2e226d 100644 --- a/setup.py +++ b/setup.py @@ -58,6 +58,7 @@ def main(): # template munching packagelist = [ 'roundup', + 'roundup.anypy', 'roundup.cgi', 'roundup.cgi.PageTemplates', 'roundup.cgi.TAL', diff --git a/share/roundup/templates/classic/detectors/nosyreaction.py b/share/roundup/templates/classic/detectors/nosyreaction.py index c732fd0..ae00795 100644 --- a/share/roundup/templates/classic/detectors/nosyreaction.py +++ b/share/roundup/templates/classic/detectors/nosyreaction.py @@ -17,7 +17,8 @@ # #$Id: nosyreaction.py,v 1.4 2005-04-04 08:47:14 richard Exp $ -import sets +# Python 2.3 ... 2.6 compatibility: +from roundup.anypy.sets_ import set from roundup import roundupdb, hyperdb @@ -67,7 +68,7 @@ def updatenosy(db, cl, nodeid, newvalues): '''Update the nosy list for changes to the assignedto ''' # nodeid will be None if this is a new node - current_nosy = sets.Set() + current_nosy = set() if nodeid is None: ok = ('new', 'yes') else: @@ -87,7 +88,7 @@ def updatenosy(db, cl, nodeid, newvalues): continue current_nosy.add(value) - new_nosy = sets.Set(current_nosy) + new_nosy = set(current_nosy) # add assignedto(s) to the nosy list if newvalues.has_key('assignedto') and newvalues['assignedto'] is not None: diff --git a/test/db_test_base.py b/test/db_test_base.py index 94d34d3..241fd95 100644 --- a/test/db_test_base.py +++ b/test/db_test_base.py @@ -17,7 +17,9 @@ # # $Id: db_test_base.py,v 1.101 2008-08-19 01:40:59 richard Exp $ -import unittest, os, shutil, errno, imp, sys, time, pprint, sets, base64, os.path +import unittest, os, shutil, errno, imp, sys, time, pprint, base64, os.path +# Python 2.3 ... 2.6 compatibility: +from roundup.anypy.sets_ import set from roundup.hyperdb import String, Password, Link, Multilink, Date, \ Interval, DatabaseError, Boolean, Number, Node @@ -284,7 +286,7 @@ class DBTest(MyTestCase): # try a couple of the built-in iterable types to make # sure that we accept them and handle them properly # try a set as input for the multilink - nid = self.db.issue.create(title="spam", nosy=sets.Set(u1)) + nid = self.db.issue.create(title="spam", nosy=set(u1)) if commit: self.db.commit() self.assertEqual(self.db.issue.get(nid, "nosy"), [u1]) self.assertRaises(TypeError, self.db.issue.set, nid, @@ -294,7 +296,7 @@ class DBTest(MyTestCase): if commit: self.db.commit() self.assertEqual(self.db.issue.get(nid, "nosy"), []) # make sure we accept a frozen set - self.db.issue.set(nid, nosy=sets.Set([u1,u2])) + self.db.issue.set(nid, nosy=set([u1,u2])) if commit: self.db.commit() l = [u1,u2]; l.sort() m = self.db.issue.get(nid, "nosy"); m.sort() @@ -487,12 +489,12 @@ class DBTest(MyTestCase): others = nodeids[:] others.remove('1') - self.assertEqual(sets.Set(self.db.status.getnodeids()), - sets.Set(nodeids)) - self.assertEqual(sets.Set(self.db.status.getnodeids(retired=True)), - sets.Set(['1'])) - self.assertEqual(sets.Set(self.db.status.getnodeids(retired=False)), - sets.Set(others)) + self.assertEqual(set(self.db.status.getnodeids()), + set(nodeids)) + self.assertEqual(set(self.db.status.getnodeids(retired=True)), + set(['1'])) + self.assertEqual(set(self.db.status.getnodeids(retired=False)), + set(others)) self.assert_(self.db.status.is_retired('1')) @@ -2054,7 +2056,7 @@ class SchemaTest(MyTestCase): self.db.getjournal('a', aid) class RDBMSTest: - ''' tests specific to RDBMS backends ''' + """ tests specific to RDBMS backends """ def test_indexTest(self): self.assertEqual(self.db.sql_index_exists('_issue', '_issue_id_idx'), 1) self.assertEqual(self.db.sql_index_exists('_issue', '_issue_x_idx'), 0) diff --git a/test/test_anypy_hashlib.py b/test/test_anypy_hashlib.py new file mode 100644 index 0000000..cdfb4f1 --- /dev/null +++ b/test/test_anypy_hashlib.py @@ -0,0 +1,139 @@ +#! /usr/bin/env python +import unittest +import warnings + +import roundup.anypy.hashlib_ + +class UntestableWarning(Warning): + pass + +# suppress deprecation warnings; -> warnings.filters[0]: +warnings.simplefilter(action='ignore', + category=DeprecationWarning, + append=0) + +try: + import sha +except: + warnings.warn('sha module functions', UntestableWarning) + sha = None + +try: + import md5 +except: + warnings.warn('md5 module functions', UntestableWarning) + md5 = None + +try: + import hashlib +except: + warnings.warn('hashlib module functions', UntestableWarning) + hashlib = None + +# preserve other warning filters set elsewhere: +del warnings.filters[0] + +if not ((sha or md5) and hashlib): + warnings.warn('anypy.hashlib_ continuity', UntestableWarning) + +class TestCase_anypy_hashlib(unittest.TestCase): + """test the hashlib compatibility layer""" + + testdata = ( + ('', + 'da39a3ee5e6b4b0d3255bfef95601890afd80709', + 'd41d8cd98f00b204e9800998ecf8427e'), + ('Strange women lying in ponds distributing swords' + ' is no basis for a system of government.', + 'da9b2b00466b00411038c057681fe67349f92d7d', + 'b71c5178d316ec446c25386f4857d4f9'), + ('Ottos Mops hopst fort', + 'fdf7e6c54cf07108c86edd8d47c90450671c2c81', + 'a3dce74bee59ee92f1038263e5252500'), + ('Dieser Satz kein Verb', + '3030aded8a079b92043a39dc044a35443959dcdd', + '2f20c69d514228011fb0d32e14dd5d80'), + ) + + # the following two are always excecuted: + def test_sha1_expected_anypy(self): + """...anypy.hashlib_.sha1().hexdigest() yields expected results""" + for src, SHA, MD5 in self.testdata: + self.assertEqual(roundup.anypy.hashlib_.sha1(src).hexdigest(), SHA) + + def test_md5_expected_anypy(self): + """...anypy.hashlib_.md5().hexdigest() yields expected results""" + for src, SHA, MD5 in self.testdata: + self.assertEqual(roundup.anypy.hashlib_.md5(src).hexdigest(), MD5) + + # execution depending on availability of modules: + if md5 and hashlib: + def test_md5_continuity(self): + """md5.md5().digest() == hashlib.md5().digest()""" + if md5.md5 is hashlib.md5: + return + else: + for s, i1, i2 in self.testdata: + self.assertEqual(md5.md5(s).digest(), + hashlib.md5().digest()) + + if md5: + def test_md5_expected(self): + """md5.md5().hexdigest() yields expected results""" + for src, SHA, MD5 in self.testdata: + self.assertEqual(md5.md5(src).hexdigest(), MD5) + + def test_md5_new_expected(self): + """md5.new is md5.md5, or at least yields expected results""" + if md5.new is md5.md5: + return + else: + for src, SHA, MD5 in self.testdata: + self.assertEqual(md5.new(src).hexdigest(), MD5) + + if sha and hashlib: + def test_sha1_continuity(self): + """sha.sha().digest() == hashlib.sha1().digest()""" + if sha.sha is hashlib.sha1: + return + else: + for s in self.testdata: + self.assertEqual(sha.sha(s).digest(), + hashlib.sha1().digest()) + + if sha: + def test_sha_expected(self): + """sha.sha().hexdigest() yields expected results""" + for src, SHA, MD5 in self.testdata: + self.assertEqual(sha.sha(src).hexdigest(), SHA) + + # fails for me with Python 2.3; unittest module bug? + def test_sha_new_expected(self): + """sha.new is sha.sha, or at least yields expected results""" + if sha.new is sha.sha: + return + else: + for src, SHA, MD5 in self.testdata: + self.assertEqual(sha.new(src).hexdigest(), SHA) + + if hashlib: + def test_sha1_expected_hashlib(self): + """hashlib.sha1().hexdigest() yields expected results""" + for src, SHA, MD5 in self.testdata: + self.assertEqual(hashlib.sha1(src).hexdigest(), SHA) + + def test_md5_expected_hashlib(self): + """hashlib.md5().hexdigest() yields expected results""" + for src, SHA, MD5 in self.testdata: + self.assertEqual(hashlib.md5(src).hexdigest(), MD5) + +def test_suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(TestCase_anypy_hashlib)) + return suite + +if __name__ == '__main__': + runner = unittest.TextTestRunner() + unittest.main(testRunner=runner) + +# vim: ts=8 et sts=4 sw=4 si diff --git a/test/test_hyperdbvals.py b/test/test_hyperdbvals.py index 9d01d4d..9b64442 100644 --- a/test/test_hyperdbvals.py +++ b/test/test_hyperdbvals.py @@ -10,7 +10,8 @@ # # $Id: test_hyperdbvals.py,v 1.3 2006-08-18 01:26:19 richard Exp $ -import unittest, os, shutil, errno, sys, difflib, cgi, re, sha +import unittest, os, shutil, errno, sys, difflib, cgi, re +from roundup.anypy.hashlib_ import sha1 from roundup import init, instance, password, hyperdb, date @@ -80,7 +81,7 @@ class RawToHyperdbTest(unittest.TestCase): self.assert_(isinstance(val, password.Password)) val = self._test('password', '{crypt}a string') self.assert_(isinstance(val, password.Password)) - s = sha.sha('a string').hexdigest() + s = sha1('a string').hexdigest() val = self._test('password', '{SHA}'+s) self.assert_(isinstance(val, password.Password)) self.assertEqual(val, 'a string') -- 2.30.2