Author: ckauhaus
Date: Mon Dec 1 15:06:23 2008
New Revision: 7114
Log:
Re-added fixes code from r7105
Added:
gocept.infrastructure/feature_systemupgrade/util/fixes/
gocept.infrastructure/feature_systemupgrade/util/fixes/check (contents,
props changed)
gocept.infrastructure/feature_systemupgrade/util/fixes/db/
gocept.infrastructure/feature_systemupgrade/util/fixes/fix (contents,
props changed)
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/fix.py
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/fixapi.py
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/db/
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/db/one.py
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/db/two.py
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/db_broken/
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/db_broken/empty.py
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/db_empty/
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/db_failing/
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/db_failing/fix.py
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/db_non_converging/
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/db_non_converging/fix.py
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/test_fix.py
Added: gocept.infrastructure/feature_systemupgrade/util/fixes/check
==============================================================================
--- (empty file)
+++ gocept.infrastructure/feature_systemupgrade/util/fixes/check Mon Dec 1
15:06:23 2008
(at)(at) -0,0 +1 (at)(at)
+link fix
\ No newline at end of file
Added: gocept.infrastructure/feature_systemupgrade/util/fixes/fix
==============================================================================
--- (empty file)
+++ gocept.infrastructure/feature_systemupgrade/util/fixes/fix Mon Dec 1
15:06:23 2008
(at)(at) -0,0 +1,25 (at)(at)
+#!/bin/env python
+# Copyright (c) 2008 gocept gmbh & co. kg
+# See also LICENSE.txt
+
+import sys
+import os.path
+
+base = os.path.dirname(__file__)
+sys.path.append(os.path.join(base, 'lib'))
+import fix
+
+
+fixer = fix.Fixer(os.path.join(base, 'db'))
+
+command = os.path.basename(sys.argv[0])
+if command == 'check':
+ fixes = fixer.list()
+ for fix in fixes:
+ print fix
+ if fixes:
+ sys.exit(2)
+elif command == 'fix':
+ fixer.apply()
+else:
+ raise RuntimeError("%s: invalid command name '%s'" % (sys.argv[0],
command))
Added: gocept.infrastructure/feature_systemupgrade/util/fixes/lib/fix.py
==============================================================================
--- (empty file)
+++ gocept.infrastructure/feature_systemupgrade/util/fixes/lib/fix.py Mon Dec
1 15:06:23 2008
(at)(at) -0,0 +1,56 (at)(at)
+# Copyright (c) 2008 gocept gmbh & co. kg
+# See also LICENSE.txt
+
+import glob
+import inspect
+import os
+import types
+
+import fixapi
+
+
+class Fixer(object):
+ """Fixer allows to list pending fixes and to apply them."""
+
+ def __init__(self, dbdir):
+ self.dir = dbdir
+ self._load_fixes()
+
+ def list(self):
+ return sorted(fix.__name__ for fix in self._list_pending())
+
+ def apply(self):
+ pending = self._list_pending()
+ while pending:
+ for fix in pending:
+ fix.apply()
+ new_pending = self._list_pending()
+ if new_pending == pending:
+ # no progress
+ break
+ pending = new_pending
+
+ def _load_fixes(self):
+ self.fixes = set()
+ for file in glob.glob(os.path.join(self.dir, '*.py')):
+ module = self._import(file)
+ module_fixes = {}
+ for fixname, fix in module.__dict__.items():
+ if inspect.isclass(fix) and issubclass(fix, fixapi.Fix):
+ module_fixes[fixname] = fix()
+ if not module_fixes:
+ raise RuntimeError("no fix found in file '%s'" % file)
+ filename = os.path.splitext(os.path.basename(file))[0]
+ for fixname, fix in module_fixes.items():
+ fix.__name__ = '%s.%s' % (filename, fixname)
+ self.fixes.add(fix)
+
+ def _import(self, file):
+ locals = {}
+ execfile(file, locals)
+ module = types.ModuleType(os.path.basename(file))
+ module.__dict__.update(locals)
+ return module
+
+ def _list_pending(self):
+ return set(fix for fix in self.fixes if fix.is_pending())
Added: gocept.infrastructure/feature_systemupgrade/util/fixes/lib/fixapi.py
==============================================================================
--- (empty file)
+++ gocept.infrastructure/feature_systemupgrade/util/fixes/lib/fixapi.py Mon
Dec 1 15:06:23 2008
(at)(at) -0,0 +1,5 (at)(at)
+# Copyright (c) 2008 gocept gmbh & co. kg
+# See also LICENSE.txt
+
+class Fix(object):
+ """Abstract base class of all fixes."""
Added:
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/db/one.py
==============================================================================
--- (empty file)
+++
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/db/one.py Mon
Dec 1 15:06:23 2008
(at)(at) -0,0 +1,15 (at)(at)
+# Copyright (c) 2008 gocept gmbh & co. kg
+# See also LICENSE.txt
+
+import fixapi
+
+
+class RunTwice(fixapi.Fix):
+
+ counter = 2
+
+ def is_pending(self):
+ return bool(self.counter)
+
+ def apply(self):
+ self.counter -= 1
Added:
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/db/two.py
==============================================================================
--- (empty file)
+++
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/db/two.py Mon
Dec 1 15:06:23 2008
(at)(at) -0,0 +1,30 (at)(at)
+# Copyright (c) 2008 gocept gmbh & co. kg
+# See also LICENSE.txt
+
+import time
+
+import fixapi
+
+
+class IgnoreMe(fixapi.Fix):
+
+ def is_pending(self):
+ return False
+
+
+class RunOnce(fixapi.Fix):
+
+ pending = True
+
+ def is_pending(self):
+ return self.pending
+
+ def apply(self):
+ self.pending = False
+
+
+class UsesImports(fixapi.Fix):
+
+ def is_pending(self):
+ time.time()
+ return False
Added:
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/db_broken/empty.py
==============================================================================
--- (empty file)
+++
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/db_broken/empty.py Mon
Dec 1 15:06:23 2008
(at)(at) -0,0 +1,6 (at)(at)
+# Copyright (c) 2008 gocept gmbh & co. kg
+# See also LICENSE.txt
+
+import fixapi
+
+# intentionally left blank
Added:
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/db_failing/fix.py
==============================================================================
--- (empty file)
+++
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/db_failing/fix.py Mon
Dec 1 15:06:23 2008
(at)(at) -0,0 +1,13 (at)(at)
+# Copyright (c) 2008 gocept gmbh & co. kg
+# See also LICENSE.txt
+
+import fixapi
+
+
+class Failing(fixapi.Fix):
+
+ def is_pending(self):
+ return True
+
+ def apply(self):
+ raise RuntimeError('cannot apply failing fix')
Added:
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/db_non_converging/fix.py
==============================================================================
--- (empty file)
+++
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/db_non_converging/fix.py Mon
Dec 1 15:06:23 2008
(at)(at) -0,0 +1,13 (at)(at)
+# Copyright (c) 2008 gocept gmbh & co. kg
+# See also LICENSE.txt
+
+import fixapi
+
+
+class NonConverging(fixapi.Fix):
+
+ def is_pending(self):
+ return True
+
+ def apply(self):
+ pass
Added:
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/test_fix.py
==============================================================================
--- (empty file)
+++
gocept.infrastructure/feature_systemupgrade/util/fixes/lib/tests/test_fix.py Mon
Dec 1 15:06:23 2008
(at)(at) -0,0 +1,47 (at)(at)
+# Copyright (c) 2008 gocept gmbh & co. kg
+# See also LICENSE.txt
+
+import os.path
+import sys
+import unittest
+
+sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
+import fix
+
+
+class FixerTest(unittest.TestCase):
+
+ base = os.path.dirname(__file__)
+
+ def test_list_db(self):
+ fixer = fix.Fixer(os.path.join(self.base, 'db'))
+ self.assertEquals(['one.RunTwice', 'two.RunOnce'], fixer.list())
+
+ def test_list_empty_db(self):
+ fixer = fix.Fixer(os.path.join(self.base, 'db_empty'))
+ self.assertEquals([], fixer.list())
+
+ def test_list_broken_db(self):
+ self.assertRaises(
+ RuntimeError,
+ lambda: fix.Fixer(os.path.join(self.base, 'db_broken')))
+
+ def test_apply_converges(self):
+ fixer = fix.Fixer(os.path.join(self.base, 'db'))
+ fixer.apply()
+ self.assertEquals([], fixer.list())
+
+ def test_apply_failing(self):
+ fixer = fix.Fixer(os.path.join(self.base, 'db_failing'))
+ self.assertRaises(RuntimeError, fixer.apply)
+
+ def test_apply_not_converging(self):
+ fixer = fix.Fixer(os.path.join(self.base, 'db_non_converging'))
+ self.assertEquals(['fix.NonConverging'], fixer.list())
+ fixer.apply()
+ self.assertEquals(['fix.NonConverging'], fixer.list())
+ fixer.apply()
+ self.assertEquals(['fix.NonConverging'], fixer.list())
+
+
+unittest.main()
|