Skip to content

/ Zope / gocept svn checkins / Archive / 2008 / 2008-12 / SVN: r7114 - in gocept.infrastructure/feature_systemupgrade/util/fixes: . db lib lib/tests lib/tests/db lib/tests/db_broken lib/tests/db_empty lib/tests/db_failing lib/tests/db_non_converging

[ << ] [ >> ]

[ SVN: r7111 - in gocept.infrastructure/testing/pupp... ] [ SVN: r7115 - in gocept.infrastructure/feature_syst... ]

SVN: r7114 - in gocept.infrastructure/feature_systemupgrade/util/fixes: . db lib lib/tests lib/tests/db lib/tests/db_broken lib/tests/db_empty lib/tests/db_failing lib/tests/db_non_converging
Christian Kauhaus <kc(at)gocept.com>
2008-12-01 15:06:25 [ FULL ]
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()

MailBoxer