diff options
Diffstat (limited to 'morphlib')
-rw-r--r-- | morphlib/morph2.py | 62 | ||||
-rw-r--r-- | morphlib/morph2_tests.py | 76 | ||||
-rw-r--r-- | morphlib/plugins/branch_and_merge_plugin.py | 23 |
3 files changed, 128 insertions, 33 deletions
diff --git a/morphlib/morph2.py b/morphlib/morph2.py index d99e4a9e..0eca6fed 100644 --- a/morphlib/morph2.py +++ b/morphlib/morph2.py @@ -14,7 +14,10 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +import collections +import copy import json +import re class Morphology(object): @@ -50,8 +53,15 @@ class Morphology(object): ] } + @staticmethod + def _order_keys(pairs): + result = collections.OrderedDict() + for k,v in pairs: + result[k] = v + return result + def __init__(self, text): - self._dict = json.loads(text) + self._dict = json.loads(text, object_pairs_hook=self._order_keys) self._set_defaults() self._validate_children() @@ -105,19 +115,8 @@ class Morphology(object): if 'disk-size' in self: size = self['disk-size'] - if isinstance(size, basestring): - size = size.lower() - if size.endswith('g'): - size = int(size[:-1]) * 1024 ** 3 - elif size.endswith('m'): # pragma: no cover - size = int(size[:-1]) * 1024 ** 2 - elif size.endswith('k'): # pragma: no cover - size = int(size[:-1]) * 1024 - else: # pragma: no cover - size = int(size) - else: # pragma: no cover - size = int(size) - self._dict['disk-size'] = size + self._dict['_disk-size'] = size + self._dict['disk-size'] = self._parse_size(size) for name, value in self.static_defaults[self['kind']]: if name not in self._dict: @@ -134,3 +133,38 @@ class Morphology(object): source['morph'] = source['name'] if 'build-depends' not in source: source['build-depends'] = None + + def _parse_size(self, size): + if isinstance(size, basestring): + size = size.lower() + if size.endswith('g'): + return int(size[:-1]) * 1024 ** 3 + elif size.endswith('m'): # pragma: no cover + return int(size[:-1]) * 1024 ** 2 + elif size.endswith('k'): # pragma: no cover + return int(size[:-1]) * 1024 + return int(size) + + def write_to_file(self, f): + # Recreate dict without the empty default values, with a few kind + # specific hacks to try and edit standard morphologies as + # non-destructively as possible + as_dict = collections.OrderedDict() + for key in self.keys(): + if self['kind'] == 'stratum' and key == 'chunks': + value = copy.copy(self[key]) + for chunk in value: + if chunk["morph"] == chunk["name"]: + del chunk["morph"] + if self['kind'] == 'system' and key == 'disk-size': + # Use human-readable value (assumes we never programmatically + # change this value within morph) + value = self['_disk-size'] + else: + value = self[key] + if value and key[0] != '_': + as_dict[key] = value + text = json.dumps(as_dict, indent=4) + text = re.sub(" \n", "\n", text) + f.write(text) + f.write('\n') diff --git a/morphlib/morph2_tests.py b/morphlib/morph2_tests.py index 60917537..142b5949 100644 --- a/morphlib/morph2_tests.py +++ b/morphlib/morph2_tests.py @@ -14,6 +14,7 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +import StringIO import unittest from morphlib.morph2 import Morphology @@ -197,3 +198,78 @@ class MorphologyTests(unittest.TestCase): self.assertRaises(ValueError, Morphology, text) + + def test_writing_preserves_field_order(self): + text = '''{ + "kind": "system", + "disk-size": 1073741824, + "description": "Some text", + "arch": "x86_64", + "system-kind": "syslinux-disk", + "strata": [ + { + "morph": "foundation", + "repo": "morphs", + "ref": "ref" + }, + { + "morph": "devel", + "repo": "morphs", + "ref": "ref" + } + ] +}''' + morphology = Morphology(text) + output = StringIO.StringIO() + morphology.write_to_file(output) + + text_lines = text.splitlines() + output_lines = output.getvalue().splitlines() + + # Verify that input and output are equal. + self.assertEqual(text_lines, output_lines) + + def test_writing_stratum_morphology_preserves_chunk_order(self): + text = '''{ + "kind": "stratum", + "chunks": [ + { + "name": "foo", + "repo": "morphs", + "ref": "ref", + "build-depends": [] + }, + { + "name": "bar", + "repo": "morphs", + "ref": "ref", + "build-depends": [] + } + ] +}''' + morphology = Morphology(text) + output = StringIO.StringIO() + morphology.write_to_file(output) + + text_lines = text.splitlines() + output_lines = output.getvalue().splitlines() + + # Verify that input and output are equal. + self.assertEqual(text_lines, output_lines) + + def test_writing_preserves_disk_size(self): + text = '''{ + "kind": "system", + "disk-size": "1g", + "arch": "x86_64", + "system-kind": "syslinux-disk" +}''' + morphology = Morphology(text) + output = StringIO.StringIO() + morphology.write_to_file(output) + + text_lines = text.splitlines() + output_lines = output.getvalue().splitlines() + + # Verify that in- and output are the same. + self.assertEqual(text_lines, output_lines) diff --git a/morphlib/plugins/branch_and_merge_plugin.py b/morphlib/plugins/branch_and_merge_plugin.py index 5e5ce0c1..d6485c2b 100644 --- a/morphlib/plugins/branch_and_merge_plugin.py +++ b/morphlib/plugins/branch_and_merge_plugin.py @@ -234,14 +234,9 @@ class BranchAndMergePlugin(cliapp.Plugin): filename = name else: filename = os.path.join(repo_dir, name) - as_dict = {} - for key in morphology.keys(): - value = morphology[key] - if value: - as_dict[key] = value + filename = os.path.join(repo_dir, '%s' % name) with morphlib.savefile.SaveFile(filename, 'w') as f: - json.dump(as_dict, fp=f, indent=4, sort_keys=True) - f.write('\n') + morphology.write_to_file(f) @staticmethod def get_edit_info(morphology_name, morphology, name, collection='strata'): @@ -258,17 +253,6 @@ class BranchAndMergePlugin(cliapp.Plugin): (name, morphology_name)) @staticmethod - def write_morphology(filename, morphology): - as_dict = {} - for key in morphology.keys(): - value = morphology[key] - if value: - as_dict[key] = value - with morphlib.savefile.SaveFile(filename, 'w') as f: - json.dump(as_dict, fp=f, indent=4, sort_keys=True) - f.write('\n') - - @staticmethod def convert_uri_to_path(uri): parts = urlparse.urlparse(uri) @@ -357,7 +341,8 @@ class BranchAndMergePlugin(cliapp.Plugin): repo = cache.get_repo(reponame) source['ref'], tree = repo.resolve_ref(ref) - self.write_morphology(filename, morph) + with morphlib.savefile.SaveFile(filename, 'w') as f: + morph.write_to_file(f) def init(self, args): '''Initialize a workspace directory.''' |