Merge pull request #7 from TheClimateCorporation/include-dsc-file

include dsc file and checksums in message
This commit is contained in:
memory 2017-06-23 09:19:45 -07:00 committed by GitHub
commit 0719ce4a5e
4 changed files with 193 additions and 63 deletions

View File

@ -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 <n@climate.com>', 'Binary': 'testdeb', 'Maintainer': 'Nathan J. Mehl <n@climate.com>', '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 <n@climate.com>',
'Package-List': 'testdeb',
'Source': 'testdeb',
'Standards-Version': '3.9.6',
'Uploaders': 'Nathan J. Mehl <n@climate.com>',
'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'})}

View File

@ -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):

View File

@ -1,6 +1,6 @@
from distutils.core import setup
__VERSION__ = '1.3.0'
__VERSION__ = '1.3.1'
setup(
name='pydpkg',

View File

@ -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)