[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