]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- remove some old cruft
authorMike Bayer <mike_mp@zzzcomputing.com>
Sun, 7 Sep 2014 23:17:46 +0000 (19:17 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 7 Sep 2014 23:17:46 +0000 (19:17 -0400)
- prop.compare() isn't needed; replace with prop._with_parent()
for relationships
- update docs in orm/interfaces

lib/sqlalchemy/orm/dynamic.py
lib/sqlalchemy/orm/interfaces.py
lib/sqlalchemy/orm/relationships.py
lib/sqlalchemy/orm/util.py

index 51db1b107e89b6b2ba4cd6e6961a258a9606ca8a..a4ccfe417f4cfdf4d4adabe33b8b389ac232fb35 100644 (file)
@@ -221,10 +221,8 @@ class AppenderMixin(object):
 
         mapper = object_mapper(instance)
         prop = mapper._props[self.attr.key]
-        self._criterion = prop.compare(
-            operators.eq,
+        self._criterion = prop._with_parent(
             instance,
-            value_is_parent=True,
             alias_secondary=False)
 
         if self.attr.order_by:
index 47ee4c0761524f950ea986c7859dac538db63872..ad2452c1b9e0c143abe2b0a205777c9b4654d234 100644 (file)
@@ -9,11 +9,12 @@
 
 Contains various base classes used throughout the ORM.
 
-Defines the now deprecated ORM extension classes as well
-as ORM internals.
+Defines some key base classes prominent within the internals,
+as well as the now-deprecated ORM extension classes.
 
 Other than the deprecated extensions, this module and the
-classes within should be considered mostly private.
+classes within are mostly private, though some attributes
+are exposed when inspecting mappings.
 
 """
 
@@ -67,9 +68,15 @@ class MapperProperty(_MappedAttribute, InspectionAttr):
 
     This collection is checked before the 'cascade_iterator' method is called.
 
+    The collection typically only applies to a RelationshipProperty.
+
     """
 
     is_property = True
+    """Part of the InspectionAttr interface; states this object is a
+    mapper property.
+
+    """
 
     def setup(self, context, entity, path, adapter, **kwargs):
         """Called by Query for the purposes of constructing a SQL statement.
@@ -77,16 +84,15 @@ class MapperProperty(_MappedAttribute, InspectionAttr):
         Each MapperProperty associated with the target mapper processes the
         statement referenced by the query context, adding columns and/or
         criterion as appropriate.
-        """
 
-        pass
+        """
 
     def create_row_processor(self, context, path,
                              mapper, result, adapter, populators):
-        """Return a 3-tuple consisting of three row processing functions.
+        """Produce row processing functions and append to the given
+        set of populators lists.
 
         """
-        pass
 
     def cascade_iterator(self, type_, state, visited_instances=None,
                          halt_on=None):
@@ -98,16 +104,40 @@ class MapperProperty(_MappedAttribute, InspectionAttr):
         Note that the 'cascade' collection on this MapperProperty is
         checked first for the given type before cascade_iterator is called.
 
-        See PropertyLoader for the related instance implementation.
+        This method typically only applies to RelationshipProperty.
+
         """
 
         return iter(())
 
     def set_parent(self, parent, init):
+        """Set the parent mapper that references this MapperProperty.
+
+        This method is overridden by some subclasses to perform extra
+        setup when the mapper is first known.
+
+        """
         self.parent = parent
 
-    def instrument_class(self, mapper):  # pragma: no-coverage
-        raise NotImplementedError()
+    def instrument_class(self, mapper):
+        """Hook called by the Mapper to the property to initiate
+        instrumentation of the class attribute managed by this
+        MapperProperty.
+
+        The MapperProperty here will typically call out to the
+        attributes module to set up an InstrumentedAttribute.
+
+        This step is the first of two steps to set up an InstrumentedAttribute,
+        and is called early in the mapper setup process.
+
+        The second step is typically the init_class_attribute step,
+        called from StrategizedProperty via the post_instrument_class()
+        hook.  This step assigns additional state to the InstrumentedAttribute
+        (specifically the "impl") which has been determined after the
+        MapperProperty has determined what kind of persistence
+        management it needs to do (e.g. scalar, object, collection, etc).
+
+        """
 
     _configure_started = False
     _configure_finished = False
@@ -157,45 +187,28 @@ class MapperProperty(_MappedAttribute, InspectionAttr):
 
         """
 
-        pass
-
     def post_instrument_class(self, mapper):
         """Perform instrumentation adjustments that need to occur
         after init() has completed.
 
-        """
-        pass
+        The given Mapper is the Mapper invoking the operation, which
+        may not be the same Mapper as self.parent in an inheritance
+        scenario; however, Mapper will always at least be a sub-mapper of
+        self.parent.
 
-    def is_primary(self):
-        """Return True if this ``MapperProperty``'s mapper is the
-        primary mapper for its class.
+        This method is typically used by StrategizedProperty, which delegates
+        it to LoaderStrategy.init_class_attribute() to perform final setup
+        on the class-bound InstrumentedAttribute.
 
-        This flag is used to indicate that the ``MapperProperty`` can
-        define attribute instrumentation for the class at the class
-        level (as opposed to the individual instance level).
         """
 
-        return not self.parent.non_primary
-
     def merge(self, session, source_state, source_dict, dest_state,
               dest_dict, load, _recursive):
         """Merge the attribute represented by this ``MapperProperty``
-        from source to destination object"""
-
-        pass
-
-    def compare(self, operator, value, **kw):
-        """Return a compare operation for the columns represented by
-        this ``MapperProperty`` to the given value, which may be a
-        column value or an instance.  'operator' is an operator from
-        the operators module, or from sql.Comparator.
+        from source to destination object.
 
-        By default uses the PropComparator attached to this MapperProperty
-        under the attribute name "comparator".
         """
 
-        return operator(self.comparator, value)
-
     def __repr__(self):
         return '<%s at 0x%x; %s>' % (
             self.__class__.__name__,
@@ -203,8 +216,7 @@ class MapperProperty(_MappedAttribute, InspectionAttr):
 
 
 class PropComparator(operators.ColumnOperators):
-    """Defines boolean, comparison, and other operators for
-    :class:`.MapperProperty` objects.
+    """Defines SQL operators for :class:`.MapperProperty` objects.
 
     SQLAlchemy allows for operators to
     be redefined at both the Core and ORM level.  :class:`.PropComparator`
@@ -399,6 +411,13 @@ class StrategizedProperty(MapperProperty):
     strategies can be selected at Query time through the usage of
     ``StrategizedOption`` objects via the Query.options() method.
 
+    The mechanics of StrategizedProperty are used for every Query
+    invocation for every mapped attribute participating in that Query,
+    to determine first how the attribute will be rendered in SQL
+    and secondly how the attribute will retrieve a value from a result
+    row and apply it to a mapped object.  The routines here are very
+    performance-critical.
+
     """
 
     strategy_wildcard_key = None
@@ -460,7 +479,7 @@ class StrategizedProperty(MapperProperty):
         self.strategy = self._get_strategy_by_cls(self.strategy_class)
 
     def post_instrument_class(self, mapper):
-        if self.is_primary() and \
+        if not self.parent.non_primary and \
                 not mapper.class_manager._attr_has_impl(self.key):
             self.strategy.init_class_attribute(mapper)
 
@@ -493,18 +512,24 @@ class MapperOption(object):
 
     propagate_to_loaders = False
     """if True, indicate this option should be carried along
-    Query object generated by scalar or object lazy loaders.
+    to "secondary" Query objects produced during lazy loads
+    or refresh operations.
+
     """
 
     def process_query(self, query):
-        pass
+        """Apply a modification to the given :class:`.Query`."""
 
     def process_query_conditionally(self, query):
         """same as process_query(), except that this option may not
         apply to the given query.
 
-        Used when secondary loaders resend existing options to a new
-        Query."""
+        This is typically used during a lazy load or scalar refresh
+        operation to propagate options stated in the original Query to the
+        new Query being used for the load.  It occurs for those options that
+        specify propagate_to_loaders=True.
+
+        """
 
         self.process_query(query)
 
@@ -523,9 +548,9 @@ class LoaderStrategy(object):
 
     * it processes the ``QueryContext`` at statement construction time,
       where it can modify the SQL statement that is being produced.
-      Simple column attributes may add their represented column to the
-      list of selected columns, *eager loading* properties may add
-      ``LEFT OUTER JOIN`` clauses to the statement.
+      For example, simple column attributes will add their represented
+      column to the list of selected columns, a joined eager loader
+      may establish join clauses to add to the statement.
 
     * It produces "row processor" functions at result fetching time.
       These "row processor" functions populate a particular attribute
@@ -543,17 +568,26 @@ class LoaderStrategy(object):
         pass
 
     def setup_query(self, context, entity, path, loadopt, adapter, **kwargs):
-        pass
+        """Establish column and other state for a given QueryContext.
+
+        This method fulfills the contract specified by MapperProperty.setup().
+
+        StrategizedProperty delegates its setup() method
+        directly to this method.
+
+        """
 
     def create_row_processor(self, context, path, loadopt, mapper,
                              result, adapter, populators):
-        """Return row processing functions which fulfill the contract
-        specified by MapperProperty.create_row_processor.
+        """Establish row processing functions for a given QueryContext.
 
-        StrategizedProperty delegates its create_row_processor method
-        directly to this method. """
+        This method fulfills the contract specified by
+        MapperProperty.create_row_processor().
 
-        pass
+        StrategizedProperty delegates its create_row_processor() method
+        directly to this method.
+
+        """
 
     def __str__(self):
         return str(self.parent_property)
index 2bcb3f4a19e3d5be44998ebc757ebbd9c61bc383..95ff21444f58e2ba09d0185e511ec7d19a8919de 100644 (file)
@@ -1307,25 +1307,10 @@ class RelationshipProperty(StrategizedProperty):
                 mapperlib.Mapper._configure_all()
             return self.prop
 
-    def compare(self, op, value,
-                value_is_parent=False,
-                alias_secondary=True):
-        if op == operators.eq:
-            if value is None:
-                if self.uselist:
-                    return ~sql.exists([1], self.primaryjoin)
-                else:
-                    return self._optimized_compare(
-                        None,
-                        value_is_parent=value_is_parent,
-                        alias_secondary=alias_secondary)
-            else:
-                return self._optimized_compare(
-                    value,
-                    value_is_parent=value_is_parent,
-                    alias_secondary=alias_secondary)
-        else:
-            return op(self.comparator, value)
+    def _with_parent(self, instance, alias_secondary=True):
+        assert instance is not None
+        return self._optimized_compare(
+            instance, value_is_parent=True, alias_secondary=alias_secondary)
 
     def _optimized_compare(self, value, value_is_parent=False,
                            adapt_source=None,
@@ -1633,7 +1618,7 @@ class RelationshipProperty(StrategizedProperty):
         """Test that this relationship is legal, warn about
         inheritance conflicts."""
 
-        if not self.is_primary() and not mapperlib.class_mapper(
+        if self.parent.non_primary and not mapperlib.class_mapper(
                 self.parent.class_,
                 configure=False).has_property(self.key):
             raise sa_exc.ArgumentError(
@@ -1719,7 +1704,7 @@ class RelationshipProperty(StrategizedProperty):
         """Interpret the 'backref' instruction to create a
         :func:`.relationship` complementary to this one."""
 
-        if not self.is_primary():
+        if self.parent.non_primary:
             return
         if self.backref is not None and not self.back_populates:
             if isinstance(self.backref, util.string_types):
index 1bb6b571e993bc744bfe83286666ac11c39f1997..734f9d5e6ff01c8f56ea77629f547cf1cdf50930 100644 (file)
@@ -896,9 +896,7 @@ def with_parent(instance, prop):
     elif isinstance(prop, attributes.QueryableAttribute):
         prop = prop.property
 
-    return prop.compare(operators.eq,
-                        instance,
-                        value_is_parent=True)
+    return prop._with_parent(instance)
 
 
 def has_identity(object):