[Zope-CVS] CVS: Packages/pypes/pypes - interfaces.py:1.26
query.py:1.19
Casey Duncan
casey at zope.com
Thu Jun 10 00:44:55 EDT 2004
Update of /cvs-repository/Packages/pypes/pypes
In directory cvs.zope.org:/tmp/cvs-serv7303
Modified Files:
interfaces.py query.py
Log Message:
Define and implement resultSet() method for IPartialResult classes
=== Packages/pypes/pypes/interfaces.py 1.25 => 1.26 ===
--- Packages/pypes/pypes/interfaces.py:1.25 Wed Jun 9 00:23:12 2004
+++ Packages/pypes/pypes/interfaces.py Thu Jun 10 00:44:24 2004
@@ -742,12 +742,13 @@
is provided that does not match an input name, raise PypesQueryError.
"""
- #def resultSet(*names):
- # """Return an ISet object containing the items from the inputs named.
- # If a single name is specified, then return a set of matching objects
- # from the input. If multiple names are specified, return a set of
- # tuples of the matching items from the cooresponding named inputs.
- # """
+ def resultSet(name):
+ """Return an ISet object containing the items from the input named
+ that are matched by the criteria. If the input is not filtered by the
+ criteria, then it may be returned.
+
+ If name does not coorespond to an input, raise PypesQueryError.
+ """
class IQueryResult(Interface):
"""Result from running a query"""
=== Packages/pypes/pypes/query.py 1.18 => 1.19 ===
--- Packages/pypes/pypes/query.py:1.18 Wed Jun 9 22:38:38 2004
+++ Packages/pypes/pypes/query.py Thu Jun 10 00:44:24 2004
@@ -46,6 +46,9 @@
from zope.interface import implements
from compiler import ast
from BTrees.OOBTree import OOBTree, OOTreeSet
+from BTrees.IIBTree import IITreeSet
+from pypes import services
+from pypes.identity import IdentitySet
from pypes.interfaces import IPartialResult, IExtent
from pypes.exceptions import PypesLookupError, PypesQueryInputError, CantProcess
from pypes.exceptions import PypesQueryError
@@ -99,8 +102,78 @@
inmap[name] = set1
return inmap
+class PartialResult:
+ """Abstract partial result class"""
+
+ _inputs = None # Input map
+ _criteria = None # Criteria expression
+
+ def inputMap(self):
+ return self._inputs.copy()
+
+ def criteriaExpr(self):
+ return self._criteria
+
+ def namesUsed(self):
+ return self._criteria.freeNames(self._inputs.keys())
+
+ def union(self, other):
+ raise NotImplementedError
+
+ def intersection(self, other):
+ raise NotImplementedError
+
+ def iterResult(self, *names, **fixed):
+ raise NotImplementedError
+
+ def resultSet(self, name):
+ """Return a set of objects from the input named which satisfy the
+ criteria.
+ """
+ if name not in self._inputs:
+ raise PypesQueryError('no input named "%s"' % name)
+ if self._criteria is None:
+ return self._inputs[name]
+ if name in self._criteria.freeNames(self._inputs.keys()):
+ # Input is referenced in criteria, create set from product result
+ maxlength = len(self._inputs[name])
+ length = 0
+ idset = IITreeSet()
+ insert = idset.insert
+ for obj in self.iterResult(name):
+ try:
+ pypesid = obj._pypes_id_
+ except AttributeError:
+ # object not identified
+ idset = None
+ break
+ else:
+ if insert(pypesid):
+ length += 1
+ elif length == maxlen:
+ # All objects from the input were found
+ return self._inputs[name]
+ if idset is not None:
+ dbconn = services.accesspointFrom(self._inputs[name])
+ return IdentitySet.fromIdSet(
+ idset, dbconn=dbconn, length=length)
+ else:
+ # can't use identity set
+ # XXX won't work with unhashable objects
+ return Set(self.iterResult(name))
+ else:
+ # Input not referenced from criteria, if any results are
+ # generated, then we can return the entire input set. If
+ # not return an empty set.
+ try:
+ self.iterResult(name).next()
+ except StopIteration:
+ return IdentitySet()
+ else:
+ return self._inputs[name]
-class CartProduct:
+
+class CartProduct(PartialResult):
"""Cartesian product of one or more inputs to a query. Allows lazy
evaluation, and efficient combinatorial operations
"""
@@ -119,12 +192,6 @@
self._inputs = input_map
self._criteria = criteria
- def inputMap(self):
- return self._inputs.copy()
-
- def criteriaExpr(self):
- return self._criteria
-
def namesUsed(self):
if self._criteria is not None:
return self._criteria.freeNames(self._inputs.keys())
@@ -218,11 +285,7 @@
if i > 0:
i = 0
break
-
- def resultSet(self, *names):
- """Return a unique set of results from the named inputs where the
- criteria is satisfied
- """
+
def equijoin(left_iter, left_expr, right_iter, right_expr):
"""Join the values of the left_iter and right_iter iterables where the
@@ -248,7 +311,7 @@
if isinstance(left_by_val, dict):
# Likely val is not hashable
# switch to using BTree which does not require hashable keys
- # (but insertion is slower)
+ # (but lookup is slower)
left_by_val = OOBTree(left_by_val)
left_by_val[val] = left_by_val.get(val, []) + [obj]
else:
@@ -287,7 +350,7 @@
if isinstance(right_by_val, dict):
# Likely val is not hashable switch to using a
# BTree which does not require hashable keys
- # (but insertion is slower)
+ # (but lookup is slower)
right_by_val = OOBTree(right_by_val)
right_by_val[val] = right_by_val.get(val, []) + [obj]
else:
@@ -328,7 +391,7 @@
for left in left_matches:
yield left, right
-class Join:
+class Join(PartialResult):
"""Join of multiple inputs using a criteria expression.
This implementation handles joins of two inputs each on a separate side
@@ -391,15 +454,6 @@
self._left_func = left_expr.makeFunction(left_names)
self._right_name, = right_names
self._right_func = right_expr.makeFunction(right_names)
-
- def inputMap(self):
- return self._inputs.copy()
-
- def criteriaExpr(self):
- return self._criteria
-
- def namesUsed(self):
- return self._criteria.freeNames(self._inputs.keys())
def union(self, other):
inputs = union_input_maps(self.inputMap(), other.inputMap())
@@ -488,7 +542,7 @@
return self._iterJoinOtherProduct(names, joined_names)
-class ActualizedResult:
+class ActualizedResult(PartialResult):
"""Partial result with greedy evaluation.
When instantiated, the inputs are processed immediately against the
@@ -540,21 +594,18 @@
self._inputs = {}
for name, ipt in input_map.items():
if name in filters:
- self._inputs[name] = Set(
+ self._inputs[name] = ipt = Set(
ifilter(filters[name].makeFunction(name), ipt))
else:
self._inputs[name] = ipt
+ if not ipt:
+ # If one of the inputs is empty, they all are
+ empty = IdentitySet()
+ for name in input_map:
+ self._inputs[name] = empty
+ break
else:
self._inputs = input_map.copy()
-
- def inputMap(self):
- return self._inputs.copy()
-
- def criteriaExpr(self):
- return self._criteria
-
- def namesUsed(self):
- return self._criteria.freeNames(self._inputs.keys())
def union(self, other):
"""A union with an actualized result returns a new partial result
@@ -594,6 +645,11 @@
else:
return _empty_iter
return CartProduct(self._inputs).iterResult(*names, **fixed)
+
+ def resultSet(self, name):
+ if name not in self._inputs:
+ raise PypesQueryError('no input named "%s"' % name)
+ return self._inputs[name]
def sort(iterable, expression, order=ascending, limit=None):
More information about the Zope-CVS
mailing list