import re
+from regexes import re_verwithext
+from dak_exceptions import UnknownFormatError
+
srcformats = []
+def get_format_from_string(txt):
+ """
+ Returns the SourceFormat class that corresponds to the specified .changes
+ Format value. If the string does not match any class, UnknownFormatError
+ is raised.
+ """
+
+ for format in srcformats:
+ if format.re_format.match(txt):
+ return format
+
+ raise UnknownFormatError, "Unknown format %r" % txt
+
+def parse_format(txt):
+ """
+ Parse a .changes Format string into a tuple representation for easy
+ comparison.
+
+ >>> parse_format('1.0')
+ (1, 0)
+ >>> parse_format('8.4 (hardy)')
+ (8, 4, 'hardy')
+
+ If the format doesn't match these forms, raises UnknownFormatError.
+ """
+
+ format = re_verwithext.search(txt)
+
+ if format is None:
+ raise UnknownFormatError, txt
+
+ format = format.groups()
+
+ if format[1] is None:
+ format = int(float(format[0])), 0, format[2]
+ else:
+ format = int(format[0]), int(format[1]), format[2]
+
+ if format[2] is None:
+ format = format[:2]
+
+ return format
+
class SourceFormat(type):
def __new__(cls, name, bases, attrs):
klass = super(SourceFormat, cls).__new__(cls, name, bases, attrs)
if has[key]:
yield "contains source files not allowed in format %s" % cls.name
+ @classmethod
+ def validate_format(cls, format, is_a_dsc=False, field='files'):
+ """
+ Raises UnknownFormatError if the specified format tuple is not valid for
+ this format (for example, the format (1, 0) is not valid for the
+ "3.0 (quilt)" format). Return value is undefined in all other cases.
+ """
+ pass
+
class FormatOne(SourceFormat):
__metaclass__ = SourceFormat
for msg in super(FormatOne, cls).reject_msgs(has):
yield msg
+ @classmethod
+ def validate_format(cls, format, is_a_dsc=False, field='files'):
+ msg = "Invalid format %s definition: %r" % (cls.name, format)
+
+ if is_a_dsc:
+ if format != (1, 0):
+ raise UnknownFormatError, msg
+ else:
+ if (format < (1,5) or format > (1,8)):
+ raise UnknownFormatError, msg
+ if field != "files" and format < (1,8):
+ raise UnknownFormatError, msg
+
class FormatThree(SourceFormat):
__metaclass__ = SourceFormat
requires = ('native_tar',)
disallowed = ('orig_tar', 'debian_diff', 'debian_tar', 'more_orig_tar')
+ @classmethod
+ def validate_format(cls, format, **kwargs):
+ if format != (3, 0, 'native'):
+ raise UnknownFormatError, "Invalid format %s definition: %r" % \
+ (cls.name, format)
+
class FormatThreeQuilt(SourceFormat):
__metaclass__ = SourceFormat
requires = ('orig_tar', 'debian_tar')
disallowed = ('debian_diff', 'native_tar')
+
+ @classmethod
+ def validate_format(cls, format, **kwargs):
+ if format != (3, 0, 'quilt'):
+ raise UnknownFormatError, "Invalid format %s definition: %r" % \
+ (cls.name, format)
from dak_exceptions import *
from textutils import fix_maintainer
from regexes import re_html_escaping, html_escaping, re_single_line_field, \
- re_multi_line_field, re_srchasver, re_verwithext, \
- re_taint_free, re_gpg_uid, re_re_mark, \
- re_whitespace_comment, re_issource
+ re_multi_line_field, re_srchasver, re_taint_free, \
+ re_gpg_uid, re_re_mark, re_whitespace_comment, re_issource
-from srcformats import srcformats
+from srcformats import get_format_from_string
from collections import defaultdict
################################################################################
rejmsg.append("%s: lists multiple %s" % (dsc_filename, file_type))
# Source format specific tests
- for format in srcformats:
- if format.re_format.match(dsc['format']):
- rejmsg.extend([
- '%s: %s' % (dsc_filename, x) for x in format.reject_msgs(has)
- ])
- break
+ try:
+ format = get_format_from_string(dsc['format'])
+ rejmsg.extend([
+ '%s: %s' % (dsc_filename, x) for x in format.reject_msgs(has)
+ ])
+
+ except UnknownFormatError:
+ # Not an error here for now
+ pass
return rejmsg
if not changes.has_key(field):
raise NoFilesFieldError
- # Make sure we recognise the format of the Files: field
- format = re_verwithext.search(changes.get("format", "0.0"))
- if not format:
- raise UnknownFormatError, "%s" % (changes.get("format","0.0"))
-
- format = format.groups()
- if format[1] == None:
- format = int(float(format[0])), 0, format[2]
- else:
- format = int(format[0]), int(format[1]), format[2]
- if format[2] == None:
- format = format[:2]
-
- if is_a_dsc:
- # format = (0,0) are missing format headers of which we still
- # have some in the archive.
- if format != (1,0) and format != (0,0) and \
- format != (3,0,"quilt") and format != (3,0,"native"):
- raise UnknownFormatError, "%s" % (changes.get("format","0.0"))
- else:
- if (format < (1,5) or format > (1,8)):
- raise UnknownFormatError, "%s" % (changes.get("format","0.0"))
- if field != "files" and format < (1,8):
- raise UnknownFormatError, "%s" % (changes.get("format","0.0"))
+ # Get SourceFormat object for this Format and validate it
+ format = get_format_from_string(changes.get['format'])
+ format.validate_format(is_a_dsc=is_a_dsc, field=field)
includes_section = (not is_a_dsc) and field == "files"
from collections import defaultdict
from daklib import srcformats
+from daklib.dak_exceptions import UnknownFormatError
class SourceFormatTestCase(unittest.TestCase):
def get_rejects(self, has_vars):
'native_tar': 1,
})
+##
+
+class ParseFormatTestCase(unittest.TestCase):
+ def assertParse(self, format, expected):
+ self.assertEqual(srcformats.parse_format(format), expected)
+
+ def assertParseFail(self, format):
+ self.assertRaises(
+ UnknownFormatError,
+ lambda: srcformats.parse_format(format)
+ )
+
+ def testParse(self):
+ self.assertParse('1.0', (1, 0))
+
+ def testEmpty(self):
+ self.assertParseFail('')
+ self.assertParseFail(' ')
+ self.assertParseFail(' ')
+
+ def textText(self):
+ self.assertParse('1.2 (three)', (1, 2, 'three'))
+ self.assertParseFail('0.0 ()')
+
+class ValidateFormatTestCase(unittest.TestCase):
+ def assertValid(self, format, **kwargs):
+ kwargs['is_a_dsc'] = kwargs.get('is_a_dsc', True)
+ self.fmt.validate_format(format, **kwargs)
+
+ def assertInvalid(self, *args, **kwargs):
+ self.assertRaises(
+ UnknownFormatError,
+ lambda: self.assertValid(*args, **kwargs),
+ )
+
+class ValidateFormatOneTestCase(ValidateFormatTestCase):
+ fmt = srcformats.FormatOne
+
+ def testValid(self):
+ self.assertValid((1, 0))
+
+ def testInvalid(self):
+ self.assertInvalid((0, 1))
+ self.assertInvalid((3, 0, 'quilt'))
+
+ ##
+
+ def testBinary(self):
+ self.assertValid((1, 5), is_a_dsc=False)
+ self.assertInvalid((1, 0), is_a_dsc=False)
+
+ def testRange(self):
+ self.assertInvalid((1, 3), is_a_dsc=False)
+ self.assertValid((1, 5), is_a_dsc=False)
+ self.assertValid((1, 8), is_a_dsc=False)
+ self.assertInvalid((1, 9), is_a_dsc=False)
+
+ def testFilesField(self):
+ self.assertInvalid((1, 7), is_a_dsc=False, field='notfiles')
+ self.assertValid((1, 8), is_a_dsc=False, field='notfiles')
+
+class ValidateFormatThreeTestCase(ValidateFormatTestCase):
+ fmt = srcformats.FormatThree
+
+ def testValid(self):
+ self.assertValid((3, 0, 'native'))
+
+ def testInvalid(self):
+ self.assertInvalid((1, 0))
+ self.assertInvalid((0, 0))
+ self.assertInvalid((3, 0, 'quilt'))
+
+class ValidateFormatThreeQuiltTestCase(ValidateFormatTestCase):
+ fmt = srcformats.FormatThreeQuilt
+
+ def testValid(self):
+ self.assertValid((3, 0, 'quilt'))
+
+ def testInvalid(self):
+ self.assertInvalid((1, 0))
+ self.assertInvalid((0, 0))
+ self.assertInvalid((3, 0, 'native'))
+
+class FormatFromStringTestCase(unittest.TestCase):
+ def assertFormat(self, txt, klass):
+ self.assertEqual(srcformats.get_format_from_string(txt), klass)
+
+ def assertInvalid(self, txt):
+ self.assertRaises(
+ UnknownFormatError,
+ lambda: srcformats.get_format_from_string(txt),
+ )
+
+ def testFormats(self):
+ self.assertFormat('1.0', srcformats.FormatOne)
+ self.assertFormat('3.0 (native)', srcformats.FormatThree)
+ self.assertFormat('3.0 (quilt)', srcformats.FormatThreeQuilt)
+
+ def testInvalidFormats(self):
+ self.assertInvalid('')
+ self.assertInvalid('.')
+ self.assertInvalid('3.0 (cvs)')
+ self.assertInvalid(' 1.0 ')
+ self.assertInvalid('8.4 (hardy)')
+
if __name__ == '__main__':
unittest.main()