From 074d06528758774a64559e1da480464b5d1bb74b Mon Sep 17 00:00:00 2001 From: Sam Thursfield Date: Fri, 10 Jan 2014 15:58:43 +0000 Subject: Move morphloader errors into separate module for easy access We can now import the errors into the local namespace of any module we want (such as the unit tests) which saves having to use 40-character identifiers to refer to the exceptions. --- morphlib/morphloader.py | 144 +----------------------------------- morphlib/morphloader_errors.py | 163 +++++++++++++++++++++++++++++++++++++++++ morphlib/morphloader_tests.py | 74 +++++++++---------- without-test-modules | 2 + 4 files changed, 200 insertions(+), 183 deletions(-) create mode 100644 morphlib/morphloader_errors.py diff --git a/morphlib/morphloader.py b/morphlib/morphloader.py index cc293139..bd968fe8 100644 --- a/morphlib/morphloader.py +++ b/morphlib/morphloader.py @@ -22,149 +22,7 @@ import yaml import morphlib - -class MorphologySyntaxError(morphlib.Error): - - def __init__(self, morphology): - self.msg = 'Syntax error in morphology %s' % morphology - - -class NotADictionaryError(morphlib.Error): - - def __init__(self, morphology): - self.msg = 'Not a dictionary: morphology %s' % morphology - - -class UnknownKindError(morphlib.Error): - - def __init__(self, kind, morphology): - self.msg = ( - 'Unknown kind %s in morphology %s' % (kind, morphology)) - - -class MissingFieldError(morphlib.Error): - - def __init__(self, field, morphology_name): - self.field = field - self.morphology_name = morphology_name - self.msg = ( - 'Missing field %s from morphology %s' % (field, morphology_name)) - - -class InvalidFieldError(morphlib.Error): - - def __init__(self, field, morphology_name): - self.field = field - self.morphology_name = morphology_name - self.msg = ( - 'Field %s not allowed in morphology %s' % (field, morphology_name)) - - -class InvalidTypeError(morphlib.Error): - - def __init__(self, field, expected, actual, morphology_name): - self.field = field - self.expected = expected - self.actual = actual - self.morphology_name = morphology_name - self.msg = ( - 'Field %s expected type %s, got %s in morphology %s' % - (field, expected, actual, morphology_name)) - - -class ObsoleteFieldsError(morphlib.Error): - - def __init__(self, fields, morphology): - self.msg = ( - 'Morphology %s uses obsolete fields: %s' % - (morphology, ' '.join(fields))) - -class UnknownArchitectureError(morphlib.Error): - - def __init__(self, arch, morphology): - self.msg = ( - 'Unknown architecture %s in morphology %s' % (arch, morphology)) - - -class NoBuildDependenciesError(morphlib.Error): - - def __init__(self, stratum_name, chunk_name, morphology): - self.msg = ( - 'Stratum %s has no build dependencies for chunk %s in %s' % - (stratum_name, chunk_name, morphology)) - - -class NoStratumBuildDependenciesError(morphlib.Error): - - def __init__(self, stratum_name, morphology): - self.msg = ( - 'Stratum %s has no build dependencies in %s' % - (stratum_name, morphology)) - - -class EmptyStratumError(morphlib.Error): - - def __init__(self, stratum_name, morphology): - self.msg = ( - 'Stratum %s has no chunks in %s' % - (stratum_name, morphology)) - - -class DuplicateChunkError(morphlib.Error): - - def __init__(self, stratum_name, chunk_name): - self.stratum_name = stratum_name - self.chunk_name = chunk_name - morphlib.Error.__init__( - self, 'Duplicate chunk %(chunk_name)s '\ - 'in stratum %(stratum_name)s' % locals()) - - -class SystemStrataNotListError(morphlib.Error): - - def __init__(self, system_name, strata_type): - self.system_name = system_name - self.strata_type = strata_type - typename = strata_type.__name__ - morphlib.Error.__init__( - self, 'System %(system_name)s has the wrong type for its strata: '\ - '%(typename)s, expected list' % locals()) - -class DuplicateStratumError(morphlib.Error): - - def __init__(self, system_name, stratum_name): - self.system_name = system_name - self.stratum_name = stratum_name - morphlib.Error.__init__( - self, 'Duplicate stratum %(stratum_name)s '\ - 'in system %(system_name)s' % locals()) - - -class SystemStratumSpecsNotMappingError(morphlib.Error): - - def __init__(self, system_name, strata): - self.system_name = system_name - self.strata = strata - morphlib.Error.__init__( - self, 'System %(system_name)s has stratum specs '\ - 'that are not mappings.' % locals()) - - -class EmptySystemError(morphlib.Error): - - def __init__(self, system_name): - morphlib.Error.__init__( - self, 'System %(system_name)s has no strata.' % locals()) - - -class MultipleValidationErrors(morphlib.Error): - - def __init__(self, name, errors): - self.name = name - self.errors = errors - self.msg = 'Multiple errors when validating %(name)s:' - for error in errors: - self.msg += ('\t' + str(error)) +from morphlib.morphloader_errors import * class MorphologyLoader(object): diff --git a/morphlib/morphloader_errors.py b/morphlib/morphloader_errors.py new file mode 100644 index 00000000..d456cc9e --- /dev/null +++ b/morphlib/morphloader_errors.py @@ -0,0 +1,163 @@ +# Copyright (C) 2013-2014 Codethink Limited +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# =*= License: GPL-2 =*= + + +import morphlib + + +class MorphologySyntaxError(morphlib.Error): + + def __init__(self, morphology): + self.msg = 'Syntax error in morphology %s' % morphology + + +class NotADictionaryError(morphlib.Error): + + def __init__(self, morphology): + self.msg = 'Not a dictionary: morphology %s' % morphology + + +class UnknownKindError(morphlib.Error): + + def __init__(self, kind, morphology): + self.msg = ( + 'Unknown kind %s in morphology %s' % (kind, morphology)) + + +class MissingFieldError(morphlib.Error): + + def __init__(self, field, morphology_name): + self.field = field + self.morphology_name = morphology_name + self.msg = ( + 'Missing field %s from morphology %s' % (field, morphology_name)) + + +class InvalidFieldError(morphlib.Error): + + def __init__(self, field, morphology_name): + self.field = field + self.morphology_name = morphology_name + self.msg = ( + 'Field %s not allowed in morphology %s' % (field, morphology_name)) + + +class InvalidTypeError(morphlib.Error): + + def __init__(self, field, expected, actual, morphology_name): + self.field = field + self.expected = expected + self.actual = actual + self.morphology_name = morphology_name + self.msg = ( + 'Field %s expected type %s, got %s in morphology %s' % + (field, expected, actual, morphology_name)) + + +class ObsoleteFieldsError(morphlib.Error): + + def __init__(self, fields, morphology): + self.msg = ( + 'Morphology %s uses obsolete fields: %s' % + (morphology, ' '.join(fields))) + +class UnknownArchitectureError(morphlib.Error): + + def __init__(self, arch, morphology): + self.msg = ( + 'Unknown architecture %s in morphology %s' % (arch, morphology)) + + +class NoBuildDependenciesError(morphlib.Error): + + def __init__(self, stratum_name, chunk_name, morphology): + self.msg = ( + 'Stratum %s has no build dependencies for chunk %s in %s' % + (stratum_name, chunk_name, morphology)) + + +class NoStratumBuildDependenciesError(morphlib.Error): + + def __init__(self, stratum_name, morphology): + self.msg = ( + 'Stratum %s has no build dependencies in %s' % + (stratum_name, morphology)) + + +class EmptyStratumError(morphlib.Error): + + def __init__(self, stratum_name, morphology): + self.msg = ( + 'Stratum %s has no chunks in %s' % + (stratum_name, morphology)) + + +class DuplicateChunkError(morphlib.Error): + + def __init__(self, stratum_name, chunk_name): + self.stratum_name = stratum_name + self.chunk_name = chunk_name + morphlib.Error.__init__( + self, 'Duplicate chunk %(chunk_name)s '\ + 'in stratum %(stratum_name)s' % locals()) + + +class SystemStrataNotListError(morphlib.Error): + + def __init__(self, system_name, strata_type): + self.system_name = system_name + self.strata_type = strata_type + typename = strata_type.__name__ + morphlib.Error.__init__( + self, 'System %(system_name)s has the wrong type for its strata: '\ + '%(typename)s, expected list' % locals()) + +class DuplicateStratumError(morphlib.Error): + + def __init__(self, system_name, stratum_name): + self.system_name = system_name + self.stratum_name = stratum_name + morphlib.Error.__init__( + self, 'Duplicate stratum %(stratum_name)s '\ + 'in system %(system_name)s' % locals()) + + +class SystemStratumSpecsNotMappingError(morphlib.Error): + + def __init__(self, system_name, strata): + self.system_name = system_name + self.strata = strata + morphlib.Error.__init__( + self, 'System %(system_name)s has stratum specs '\ + 'that are not mappings.' % locals()) + + +class EmptySystemError(morphlib.Error): + + def __init__(self, system_name): + morphlib.Error.__init__( + self, 'System %(system_name)s has no strata.' % locals()) + + +class MultipleValidationErrors(morphlib.Error): + + def __init__(self, name, errors): + self.name = name + self.errors = errors + self.msg = 'Multiple errors when validating %(name)s:' + for error in errors: + self.msg += ('\t' + str(error)) diff --git a/morphlib/morphloader_tests.py b/morphlib/morphloader_tests.py index ee9b4c4c..b8ce2407 100644 --- a/morphlib/morphloader_tests.py +++ b/morphlib/morphloader_tests.py @@ -23,6 +23,8 @@ import unittest import morphlib +from morphlib.morphloader_errors import * + class MorphologyLoaderTests(unittest.TestCase): @@ -47,12 +49,12 @@ build-system: dummy def test_fails_to_parse_utter_garbage(self): self.assertRaises( - morphlib.morphloader.MorphologySyntaxError, + MorphologySyntaxError, self.loader.parse_morphology_text, ',,,', 'test') def test_fails_to_parse_non_dict(self): self.assertRaises( - morphlib.morphloader.NotADictionaryError, + NotADictionaryError, self.loader.parse_morphology_text, '- item1\n- item2\n', 'test') def test_fails_to_validate_dict_without_kind(self): @@ -60,14 +62,14 @@ build-system: dummy 'invalid': 'field', }) self.assertRaises( - morphlib.morphloader.MissingFieldError, self.loader.validate, m) + MissingFieldError, self.loader.validate, m) def test_fails_to_validate_chunk_with_no_fields(self): m = morphlib.morph3.Morphology({ 'kind': 'chunk', }) self.assertRaises( - morphlib.morphloader.MissingFieldError, self.loader.validate, m) + MissingFieldError, self.loader.validate, m) def chunk_morph(self, name='foo', **kwargs): '''Create an example chunk morphology''' @@ -97,7 +99,7 @@ build-system: dummy def test_fails_to_validate_chunk_with_invalid_field(self): m = self.chunk_morph(invalid='field') self.assertRaises( - morphlib.morphloader.InvalidFieldError, self.loader.validate, m) + InvalidFieldError, self.loader.validate, m) def test_validate_requires_products_list(self): m = self.chunk_morph( @@ -105,7 +107,7 @@ build-system: dummy 'foo-runtime': ['.'], 'foo-devel': ['.'], }) - with self.assertRaises(morphlib.morphloader.InvalidTypeError) as cm: + with self.assertRaises(InvalidTypeError) as cm: self.loader.validate(m) e = cm.exception self.assertEqual((e.field, e.expected, e.actual, e.morphology_name), @@ -116,7 +118,7 @@ build-system: dummy products={ 'foo-runtime', }) - with self.assertRaises(morphlib.morphloader.InvalidTypeError) as cm: + with self.assertRaises(InvalidTypeError) as cm: self.loader.validate(m) e = cm.exception self.assertEqual((e.field, e.expected, e.actual, e.morphology_name), @@ -130,20 +132,20 @@ build-system: dummy 'cludein': [], } ]) - with self.assertRaises(morphlib.morphloader.MultipleValidationErrors) \ + with self.assertRaises(MultipleValidationErrors) \ as cm: self.loader.validate(m) exs = cm.exception.errors self.assertEqual( sorted((type(ex), ex.field) for ex in exs), sorted(( - (morphlib.morphloader.MissingFieldError, + (MissingFieldError, 'products[0].artifact'), - (morphlib.morphloader.MissingFieldError, + (MissingFieldError, 'products[0].include'), - (morphlib.morphloader.InvalidFieldError, + (InvalidFieldError, 'products[0].cludein'), - (morphlib.morphloader.InvalidFieldError, + (InvalidFieldError, 'products[0].factiart'), )) ) @@ -156,7 +158,7 @@ build-system: dummy 'include': '.*', } ]) - with self.assertRaises(morphlib.morphloader.InvalidTypeError) as cm: + with self.assertRaises(InvalidTypeError) as cm: self.loader.validate(m) ex = cm.exception self.assertEqual(('products[0].include', list, str, 'foo'), @@ -173,7 +175,7 @@ build-system: dummy ] } ]) - with self.assertRaises(morphlib.morphloader.InvalidTypeError) as cm: + with self.assertRaises(InvalidTypeError) as cm: self.loader.validate(m) ex = cm.exception self.assertEqual(('products[0].include[0]', str, int, 'foo'), @@ -186,45 +188,45 @@ build-system: dummy 'kind': 'stratum', }) self.assertRaises( - morphlib.morphloader.MissingFieldError, self.loader.validate, m) + MissingFieldError, self.loader.validate, m) def test_fails_to_validate_stratum_with_invalid_field(self): m = self.stratum_morph(invalid='field') self.assertRaises( - morphlib.morphloader.InvalidFieldError, self.loader.validate, m) + InvalidFieldError, self.loader.validate, m) def test_fails_to_validate_system_with_obsolete_system_kind_field(self): m = self.system_morph(**{ 'system-kind': 'foo', }) self.assertRaises( - morphlib.morphloader.ObsoleteFieldsError, self.loader.validate, m) + ObsoleteFieldsError, self.loader.validate, m) def test_fails_to_validate_system_with_obsolete_disk_size_field(self): m = self.system_morph(**{ 'disk-size': 'over 9000', }) self.assertRaises( - morphlib.morphloader.ObsoleteFieldsError, self.loader.validate, m) + ObsoleteFieldsError, self.loader.validate, m) def test_fails_to_validate_system_with_no_fields(self): m = morphlib.morph3.Morphology({ 'kind': 'system', }) self.assertRaises( - morphlib.morphloader.MissingFieldError, self.loader.validate, m) + MissingFieldError, self.loader.validate, m) def test_fails_to_validate_system_with_invalid_field(self): m = self.system_morph(invalid='field') self.assertRaises( - morphlib.morphloader.InvalidFieldError, self.loader.validate, m) + InvalidFieldError, self.loader.validate, m) def test_fails_to_validate_morphology_with_unknown_kind(self): m = morphlib.morph3.Morphology({ 'kind': 'invalid', }) self.assertRaises( - morphlib.morphloader.UnknownKindError, self.loader.validate, m) + UnknownKindError, self.loader.validate, m) def test_validate_requires_unique_stratum_names_within_a_system(self): m = self.system_morph( @@ -240,7 +242,7 @@ build-system: dummy "ref": "ref" } ]) - self.assertRaises(morphlib.morphloader.DuplicateStratumError, + self.assertRaises(DuplicateStratumError, self.loader.validate, m) def test_validate_requires_unique_chunk_names_within_a_stratum(self): @@ -257,14 +259,13 @@ build-system: dummy "ref": "ref" } ]) - self.assertRaises(morphlib.morphloader.DuplicateChunkError, - self.loader.validate, m) + self.assertRaises( + DuplicateChunkError, self.loader.validate, m) def test_validate_requires_a_valid_architecture(self): m = self.system_morph(arch="blah") self.assertRaises( - morphlib.morphloader.UnknownArchitectureError, - self.loader.validate, m) + UnknownArchitectureError, self.loader.validate, m) def test_validate_normalises_architecture_armv7_to_armv7l(self): m = self.system_morph(arch="armv7") @@ -283,8 +284,7 @@ build-system: dummy } ]) self.assertRaises( - morphlib.morphloader.NoBuildDependenciesError, - self.loader.validate, m) + NoBuildDependenciesError, self.loader.validate, m) def test_validate_requires_build_deps_or_bootstrap_mode_for_strata(self): m = self.stratum_morph( @@ -297,8 +297,7 @@ build-system: dummy } ]) self.assertRaises( - morphlib.morphloader.NoStratumBuildDependenciesError, - self.loader.validate, m) + NoStratumBuildDependenciesError, self.loader.validate, m) m['build-depends'] = [ { @@ -324,8 +323,7 @@ build-system: dummy }, ]}) self.assertRaises( - morphlib.morphloader.EmptyStratumError, - self.loader.validate, m) + EmptyStratumError, self.loader.validate, m) def test_validate_requires_strata_in_system(self): m = morphlib.morph3.Morphology( @@ -333,14 +331,12 @@ build-system: dummy kind='system', arch='testarch') self.assertRaises( - morphlib.morphloader.MissingFieldError, - self.loader.validate, m) + MissingFieldError, self.loader.validate, m) def test_validate_requires_list_of_strata_in_system(self): for v in (None, {}): m = self.system_morph(strata=v) - with self.assertRaises( - morphlib.morphloader.SystemStrataNotListError) as cm: + with self.assertRaises(SystemStrataNotListError) as cm: self.loader.validate(m) self.assertEqual(cm.exception.strata_type, type(v)) @@ -348,13 +344,11 @@ build-system: dummy def test_validate_requires_non_empty_strata_in_system(self): m = self.system_morph(strata=[]) self.assertRaises( - morphlib.morphloader.EmptySystemError, - self.loader.validate, m) + EmptySystemError, self.loader.validate, m) def test_validate_requires_stratum_specs_in_system(self): m = self.system_morph(strata=["foo"]) - with self.assertRaises( - morphlib.morphloader.SystemStratumSpecsNotMappingError) as cm: + with self.assertRaises(SystemStratumSpecsNotMappingError) as cm: self.loader.validate(m) self.assertEqual(cm.exception.strata, ["foo"]) diff --git a/without-test-modules b/without-test-modules index 1f5bc872..4fc17925 100644 --- a/without-test-modules +++ b/without-test-modules @@ -31,3 +31,5 @@ morphlib/plugins/branch_and_merge_new_plugin.py morphlib/plugins/print_architecture_plugin.py # Not unit tested, since it needs a full system branch morphlib/buildbranch.py + +morphlib/morphloader_errors.py -- cgit v1.2.1