From: Mike Bayer Date: Sun, 27 Mar 2011 21:52:30 +0000 (-0400) Subject: - reorganizing the test modules and fixtures, but keeping the essential method of X-Git-Tag: rel_0_7b4~52 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=54563de4bb7be9ce8f3f284808751424a5d7a4b1;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - reorganizing the test modules and fixtures, but keeping the essential method of 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 ! --- diff --git a/test/lib/fixtures.py b/test/lib/fixtures.py index 14c37981b9..b325975ff2 100644 --- a/test/lib/fixtures.py +++ b/test/lib/fixtures.py @@ -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 -