diff options
author | Lars Wirzenius <lars.wirzenius@codethink.co.uk> | 2012-05-11 13:52:42 +0100 |
---|---|---|
committer | Lars Wirzenius <lars.wirzenius@codethink.co.uk> | 2012-05-11 13:52:42 +0100 |
commit | e5fefead3a643085055e8419f330e5756268013c (patch) | |
tree | 51297ba37b8dcc3031da8829d74894ee13f600ba /morphlib | |
parent | 8a02512e83750f6f057b0e0bb21d4d54ee619c10 (diff) | |
download | morph-e5fefead3a643085055e8419f330e5756268013c.tar.gz |
Fix stringifying morphologies to be deterministic
Previously we were stringifying complex values (lists, dicts) by
using whatever Python produces, but different runs and versions of
Python may convert them differently, particularly dicts. We now do
it manually.
Diffstat (limited to 'morphlib')
-rw-r--r-- | morphlib/cachekeycomputer.py | 22 | ||||
-rw-r--r-- | morphlib/cachekeycomputer_tests.py | 14 |
2 files changed, 32 insertions, 4 deletions
diff --git a/morphlib/cachekeycomputer.py b/morphlib/cachekeycomputer.py index a1c2ebd6..6ae2b107 100644 --- a/morphlib/cachekeycomputer.py +++ b/morphlib/cachekeycomputer.py @@ -89,12 +89,26 @@ class CacheKeyComputer(object): if kind == 'chunk': keys['ref'] = artifact.source.sha1 elif kind in ('system', 'stratum'): - checksum = hashlib.sha1() morphology = artifact.source.morphology - getkey = lambda s: [ord(c) for c in s] - for key in sorted(morphology.keys(), key=getkey): - checksum.update('%s=%s' % (key, morphology[key])) + le_dict = dict((k,morphology[k]) for k in morphology.keys()) + checksum = hashlib.sha1(self._stringify(le_dict)) keys['morphology-sha1'] = checksum.hexdigest() return keys + def _stringify(self, value): + if type(value) in [str, unicode, int]: + return str(value) + elif value is None: + return '' + elif type(value) is list: + return '[' + ','.join(self._stringify(x) for x in value) + ']' + elif type(value) is dict: + keys = value.keys() + keys.sort(key=lambda s: [ord(c) for c in s]) + pairs = ['%s:%s' % (self._stringify(k), self._stringify(value[k])) + for k in keys] + return '{' + ','.join(pairs) + '}' + else: # pragma: no cover + raise NotImplementedError( + 'type %s is not stringified' % type(value)) diff --git a/morphlib/cachekeycomputer_tests.py b/morphlib/cachekeycomputer_tests.py index 7fc47370..32aef02e 100644 --- a/morphlib/cachekeycomputer_tests.py +++ b/morphlib/cachekeycomputer_tests.py @@ -166,3 +166,17 @@ class CacheKeyComputerTests(unittest.TestCase): old_sha = self.ckc.compute_key(old_artifact) new_sha = self.ckc.compute_key(new_artifact) self.assertEqual(old_sha, new_sha) + + def test_stringifies_string(self): + self.assertEqual(self.ckc._stringify('foo'), 'foo') + + def test_stringifies_integer(self): + self.assertEqual(self.ckc._stringify(12765), '12765') + + def test_stringifies_dict(self): + self.assertEqual(self.ckc._stringify({'foo': 'bar', 'yo': 'foobar' }), + '{foo:bar,yo:foobar}') + + def test_stringifies_list(self): + self.assertEqual(self.ckc._stringify(['foo', 'bar']), '[foo,bar]') + |