diff --git a/README.md b/README.md index ab331e2..cc5d8f9 100644 --- a/README.md +++ b/README.md @@ -147,8 +147,30 @@ the [pip](https://packaging.python.org/installing/) tool: >>> from pydpkg import Dsc >>> dsc = Dsc('testdeb_0.0.0.dsc') + >>> dsc.standards_version + '3.9.6' + >>> dsc.format + '3.0 (quilt)' + >>> x.build_depends + 'python (>= 2.6.6-3), debhelper (>= 9)' + +#### Get the full set of dsc headers as a dictionary + >>> dsc.headers - {'Uploaders': 'Nathan J. Mehl ', 'Binary': 'testdeb', 'Maintainer': 'Nathan J. Mehl ', 'Format': '3.0 (quilt)', 'Build-Depends': 'python (>= 2.6.6-3), debhelper (>= 9)', 'Source': 'testdeb', 'Version': '0.0.0-1', 'Standards-Version': '3.9.6', 'Architecture': 'all', 'Files': ' 142ca7334ed1f70302b4504566e0c233 280 testdeb_0.0.0.orig.tar.gz\n fc80e6e7f1c1a08b78a674aaee6c1548 232 testdeb_0.0.0-1.debian.tar.xz', 'Checksums-Sha1': ' f250ac0a426b31df24fc2c98050f4fab90e456cd 280 testdeb_0.0.0.orig.tar.gz\n cb3474ff94053018957ebcf1d8a2b45f75dda449 232 testdeb_0.0.0-1.debian.tar.xz', 'Package-List': 'testdeb', 'Homepage': 'https://github.com/TheClimateCorporation', 'Checksums-Sha256': ' aa57ba8f29840383f5a96c5c8f166a9e6da7a484151938643ce2618e82bfeea7 280 testdeb_0.0.0.orig.tar.gz\n 1ddb2a7336a99bc1d203f3ddb59f6fa2d298e90cb3e59cccbe0c84e359979858 232 testdeb_0.0.0-1.debian.tar.xz'} + {'Architecture': 'all', + 'Binary': 'testdeb', + 'Build-Depends': 'python (>= 2.6.6-3), debhelper (>= 9)', + 'Checksums-Sha1': ' f250ac0a426b31df24fc2c98050f4fab90e456cd 280 testdeb_0.0.0.orig.tar.gz\n cb3474ff94053018957ebcf1d8a2b45f75dda449 232 testdeb_0.0.0-1.debian.tar.xz\n 80cd7b01014a269d445c63b037b885d6002cf533 841 testdeb_0.0.0.dsc', + 'Checksums-Sha256': ' aa57ba8f29840383f5a96c5c8f166a9e6da7a484151938643ce2618e82bfeea7 280 testdeb_0.0.0.orig.tar.gz\n 1ddb2a7336a99bc1d203f3ddb59f6fa2d298e90cb3e59cccbe0c84e359979858 232 testdeb_0.0.0-1.debian.tar.xz\n b5ad1591349eb48db65e6865be506ad7dbd21931902a71addee5b1db9ae1ac2a 841 testdeb_0.0.0.dsc', + 'Files': ' 142ca7334ed1f70302b4504566e0c233 280 testdeb_0.0.0.orig.tar.gz\n fc80e6e7f1c1a08b78a674aaee6c1548 232 testdeb_0.0.0-1.debian.tar.xz\n 893d13a2ef13f7409c9521e8ab1dbccb 841 testdeb_0.0.0.dsc', + 'Format': '3.0 (quilt)', + 'Homepage': 'https://github.com/TheClimateCorporation', + 'Maintainer': 'Nathan J. Mehl ', + 'Package-List': 'testdeb', + 'Source': 'testdeb', + 'Standards-Version': '3.9.6', + 'Uploaders': 'Nathan J. Mehl ', + 'Version': '0.0.0-1'} #### Interact directly with the dsc message @@ -161,7 +183,7 @@ the [pip](https://packaging.python.org/installing/) tool: #### Render the dsc message as a string - >>> print(dsc.message_str) + >>> print(dsc) Format: 3.0 (quilt) Source: testdeb Binary: testdeb @@ -173,20 +195,25 @@ the [pip](https://packaging.python.org/installing/) tool: Standards-Version: 3.9.6 Build-Depends: python (>= 2.6.6-3), debhelper (>= 9) Package-List: testdeb - Checksums-Sha1: f250ac0a426b31df24fc2c98050f4fab90e456cd 280 - testdeb_0.0.0.orig.tar.gz + Checksums-Sha1: + f250ac0a426b31df24fc2c98050f4fab90e456cd 280 testdeb_0.0.0.orig.tar.gz cb3474ff94053018957ebcf1d8a2b45f75dda449 232 testdeb_0.0.0-1.debian.tar.xz - Checksums-Sha256: aa57ba8f29840383f5a96c5c8f166a9e6da7a484151938643ce2618e82bfeea7 280 - testdeb_0.0.0.orig.tar.gz - 1ddb2a7336a99bc1d203f3ddb59f6fa2d298e90cb3e59cccbe0c84e359979858 232 - testdeb_0.0.0-1.debian.tar.xz - Files: 142ca7334ed1f70302b4504566e0c233 280 testdeb_0.0.0.orig.tar.gz + 80cd7b01014a269d445c63b037b885d6002cf533 841 testdeb_0.0.0.dsc + Checksums-Sha256: + aa57ba8f29840383f5a96c5c8f166a9e6da7a484151938643ce2618e82bfeea7 280 testdeb_0.0.0.orig.tar.gz + 1ddb2a7336a99bc1d203f3ddb59f6fa2d298e90cb3e59cccbe0c84e359979858 232 testdeb_0.0.0-1.debian.tar.xz + b5ad1591349eb48db65e6865be506ad7dbd21931902a71addee5b1db9ae1ac2a 841 testdeb_0.0.0.dsc + Files: + 142ca7334ed1f70302b4504566e0c233 280 testdeb_0.0.0.orig.tar.gz fc80e6e7f1c1a08b78a674aaee6c1548 232 testdeb_0.0.0-1.debian.tar.xz + 893d13a2ef13f7409c9521e8ab1dbccb 841 testdeb_0.0.0.dsc #### List the package source files from the dsc - >>> dsc.files - ['/home/n/testdeb_0.0.0.orig.tar.gz', 'home/n/testdeb_0.0.0-1.debian.tar.xz'] + >>> dsc.source_files + ['/tmp/testdeb_0.0.0.orig.tar.gz', + '/tmp/testdeb_0.0.0-1.debian.tar.xz', + '/tmp/testdeb_0.0.0.dsc' ] #### Validate that the package source files are present @@ -199,19 +226,24 @@ the [pip](https://packaging.python.org/installing/) tool: >>> bad = Dsc('testdeb_1.1.1-bad.dsc') >>> bad.missing_files - ['/home/n/testdeb_1.1.1.orig.tar.gz', '/home/n/testdeb_1.1.1-1.debian.tar.xz'] + ['/tmp/testdeb_1.1.1.orig.tar.gz', '/tmp/testdeb_1.1.1-1.debian.tar.xz'] >>> bad.all_files_present False >>> bad.validate() - pydpkg.DscMissingFileError: ['/home/n/testdeb_1.1.1.orig.tar.gz', '/home/n/testdeb_1.1.1-1.debian.tar.xz'] + pydpkg.DscMissingFileError: ['/tmp/testdeb_1.1.1.orig.tar.gz', '/tmp/testdeb_1.1.1-1.debian.tar.xz'] #### Inspect the source file checksums from the dsc >>> pp(dsc.checksums) - {'sha1': {'/home/n/testdeb_0.0.0-1.debian.tar.xz': 'cb3474ff94053018957ebcf1d8a2b45f75dda449', - '/home/n/testdeb_0.0.0.orig.tar.gz': 'f250ac0a426b31df24fc2c98050f4fab90e456cd'}, - 'sha256': {'/home/n/testdeb_0.0.0-1.debian.tar.xz': '1ddb2a7336a99bc1d203f3ddb59f6fa2d298e90cb3e59cccbe0c84e359979858', - '/home/n/testdeb_0.0.0.orig.tar.gz': 'aa57ba8f29840383f5a96c5c8f166a9e6da7a484151938643ce2618e82bfeea7'}} + {'md5': {'/tmp/testdeb_0.0.0-1.debian.tar.xz': 'fc80e6e7f1c1a08b78a674aaee6c1548', + '/tmp/testdeb_0.0.0.dsc': '893d13a2ef13f7409c9521e8ab1dbccb', + '/tmp/testdeb_0.0.0.orig.tar.gz': '142ca7334ed1f70302b4504566e0c233'}, + 'sha1': {'/tmp/testdeb_0.0.0-1.debian.tar.xz': 'cb3474ff94053018957ebcf1d8a2b45f75dda449', + '/tmp/testdeb_0.0.0.dsc': '80cd7b01014a269d445c63b037b885d6002cf533', + '/tmp/testdeb_0.0.0.orig.tar.gz': 'f250ac0a426b31df24fc2c98050f4fab90e456cd'}, + 'sha256': {'/tmp/testdeb_0.0.0-1.debian.tar.xz': '1ddb2a7336a99bc1d203f3ddb59f6fa2d298e90cb3e59cccbe0c84e359979858', + '/tmp/testdeb_0.0.0.dsc': 'b5ad1591349eb48db65e6865be506ad7dbd21931902a71addee5b1db9ae1ac2a', + '/tmp/testdeb_0.0.0.orig.tar.gz': 'aa57ba8f29840383f5a96c5c8f166a9e6da7a484151938643ce2618e82bfeea7'}} #### Validate that all source file checksums are correct @@ -224,8 +256,8 @@ the [pip](https://packaging.python.org/installing/) tool: >>> bad = Dsc('testdeb_0.0.0-badchecksums.dsc') >>> bad.corrected_checksums - {'sha256': defaultdict(None, {'/home/n/testdeb_0.0.0-1.debian.tar.xz': '1ddb2a7336a99bc1d203f3ddb59f6fa2d298e90cb3e59cccbe0c84e359979858', '/home/n/testdeb_0.0.0.orig.tar.gz': 'aa57ba8f29840383f5a96c5c8f166a9e6da7a484151938643ce2618e82bfeea7'}), 'sha1': defaultdict(None, {'/home/n/testdeb_0.0.0-1.debian.tar.xz': 'cb3474ff94053018957ebcf1d8a2b45f75dda449', '/home/n/testdeb_0.0.0.orig.tar.gz': 'f250ac0a426b31df24fc2c98050f4fab90e456cd'})} + {'sha256': defaultdict(None, {'/tmp/testdeb_0.0.0-1.debian.tar.xz': '1ddb2a7336a99bc1d203f3ddb59f6fa2d298e90cb3e59cccbe0c84e359979858', '/tmp/testdeb_0.0.0.orig.tar.gz': 'aa57ba8f29840383f5a96c5c8f166a9e6da7a484151938643ce2618e82bfeea7'}), 'sha1': defaultdict(None, {'/tmp/testdeb_0.0.0-1.debian.tar.xz': 'cb3474ff94053018957ebcf1d8a2b45f75dda449', '/tmp/testdeb_0.0.0.orig.tar.gz': 'f250ac0a426b31df24fc2c98050f4fab90e456cd'})} >>> bad.all_checksums_correct False >>> bad.validate() - pydpkg.DscBadChecksumsError: {'sha256': defaultdict(None, {'/home/n/testdeb_0.0.0-1.debian.tar.xz': '1ddb2a7336a99bc1d203f3ddb59f6fa2d298e90cb3e59cccbe0c84e359979858', '/home/n/testdeb_0.0.0.orig.tar.gz': 'aa57ba8f29840383f5a96c5c8f166a9e6da7a484151938643ce2618e82bfeea7'}), 'sha1': defaultdict(None, {'/home/n/testdeb_0.0.0-1.debian.tar.xz': 'cb3474ff94053018957ebcf1d8a2b45f75dda449', '/home/n/testdeb_0.0.0.orig.tar.gz': 'f250ac0a426b31df24fc2c98050f4fab90e456cd'})} + pydpkg.DscBadChecksumsError: {'sha256': defaultdict(None, {'/tmp/testdeb_0.0.0-1.debian.tar.xz': '1ddb2a7336a99bc1d203f3ddb59f6fa2d298e90cb3e59cccbe0c84e359979858', '/tmp/testdeb_0.0.0.orig.tar.gz': 'aa57ba8f29840383f5a96c5c8f166a9e6da7a484151938643ce2618e82bfeea7'}), 'sha1': defaultdict(None, {'/tmp/testdeb_0.0.0-1.debian.tar.xz': 'cb3474ff94053018957ebcf1d8a2b45f75dda449', '/tmp/testdeb_0.0.0.orig.tar.gz': 'f250ac0a426b31df24fc2c98050f4fab90e456cd'})} diff --git a/pydpkg/__init__.py b/pydpkg/__init__.py index 8257b9b..dd7c147 100644 --- a/pydpkg/__init__.py +++ b/pydpkg/__init__.py @@ -568,7 +568,7 @@ class Dsc(object): self._dirname = os.path.dirname(self.filename) self._log = logger or logging.getLogger(__name__) self._message = None - self._files = None + self._source_files = None self._sizes = None self._message_str = None self._checksums = None @@ -590,6 +590,9 @@ class Dsc(object): :returns: string :raises: AttributeError """ + self._log.debug('grabbing attr: %s', attr) + if attr in self.__dict__: + return self.__dict__[attr] # handle attributes with dashes :-( munged = attr.replace('_', '-') # beware: email.Message[nonexistent] returns None not KeyError @@ -606,6 +609,7 @@ class Dsc(object): :returns: string :raises: KeyError """ + self._log.debug('grabbing item: %s', item) try: return getattr(self, item) except AttributeError: @@ -624,6 +628,7 @@ class Dsc(object): @property def message(self): """Return an email.Message object containing the parsed dsc file""" + self._log.debug('accessing message property') if self._message is None: self._message = self._process_dsc_file() return self._message @@ -644,18 +649,18 @@ class Dsc(object): return self._pgp_message @property - def files(self): + def source_files(self): """Return a list of source files found in the dsc file""" - if self._files is None: - self._files = self._process_source_files() - return [x[0] for x in self._files] + if self._source_files is None: + self._source_files = self._process_source_files() + return [x[0] for x in self._source_files] @property def all_files_present(self): """Return true if all files listed in the dsc have been found""" - if self._files is None: - self._files = self._process_source_files() - return all([x[2] for x in self._files]) + if self._source_files is None: + self._source_files = self._process_source_files() + return all([x[2] for x in self._source_files]) @property def all_checksums_correct(self): @@ -673,16 +678,16 @@ class Dsc(object): @property def missing_files(self): """Return a list of all files from the dsc that we failed to find""" - if self._files is None: - self._files = self._process_source_files() - return [x[0] for x in self._files if x[2] is False] + if self._source_files is None: + self._source_files = self._process_source_files() + return [x[0] for x in self._source_files if x[2] is False] @property def sizes(self): """Return a list of source files found in the dsc file""" - if self._files is None: - self._files = self._process_source_files() - return dict([(x[0], x[1]) for x in self._files]) + if self._source_files is None: + self._source_files = self._process_source_files() + return dict([(x[0], x[1]) for x in self._source_files]) @property def message_str(self): @@ -706,7 +711,7 @@ class Dsc(object): """Raise exceptions if files are missing or checksums are bad.""" if not self.all_files_present: raise DscMissingFileError( - [x[0] for x in self._files if not x[2]]) + [x[0] for x in self._source_files if not x[2]]) if not self.all_checksums_correct: raise DscBadChecksumsError(self.corrected_checksums) @@ -714,38 +719,83 @@ class Dsc(object): """Walk through the dsc message looking for any keys in the format 'Checksum-hashtype'. Return a nested dictionary in the form {hashtype: {filename: {digest}}}""" + self._log.debug('process_checksums()') sums = {} for key in self.message.keys(): if key.lower().startswith('checksums'): hashtype = key.split('-')[1].lower() - sums[hashtype] = {} - source = self.message[key] - for line in source.split('\n'): - if line: - digest, _, filename = line.strip().split(' ') - pathname = os.path.abspath( - os.path.join(self._dirname, filename)) - sums[hashtype][pathname] = digest + # grrrrrr debian :( :( :( + elif key.lower() == 'files': + hashtype = 'md5' + else: + continue + sums[hashtype] = {} + source = self.message[key] + for line in source.split('\n'): + if line: # grrr py3-- + digest, _, filename = line.strip().split(' ') + pathname = os.path.abspath( + os.path.join(self._dirname, filename)) + sums[hashtype][pathname] = digest return sums + def _internalize_message(self, msg): + """Ugh: the dsc message body may not include a Files or + Checksums-foo entry for _itself_, which makes for hilarious + misadventures up the chain. So, pfeh, we add it.""" + self._log.debug('internalize_message()') + base = os.path.basename(self.filename) + size = os.path.getsize(self.filename) + for key, source in msg.items(): + self._log.debug('processing key: %s', key) + if key.lower().startswith('checksums'): + hashtype = key.split('-')[1].lower() + elif key.lower() == 'files': + hashtype = 'md5' + else: + continue + found = [] + for line in source.split('\n'): + if line: # grrr + found.append(line.strip().split(' ')) + files = [x[2] for x in found] + if base not in files: + self._log.debug('dsc file not found in %s: %s', key, base) + self._log.debug('getting hasher for %s', hashtype) + hasher = getattr(hashlib, hashtype)() + self._log.debug('hashing file') + with open(self.filename, 'rb') as fileobj: + # pylint: disable=cell-var-from-loop + for chunk in iter(lambda: fileobj.read(1024), b''): + hasher.update(chunk) + self._log.debug('completed hashing file') + self._log.debug('got %s digest: %s', + hashtype, hasher.hexdigest()) + newline = '\n {0} {1} {2}'.format( + hasher.hexdigest(), size, base) + self._log.debug('new line: %s', newline) + msg.replace_header(key, msg[key] + newline) + return msg + def _process_dsc_file(self): """Extract the dsc message from a file: parse the dsc body and return an email.Message object. Attempt to extract the RFC822 message from an OpenPGP message if necessary.""" + self._log.debug('process_dsc_file()') if not self.filename.endswith('.dsc'): - self._log.warning( + self._log.debug( 'File %s does not appear to be a dsc file; pressing ' 'on but we may experience some turbulence and possibly ' 'explode.', self.filename) try: self._pgp_message = pgpy.PGPMessage.from_file(self.filename) + self._log.debug('Found pgp signed message') msg = message_from_string(self._pgp_message.message) except TypeError as ex: self._log.exception(ex) self._log.fatal( 'dsc file %s has a corrupt signature: %s', self.filename, ex) raise DscBadSignatureError - # '%s has a corrupt signature' % self.filename) except IOError as ex: self._log.fatal('Could not read dsc file "%s": %s', self.filename, ex) @@ -755,6 +805,7 @@ class Dsc(object): self.filename, ex) with open(self.filename) as fileobj: msg = message_from_file(fileobj) + msg = self._internalize_message(msg) return msg def _process_source_files(self): @@ -768,6 +819,7 @@ class Dsc(object): Also extract the file size from the message lines and fill out the _files dictionary. """ + self._log.debug('process_source_files()') filenames = [] try: files = self.message['Files'] @@ -789,6 +841,7 @@ class Dsc(object): dsc file. Check each in turn. If any checksum is invalid, append the correct checksum to a similarly structured dict and return them all at the end.""" + self._log.debug('validate_checksums()') bad_hashes = defaultdict(lambda: defaultdict(None)) for hashtype, filenames in six.iteritems(self.checksums): for filename, digest in six.iteritems(filenames): diff --git a/setup.py b/setup.py index afa353f..0b26c3d 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ from distutils.core import setup -__VERSION__ = '1.3.0' +__VERSION__ = '1.3.1' setup( name='pydpkg', diff --git a/tests/test_dsc.py b/tests/test_dsc.py index 232a4ed..869275a 100644 --- a/tests/test_dsc.py +++ b/tests/test_dsc.py @@ -5,7 +5,11 @@ import unittest import pytest from email.message import Message -from pydpkg import Dsc, DscMissingFileError, DscBadSignatureError, DscBadChecksumsError +from pydpkg import Dsc +from pydpkg import DscMissingFileError +from pydpkg import DscBadSignatureError +from pydpkg import DscBadChecksumsError + from pgpy import PGPMessage @@ -17,12 +21,14 @@ TEST_BAD_CHECKSUMS_FILE = 'testdeb_0.0.0-badchecksums.dsc' class DscTest(unittest.TestCase): + def setUp(self): - goodfile = os.path.join(os.path.dirname(__file__), TEST_DSC_FILE) - signed = os.path.join(os.path.dirname(__file__), TEST_SIGNED_DSC_FILE) - badfile = os.path.join(os.path.dirname(__file__), TEST_BAD_DSC_FILE) - badsigned = os.path.join(os.path.dirname(__file__), TEST_BAD_SIGNED_FILE) - badchecksums = os.path.join(os.path.dirname(__file__), TEST_BAD_CHECKSUMS_FILE) + self.dirn = os.path.dirname(__file__) + goodfile = os.path.join(self.dirn, TEST_DSC_FILE) + signed = os.path.join(self.dirn, TEST_SIGNED_DSC_FILE) + badfile = os.path.join(self.dirn, TEST_BAD_DSC_FILE) + badsigned = os.path.join(self.dirn, TEST_BAD_SIGNED_FILE) + badchecksums = os.path.join(self.dirn, TEST_BAD_CHECKSUMS_FILE) self.good = Dsc(goodfile) self.signed = Dsc(signed) self.bad = Dsc(badfile) @@ -50,23 +56,19 @@ class DscTest(unittest.TestCase): def test_message(self): self.assertIsInstance(self.good.message, type(Message())) - def test_found_files(self): + def test_found_source_files(self): self.assertEqual( - self.good.files, - [os.path.join(os.path.dirname(__file__), - 'testdeb_0.0.0.orig.tar.gz'), - os.path.join(os.path.dirname(__file__), - 'testdeb_0.0.0-1.debian.tar.xz')] - ) + self.good.source_files, + [os.path.join(self.dirn, 'testdeb_0.0.0.orig.tar.gz'), + os.path.join(self.dirn, 'testdeb_0.0.0-1.debian.tar.xz'), + os.path.join(self.dirn, 'testdeb_0.0.0.dsc')]) def test_missing_files(self): self.assertEqual(True, self.good.all_files_present) self.assertEqual(False, self.bad.all_files_present) self.assertEqual( - [os.path.join(os.path.dirname(__file__), - 'testdeb_1.1.1.orig.tar.gz'), - os.path.join(os.path.dirname(__file__), - 'testdeb_1.1.1-1.debian.tar.xz')], + [os.path.join(self.dirn, 'testdeb_1.1.1.orig.tar.gz'), + os.path.join(self.dirn, 'testdeb_1.1.1-1.debian.tar.xz')], self.bad.missing_files) with pytest.raises(DscMissingFileError): self.bad.validate() @@ -75,15 +77,58 @@ class DscTest(unittest.TestCase): self.assertEqual(None, self.good.pgp_message) self.assertEqual(self.signed.source, 'testdeb') with pytest.raises(DscBadSignatureError): - self.badsigned.files + self.badsigned.source_files self.assertIsInstance(self.signed.pgp_message, PGPMessage) + def test_parse_checksums(self): + xz = os.path.join(self.dirn, 'testdeb_0.0.0-1.debian.tar.xz') + gz = os.path.join(self.dirn, 'testdeb_0.0.0.orig.tar.gz') + dsc = os.path.join(self.dirn, 'testdeb_0.0.0.dsc') + self.assertEqual( + self.good.checksums, + {'md5': {xz: 'fc80e6e7f1c1a08b78a674aaee6c1548', + dsc: '893d13a2ef13f7409c9521e8ab1dbccb', + gz: '142ca7334ed1f70302b4504566e0c233'}, + 'sha1': {xz: 'cb3474ff94053018957ebcf1d8a2b45f75dda449', + dsc: '80cd7b01014a269d445c63b037b885d6002cf533', + gz: 'f250ac0a426b31df24fc2c98050f4fab90e456cd'}, + 'sha256': { + xz: '1ddb2a7336a99bc1d203f3ddb59f6fa2d298e90cb3e59cccbe0c84e359979858', + dsc: 'b5ad1591349eb48db65e6865be506ad7dbd21931902a71addee5b1db9ae1ac2a', + gz: 'aa57ba8f29840383f5a96c5c8f166a9e6da7a484151938643ce2618e82bfeea7'}}) + def test_checksum_validation(self): self.assertEqual(True, self.good.all_checksums_correct) self.assertEqual(False, self.badchecksums.all_checksums_correct) with pytest.raises(DscBadChecksumsError): self.badchecksums.validate() + def test_message_internalization(self): + self.maxDiff = None + files = """142ca7334ed1f70302b4504566e0c233 280 testdeb_0.0.0.orig.tar.gz + fc80e6e7f1c1a08b78a674aaee6c1548 232 testdeb_0.0.0-1.debian.tar.xz + 893d13a2ef13f7409c9521e8ab1dbccb 841 testdeb_0.0.0.dsc""" + sha_1 = """f250ac0a426b31df24fc2c98050f4fab90e456cd 280 testdeb_0.0.0.orig.tar.gz + cb3474ff94053018957ebcf1d8a2b45f75dda449 232 testdeb_0.0.0-1.debian.tar.xz + 80cd7b01014a269d445c63b037b885d6002cf533 841 testdeb_0.0.0.dsc""" + sha_256 = """aa57ba8f29840383f5a96c5c8f166a9e6da7a484151938643ce2618e82bfeea7 280 testdeb_0.0.0.orig.tar.gz + 1ddb2a7336a99bc1d203f3ddb59f6fa2d298e90cb3e59cccbe0c84e359979858 232 testdeb_0.0.0-1.debian.tar.xz + b5ad1591349eb48db65e6865be506ad7dbd21931902a71addee5b1db9ae1ac2a 841 testdeb_0.0.0.dsc""" + self.assertEqual( + # gah. the py2 and py3 email.Message implementations appear to + # disagree on whether retreived multiline header strings will start + # with a newline :( :( :( + self.good.message['Files'].strip(), + files) + self.assertEqual( + # ibid. + self.good.message['checksums-sha1'].strip(), + sha_1) + self.assertEqual( + # op. cit. + self.good.message['checksums-sha256'].strip(), + sha_256) + if __name__ == "__main__": suite = unittest.TestLoader().loadTestsFromTestCase(DscTest)