summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2006-07-08 16:07:16 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2006-07-08 16:07:16 +0000
commiteeb4b2c8967940d255b816e3112b46e0bfa98074 (patch)
tree6c60d9d07037250be393831b7d4377f80855847f
parent22a0e600ce937cea4ea691d209f592e25c77d6a4 (diff)
downloadsqlalchemy-eeb4b2c8967940d255b816e3112b46e0bfa98074.tar.gz
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.
-rw-r--r--CHANGES2
-rw-r--r--lib/sqlalchemy/orm/__init__.py3
-rw-r--r--lib/sqlalchemy/orm/mapper.py99
-rw-r--r--lib/sqlalchemy/orm/properties.py3
4 files changed, 11 insertions, 96 deletions
diff --git a/CHANGES b/CHANGES
index 7f8a4f4b7..63f905236 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 9ebeffab8..8b7d3df0b 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 186963f31..92d10ad10 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 705d53363..997636b49 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