From eeb4b2c8967940d255b816e3112b46e0bfa98074 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sat, 8 Jul 2006 16:07:16 +0000 Subject: [PATCH] took out that whole compilation dependency thing. just need to loop through mapper_registry and compile whatever is not compiled. the "non-reentrant" compile() method, which is a product of the whole compilation dependency tangent, makes this pretty easy. So it was a pretty roundabout way to go for ultimately a pretty small change to compilation. --- CHANGES | 2 +- lib/sqlalchemy/orm/__init__.py | 3 +- lib/sqlalchemy/orm/mapper.py | 99 +++----------------------------- lib/sqlalchemy/orm/properties.py | 3 - 4 files changed, 11 insertions(+), 96 deletions(-) diff --git a/CHANGES b/CHANGES index 7f8a4f4b7c..63f9052368 100644 --- a/CHANGES +++ b/CHANGES @@ -10,7 +10,7 @@ working around new setuptools PYTHONPATH-killing behavior in order of primary key values, for more deterministic ordering - after_insert/delete/update mapper extensions now called per object, not per-object-per-table -- fixed the last few mapper compilation stragglers (hopefully) +- further fixes/refactorings to mapper compilation 0.2.4 - try/except when the mapper sets init.__name__ on a mapped class, diff --git a/lib/sqlalchemy/orm/__init__.py b/lib/sqlalchemy/orm/__init__.py index 9ebeffab89..8b7d3df0b7 100644 --- a/lib/sqlalchemy/orm/__init__.py +++ b/lib/sqlalchemy/orm/__init__.py @@ -10,7 +10,7 @@ packages and tying operations to class properties and constructors. """ from sqlalchemy import sql, schema, engine, util, exceptions from mapper import * -from mapper import mapper_registry, _compile_triggers +from mapper import mapper_registry from query import Query from util import polymorphic_union import properties @@ -52,7 +52,6 @@ def clear_mappers(): """removes all mappers that have been created thus far. when new mappers are created, they will be assigned to their classes as their primary mapper.""" mapper_registry.clear() - _compile_triggers.clear() def clear_mapper(m): """removes the given mapper from the storage of mappers. when a new mapper is diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index 186963f316..92d10ad103 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -28,26 +28,6 @@ NO_ATTRIBUTE = object() # returned by a MapperExtension method to indicate a "do nothing" response EXT_PASS = object() -# as mappers are constructed, they place records in this dictionary -# to set up "compile triggers" between mappers related by backref setups, so that when one -# mapper compiles it can trigger the compilation of a second mapper which needs to place -# a backref on the first. -_compile_triggers = {} - -class CompileTrigger(object): - def __init__(self, mapper): - self.mapper = mapper - self.dependencies = util.Set() - def add_dependency(self, classkey): - self.dependencies.add(classkey) - def can_compile(self): - return len(self.dependencies) == 0 or (len(self.dependencies)==1 and list(self.dependencies)[0] == self.mapper.class_key) - def compiled(self, classkey): - self.dependencies.remove(classkey) - def __str__(self): - return "CompileTrigger on mapper " + str(self.mapper) - def __repr__(self): - return str(self) class Mapper(object): """Persists object instances to and from schema.Table objects via the sql package. @@ -151,13 +131,6 @@ class Mapper(object): # mapper. self._compile_class() - # for all MapperProperties sent in the properties dictionary (typically this means - # (relation() instances), call the "attach()" method which may be used to set up - # compile triggers for this Mapper. - for prop in self.properties.values(): - if isinstance(prop, MapperProperty): - prop.attach(self) - # uncomment to compile at construction time (the old way) # this will break mapper setups that arent declared in the order # of dependency @@ -178,23 +151,14 @@ class Mapper(object): self._do_compile() - # find other mappers that need to be compiled, and/or - # clean out the _compile_triggers dictionary. - # this will keep the chain of compilation going until all - # mappers are compiled. - for key in _compile_triggers.keys(): - if isinstance(key, ClassKey): - mapper = mapper_registry.get(key, None) - if mapper.__is_compiled: - del _compile_triggers[key] - continue - if mapper is not None: - mapper.compile() - break - - # all known mappers should be compiled at this point - assert len(_compile_triggers) == 0 - + # look for another mapper thats not compiled, and compile it. + # this will utlimately compile all mappers, including any that + # need to set up backrefs on this mapper. + for mapper in mapper_registry.values(): + if not mapper.__is_compiled: + mapper.compile() + break + return self def _do_compile(self): @@ -213,49 +177,8 @@ class Mapper(object): self._compile_properties() self._compile_selectable() self._initialize_properties() - try: - del _compile_triggers[self] - except KeyError: - pass - - # compile some other mappers which have backrefs to this mapper - triggerset = _compile_triggers.pop(self.class_key, None) - if triggerset is not None: - for rec in triggerset: - rec.compiled(self.class_key) - if rec.can_compile(): - rec.mapper._do_compile() - return self - def _add_compile_trigger(self, argument): - """Establish the given mapper/classkey as a compilation dependency for this mapper.""" - - if isinstance(argument, Mapper): - classkey = argument.class_key - else: - classkey = ClassKey(argument, None) - - # CompileTrigger by mapper - try: - rec = _compile_triggers[self] - except KeyError: - rec = CompileTrigger(self) - _compile_triggers[self] = rec - - if classkey in rec.dependencies: - return - - rec.add_dependency(classkey) - - # CompileTrigger by triggering mapper (its classkey) - # when this mapper is compiled, all the CompileTrigger mappers - # are compiled (if their dependencies have all been compiled) - try: - triggers = _compile_triggers[classkey] - except KeyError: - triggers = [] - _compile_triggers[classkey] = triggers - triggers.append(rec) + return self def _compile_extensions(self): """goes through the global_extensions list as well as the list of MapperExtensions @@ -1163,10 +1086,6 @@ class Mapper(object): class MapperProperty(object): """an element attached to a Mapper that describes and assists in the loading and saving of an attribute on an object instance.""" - def attach(self, mapper): - """called during mapper construction for each property present in the "properties" dictionary. - this is before the Mapper has compiled its internal state.""" - pass def execute(self, session, instance, row, identitykey, imap, isnew): """called when the mapper receives a row. instance is the parent instance corresponding to the row. """ diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index 705d533639..997636b49b 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -150,9 +150,6 @@ class PropertyLoader(mapper.MapperProperty): private = property(lambda s:s.cascade.delete_orphan) - def attach(self, mapper): - mapper._add_compile_trigger(self.argument) - def cascade_iterator(self, type, object, recursive): if not type in self.cascade: return -- 2.47.3