]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- reorganizing the test modules and fixtures, but keeping the essential method of
authorMike Bayer <mike_mp@zzzcomputing.com>
Sun, 27 Mar 2011 21:52:30 +0000 (17:52 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 27 Mar 2011 21:52:30 +0000 (17:52 -0400)
creating fixture classes the same, i.e. run a method, then inspect __subclasses__() of
a marked base class, seems to have broken that approach permanently.   While the tests run
locally just fine, on the buildbot most of the environments continue to fail in entirely
random places.   One of the key changes of the reorganization is that the big bunch of
classes from _fixtures.py is now created ad-hoc instead of reusing a set of module-bound
classes.  This means there's a lot more class creation/teardown traffic occuring in the
cPython interpreter.   Taking a look at the docs for __subclasses__() confirms that the
list of subclasses is of course a weak-referenced collection.   So in the absense of the
tests working just fine for a couple of years, it would seem obvious that the bug
here is setup_classes()/mappers() is called, we come back, the new classes are now
not referenced at all, we then call __subclasses__() and maybe we get them, maybe we don't.
But it's totally not clear how this behavior just hasn't occurred at all for a couple
of years (except, possibly, for very rare occasions that I cannot reproduce).   So in this changeset we switch
to a method of class tracking that I use in a lot of other places, that of using a metaclass
to positively stick classes in the registry the moment they are created.   Test classes
are already built against a base that is created per-fixture run so we already have the advantage
of a local system.   I send this changeset to the buildbot and beg of it to please allow our
tests to pass once again !

test/lib/fixtures.py

index 14c37981b946fec5558acfe630e43f69003c5ab1..b325975ff29adc21b3e956010b233c68dfc7c662 100644 (file)
@@ -263,17 +263,21 @@ class MappedTest(_ORMTest, TablesTest, testing.AssertsExecutionResults):
         the "classes" registry.
         
         """
-        class Base(object):
+        cls_registry = cls.classes
+        class FindFixture(type):
+            def __init__(cls, classname, bases, dict_):
+                cls_registry[classname] = cls
+                return type.__init__(cls, classname, bases, dict_)
+
+        class _Base(object):
+            __metaclass__ = FindFixture
+        class Basic(BasicEntity, _Base):
             pass
-        class Basic(BasicEntity, Base):
-            pass
-        class Comparable(ComparableEntity, Base):
+        class Comparable(ComparableEntity, _Base):
             pass
         cls.Basic = Basic
         cls.Comparable = Comparable
         fn()
-        for class_ in subclasses(Base):
-            cls.classes[class_.__name__] = class_
 
     def _teardown_each_mappers(self):
         # some tests create mappers in the test bodies
@@ -309,12 +313,3 @@ class MappedTest(_ORMTest, TablesTest, testing.AssertsExecutionResults):
                  for column_values in rows[table]])
 
 
-def subclasses(cls):
-    subs, process = set(), set(cls.__subclasses__())
-    while process:
-        cls = process.pop()
-        if cls not in subs:
-            subs.add(cls)
-            process |= set(cls.__subclasses__())
-    return subs
-