[Zope-CVS] CVS: Packages/pypes/pypes - interfaces.py:1.24 query.py:1.17

Casey Duncan casey at zope.com
Mon May 31 23:05:51 EDT 2004


Update of /cvs-repository/Packages/pypes/pypes
In directory cvs.zope.org:/tmp/cvs-serv25759

Modified Files:
	interfaces.py query.py 
Log Message:
Implement fixed values for partial result iterResult methods. This is in anticipation of the sort implementation which will depend on it. It is also used by Join in certain cases.


=== Packages/pypes/pypes/interfaces.py 1.23 => 1.24 ===
--- Packages/pypes/pypes/interfaces.py:1.23	Fri May 14 00:38:29 2004
+++ Packages/pypes/pypes/interfaces.py	Mon May 31 23:05:48 2004
@@ -724,11 +724,20 @@
     #    determine a more efficient plan.
     #    """
     
-    def iterResult(*names):
+    def iterResult(*names, **fixed):
         """Yield the items for the specified input names where the criteria
         is true. If a single name is specified, yield each matching item from 
         the input. If multiple names are specified, yield tuples of the 
         matching items from the cooresponding named inputs.
+        
+        Arbitrary keyword arguments can be used to provide "fixed" output
+        values. The names of these keyword arguments coorespond to input
+        names and the values to members of the input. Fixed values are not
+        iterated and thus are yielded with each result containing ther value(s)
+        (if any). Fixed values are generally used when calling iterResults
+        from inside another generator which needs to control the output in
+        some way (i.e., enforcing joins or a sort order). If a fixed kwarg
+        is provided that does not match an input name, raise PypesQueryError.
         """
         
     #def resultSet(*names):


=== Packages/pypes/pypes/query.py 1.16 => 1.17 ===
--- Packages/pypes/pypes/query.py:1.16	Wed May 26 00:32:48 2004
+++ Packages/pypes/pypes/query.py	Mon May 31 23:05:48 2004
@@ -53,6 +53,7 @@
 from BTrees.OOBTree import OOBTree, OOTreeSet
 from pypes.interfaces import IPartialResult, IExtent
 from pypes.exceptions import PypesLookupError, PypesQueryInputError, CantProcess
+from pypes.exceptions import PypesQueryError
 from pypes.expression import Expression
 
 ## Exported constants ##
@@ -62,9 +63,7 @@
 
 ## Query Primitives ##
 
-def applyCriteria(input_map, criteria):
-    pass
-
+_empty_iter = iter(())
 
 def union_input_maps(input1, input2):
     """Create an input map dict whose values are the union of the cooresponding
@@ -158,32 +157,36 @@
         criteria = self.criteriaExpr() & other.criteriaExpr()
         return self.__class__(inputs, criteria)
     
-    def iterResult(self, *names, **static):
+    def iterResult(self, *names, **fixed):
         """Iterate the cartesian product yielding items from the inputs named
         where the criteria is satisfied. If a single name is specified, yield
         each matching item from the input. If multiple names are specified,
         yield tuples of the matching items from the cooresponding named inputs.
         
-        Static values may be passed as keyword args. The arg name matches an
+        Fixed values may be passed as keyword args. The arg name matches an
         input name, and the value must be a member of the input set. Static
         inputs are not iterated, but are returned in every result. They are
         useful when using a cart product inside of another iterator which
         handles iterating those values itself.
         """
-        for name, obj in static.items():
-            assert obj in self._inputs[name], 'static input not in product'
+        for name, obj in fixed.items():
+            if name not in self._inputs:
+                raise PypesQueryError(
+                    'fixed input %s not part of cart. product' % name)
+            if obj not in self._inputs[name]:
+                raise StopIteration
         criteria = self._criteria
         # Prime the input iterators and get the first row
         row = {}
         input_iters = []
         for name, ipt in self._inputs.items():
-            if name not in static:
+            if name not in fixed:
                 obj_iter = iter(ipt)
                 input_iters.append((name, obj_iter))
                 row[name] = obj_iter.next()
             else:
                 input_iters.append(None)
-                row[name] = static[name]
+                row[name] = fixed[name]
         # Create output factory from input names
         if len(names) == 1:
             out, = names
@@ -431,7 +434,7 @@
         joined = {}
         has_left = self._left_name in joined
         has_right = self._right_name in joined
-        # Iterate the joined results and pass them as static values
+        # Iterate the joined results and pass them as fixed values
         # to the full product's results
         for left, right in self._iterJoin(self.reverse):
             if has_left:
@@ -441,7 +444,26 @@
             for row in product.iterResult(*names, **joined):
                 yield row
         
-    def iterResult(self, *names):
+    def iterResult(self, *names, **fixed):
+        if fixed:
+            for name, obj in fixed.items():
+                if name not in self._inputs:
+                    raise PypesQueryError(
+                        'fixed input %s not part of query' % name)
+                if obj not in self._inputs[name]:
+                    return _empty_iter
+            # See if fixed values contain possible outputs. If not, bail early
+            if (self._left_name in fixed
+                and not self._left_func(fixed[self._left_name])):
+                return _empty_iter
+            if (self._right_name in fixed
+                and not self._right_func(fixed[self._right_name])):
+                return _empty_iter
+            if self._left_name in fixed or self._right_name in fixed:
+                # One or both of the joined inputs are fixed 
+                # don't bother using full join operations
+                return CartProduct(
+                    self._inputs, self._criteria).iterResult(*names, **fixed)
         if len(names) == 2 and names == (self._left_name, self._right_name):
             # Special case, names match join terms in order exactly
             # No transform of the raw join is required
@@ -565,11 +587,18 @@
         inputs = intersect_input_maps(self.inputMap(), other.inputMap())
         return other.__class__(inputs, criteria)
     
-    def iterResult(self, *names):
+    def iterResult(self, *names, **fixed):
         if len(names) == 1:
-            return iter(self._inputs[names[0]])
-        else:
-            return CartProduct(self._inputs).iterResult(*names)
+            name = names[0]
+            ipt = self._inputs[name]
+            if not fixed:
+                return iter(ipt)
+            elif name in fixed:
+                if fixed[name] in ipt:
+                    return iter((fixed[name],))
+                else:
+                    return _empty_iter
+        return CartProduct(self._inputs).iterResult(*names, **fixed)
 
 
 def sort(iterable, expression, order=ascending, limit=None):




More information about the Zope-CVS mailing list