123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527 |
- ##############################################################################
- #
- # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
- # All Rights Reserved.
- #
- # This software is subject to the provisions of the Zope Public License,
- # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
- # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
- # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
- # FOR A PARTICULAR PURPOSE
- #
- ##############################################################################
-
- from zope.interface import Interface, Attribute
-
-
- class ICollection(Interface):
-
- def clear():
- """Remove all of the items from the collection."""
-
- def __nonzero__():
- """Check if the collection is non-empty.
-
- Return a true value if the collection is non-empty and a
- false value otherwise.
- """
-
-
- class IReadSequence(Interface):
-
- def __getitem__(index):
- """Return the value at the given index.
-
- An IndexError is raised if the index cannot be found.
- """
-
- def __getslice__(index1, index2):
- """Return a subsequence from the original sequence.
-
- The subsequence includes the items from index1 up to, but not
- including, index2.
- """
-
- class IKeyed(ICollection):
-
- def has_key(key):
- """Check whether the object has an item with the given key.
-
- Return a true value if the key is present, else a false value.
- """
-
- def keys(min=None, max=None, excludemin=False, excludemax=False):
- """Return an IReadSequence containing the keys in the collection.
-
- The type of the IReadSequence is not specified. It could be a list
- or a tuple or some other type.
-
- All arguments are optional, and may be specified as keyword
- arguments, or by position.
-
- If a min is specified, then output is constrained to keys greater
- than or equal to the given min, and, if excludemin is specified and
- true, is further constrained to keys strictly greater than min. A
- min value of None is ignored. If min is None or not specified, and
- excludemin is true, the smallest key is excluded.
-
- If a max is specified, then output is constrained to keys less than
- or equal to the given max, and, if excludemax is specified and
- true, is further constrained to keys strictly less than max. A max
- value of None is ignored. If max is None or not specified, and
- excludemax is true, the largest key is excluded.
- """
-
- def maxKey(key=None):
- """Return the maximum key.
-
- If a key argument if provided and not None, return the largest key
- that is less than or equal to the argument. Raise an exception if
- no such key exists.
- """
-
- def minKey(key=None):
- """Return the minimum key.
-
- If a key argument if provided and not None, return the smallest key
- that is greater than or equal to the argument. Raise an exception
- if no such key exists.
- """
-
-
- class ISetMutable(IKeyed):
-
- def insert(key):
- """Add the key (value) to the set.
-
- If the key was already in the set, return 0, otherwise return 1.
- """
-
- def remove(key):
- """Remove the key from the set.
-
- Raises KeyError if key is not in the set.
- """
-
- def update(seq):
- """Add the items from the given sequence to the set."""
-
-
- class ISized(Interface):
- """An object that supports __len__."""
-
- def __len__():
- """Return the number of items in the container."""
-
-
- class IKeySequence(IKeyed, ISized):
-
- def __getitem__(index):
- """Return the key in the given index position.
-
- This allows iteration with for loops and use in functions,
- like map and list, that read sequences.
- """
-
-
- class ISet(IKeySequence, ISetMutable):
- pass
-
-
- class ITreeSet(IKeyed, ISetMutable):
- pass
-
- class IMinimalDictionary(ISized, IKeyed):
-
- def get(key, default):
- """Get the value associated with the given key.
-
- Return the default if has_key(key) is false.
- """
-
- def __getitem__(key):
- """Get the value associated with the given key.
-
- Raise KeyError if has_key(key) is false.
- """
-
- def __setitem__(key, value):
- """Set the value associated with the given key."""
-
- def __delitem__(key):
- """Delete the value associated with the given key.
-
- Raise KeyError if has_key(key) is false.
- """
-
- def values(min=None, max=None, excludemin=False, excludemax=False):
- """Return an IReadSequence containing the values in the collection.
-
- The type of the IReadSequence is not specified. It could be a list
- or a tuple or some other type.
-
- All arguments are optional, and may be specified as keyword
- arguments, or by position.
-
- If a min is specified, then output is constrained to values whose
- keys are greater than or equal to the given min, and, if excludemin
- is specified and true, is further constrained to values whose keys
- are strictly greater than min. A min value of None is ignored. If
- min is None or not specified, and excludemin is true, the value
- corresponding to the smallest key is excluded.
-
- If a max is specified, then output is constrained to values whose
- keys are less than or equal to the given max, and, if excludemax is
- specified and true, is further constrained to values whose keys are
- strictly less than max. A max value of None is ignored. If max is
- None or not specified, and excludemax is true, the value
- corresponding to the largest key is excluded.
- """
-
- def items(min=None, max=None, excludemin=False, excludemax=False):
- """Return an IReadSequence containing the items in the collection.
-
- An item is a 2-tuple, a (key, value) pair.
-
- The type of the IReadSequence is not specified. It could be a list
- or a tuple or some other type.
-
- All arguments are optional, and may be specified as keyword
- arguments, or by position.
-
- If a min is specified, then output is constrained to items whose
- keys are greater than or equal to the given min, and, if excludemin
- is specified and true, is further constrained to items whose keys
- are strictly greater than min. A min value of None is ignored. If
- min is None or not specified, and excludemin is true, the item with
- the smallest key is excluded.
-
- If a max is specified, then output is constrained to items whose
- keys are less than or equal to the given max, and, if excludemax is
- specified and true, is further constrained to items whose keys are
- strictly less than max. A max value of None is ignored. If max is
- None or not specified, and excludemax is true, the item with the
- largest key is excluded.
- """
-
- class IDictionaryIsh(IMinimalDictionary):
-
- def update(collection):
- """Add the items from the given collection object to the collection.
-
- The input collection must be a sequence of (key, value) 2-tuples,
- or an object with an 'items' method that returns a sequence of
- (key, value) pairs.
- """
-
- def byValue(minValue):
- """Return a sequence of (value, key) pairs, sorted by value.
-
- Values < minValue are omitted and other values are "normalized" by
- the minimum value. This normalization may be a noop, but, for
- integer values, the normalization is division.
- """
-
- def setdefault(key, d):
- """D.setdefault(k, d) -> D.get(k, d), also set D[k]=d if k not in D.
-
- Return the value like get() except that if key is missing, d is both
- returned and inserted into the dictionary as the value of k.
-
- Note that, unlike as for Python's dict.setdefault(), d is not
- optional. Python defaults d to None, but that doesn't make sense
- for mappings that can't have None as a value (for example, an
- IIBTree can have only integers as values).
- """
-
- def pop(key, d):
- """D.pop(k[, d]) -> v, remove key and return the corresponding value.
-
- If key is not found, d is returned if given, otherwise KeyError is
- raised.
- """
-
-
- class IBTree(IDictionaryIsh):
-
- def insert(key, value):
- """Insert a key and value into the collection.
-
- If the key was already in the collection, then there is no
- change and 0 is returned.
-
- If the key was not already in the collection, then the item is
- added and 1 is returned.
-
- This method is here to allow one to generate random keys and
- to insert and test whether the key was there in one operation.
-
- A standard idiom for generating new keys will be::
-
- key = generate_key()
- while not t.insert(key, value):
- key=generate_key()
- """
-
-
- class IMerge(Interface):
- """Object with methods for merging sets, buckets, and trees.
-
- These methods are supplied in modules that define collection
- classes with particular key and value types. The operations apply
- only to collections from the same module. For example, the
- IIBTree.union can only be used with IIBTree.IIBTree,
- IIBTree.IIBucket, IIBTree.IISet, and IIBTree.IITreeSet.
-
- The implementing module has a value type. The IOBTree and OOBTree
- modules have object value type. The IIBTree and OIBTree modules
- have integer value types. Other modules may be defined in the
- future that have other value types.
-
- The individual types are classified into set (Set and TreeSet) and
- mapping (Bucket and BTree) types.
- """
-
- def difference(c1, c2):
- """Return the keys or items in c1 for which there is no key in c2.
-
- If c1 is None, then None is returned. If c2 is None, then c1
- is returned.
-
- If neither c1 nor c2 is None, the output is a Set if c1 is a Set or
- TreeSet, and is a Bucket if c1 is a Bucket or BTree.
- """
-
- def union(c1, c2):
- """Compute the Union of c1 and c2.
-
- If c1 is None, then c2 is returned, otherwise, if c2 is None,
- then c1 is returned.
-
- The output is a Set containing keys from the input
- collections.
- """
-
- def intersection(c1, c2):
- """Compute the intersection of c1 and c2.
-
- If c1 is None, then c2 is returned, otherwise, if c2 is None,
- then c1 is returned.
-
- The output is a Set containing matching keys from the input
- collections.
- """
-
-
- class IBTreeModule(Interface):
- """These are available in all modules (IOBTree, OIBTree, OOBTree, IIBTree,
- IFBTree, LFBTree, LOBTree, OLBTree, and LLBTree).
- """
-
- BTree = Attribute(
- """The IBTree for this module.
-
- Also available as [prefix]BTree, as in IOBTree.""")
-
- Bucket = Attribute(
- """The leaf-node data buckets used by the BTree.
-
- (IBucket is not currently defined in this file, but is essentially
- IDictionaryIsh, with the exception of __nonzero__, as of this
- writing.)
-
- Also available as [prefix]Bucket, as in IOBucket.""")
-
- TreeSet = Attribute(
- """The ITreeSet for this module.
-
- Also available as [prefix]TreeSet, as in IOTreeSet.""")
-
- Set = Attribute(
- """The ISet for this module: the leaf-node data buckets used by the
- TreeSet.
-
- Also available as [prefix]BTree, as in IOSet.""")
-
-
- class IIMerge(IMerge):
- """Merge collections with integer value type.
-
- A primary intent is to support operations with no or integer
- values, which are used as "scores" to rate indiviual keys. That
- is, in this context, a BTree or Bucket is viewed as a set with
- scored keys, using integer scores.
- """
-
- def weightedUnion(c1, c2, weight1=1, weight2=1):
- """Compute the weighted union of c1 and c2.
-
- If c1 and c2 are None, the output is (0, None).
-
- If c1 is None and c2 is not None, the output is (weight2, c2).
-
- If c1 is not None and c2 is None, the output is (weight1, c1).
-
- Else, and hereafter, c1 is not None and c2 is not None.
-
- If c1 and c2 are both sets, the output is 1 and the (unweighted)
- union of the sets.
-
- Else the output is 1 and a Bucket whose keys are the union of c1 and
- c2's keys, and whose values are::
-
- v1*weight1 + v2*weight2
-
- where:
-
- v1 is 0 if the key is not in c1
- 1 if the key is in c1 and c1 is a set
- c1[key] if the key is in c1 and c1 is a mapping
-
- v2 is 0 if the key is not in c2
- 1 if the key is in c2 and c2 is a set
- c2[key] if the key is in c2 and c2 is a mapping
-
- Note that c1 and c2 must be collections.
- """
-
- def weightedIntersection(c1, c2, weight1=1, weight2=1):
- """Compute the weighted intersection of c1 and c2.
-
- If c1 and c2 are None, the output is (0, None).
-
- If c1 is None and c2 is not None, the output is (weight2, c2).
-
- If c1 is not None and c2 is None, the output is (weight1, c1).
-
- Else, and hereafter, c1 is not None and c2 is not None.
-
- If c1 and c2 are both sets, the output is the sum of the weights
- and the (unweighted) intersection of the sets.
-
- Else the output is 1 and a Bucket whose keys are the intersection of
- c1 and c2's keys, and whose values are::
-
- v1*weight1 + v2*weight2
-
- where:
-
- v1 is 1 if c1 is a set
- c1[key] if c1 is a mapping
-
- v2 is 1 if c2 is a set
- c2[key] if c2 is a mapping
-
- Note that c1 and c2 must be collections.
- """
-
-
- class IMergeIntegerKey(IMerge):
- """IMerge-able objects with integer keys.
-
- Concretely, this means the types in IOBTree and IIBTree.
- """
-
- def multiunion(seq):
- """Return union of (zero or more) integer sets, as an integer set.
-
- seq is a sequence of objects each convertible to an integer set.
- These objects are convertible to an integer set:
-
- + An integer, which is added to the union.
-
- + A Set or TreeSet from the same module (for example, an
- IIBTree.TreeSet for IIBTree.multiunion()). The elements of the
- set are added to the union.
-
- + A Bucket or BTree from the same module (for example, an
- IOBTree.IOBTree for IOBTree.multiunion()). The keys of the
- mapping are added to the union.
-
- The union is returned as a Set from the same module (for example,
- IIBTree.multiunion() returns an IIBTree.IISet).
-
- The point to this method is that it can run much faster than
- doing a sequence of two-input union() calls. Under the covers,
- all the integers in all the inputs are sorted via a single
- linear-time radix sort, then duplicates are removed in a second
- linear-time pass.
- """
-
- class IBTreeFamily(Interface):
- """the 64-bit or 32-bit family"""
- IO = Attribute('The IIntegerObjectBTreeModule for this family')
- OI = Attribute('The IObjectIntegerBTreeModule for this family')
- II = Attribute('The IIntegerIntegerBTreeModule for this family')
- IF = Attribute('The IIntegerFloatBTreeModule for this family')
- OO = Attribute('The IObjectObjectBTreeModule for this family')
- maxint = Attribute('The maximum integer storable in this family')
- minint = Attribute('The minimum integer storable in this family')
-
-
- class IIntegerObjectBTreeModule(IBTreeModule, IMerge):
- """keys, or set values, are integers; values are objects.
-
- describes IOBTree and LOBTree"""
-
- family = Attribute('The IBTreeFamily of this module')
-
-
- class IObjectIntegerBTreeModule(IBTreeModule, IIMerge):
- """keys, or set values, are objects; values are integers.
-
- Object keys (and set values) must sort reliably (for instance, *not* on
- object id)! Homogenous key types recommended.
-
- describes OIBTree and LOBTree"""
-
- family = Attribute('The IBTreeFamily of this module')
-
-
- class IIntegerIntegerBTreeModule(IBTreeModule, IIMerge, IMergeIntegerKey):
- """keys, or set values, are integers; values are also integers.
-
- describes IIBTree and LLBTree"""
-
- family = Attribute('The IBTreeFamily of this module')
-
-
- class IObjectObjectBTreeModule(IBTreeModule, IMerge):
- """keys, or set values, are objects; values are also objects.
-
- Object keys (and set values) must sort reliably (for instance, *not* on
- object id)! Homogenous key types recommended.
-
- describes OOBTree"""
-
- # Note that there's no ``family`` attribute; all families include
- # the OO flavor of BTrees.
-
-
- class IIntegerFloatBTreeModule(IBTreeModule, IMerge):
- """keys, or set values, are integers; values are floats.
-
- describes IFBTree and LFBTree"""
-
- family = Attribute('The IBTreeFamily of this module')
-
-
- try:
- from ZODB.POSException import BTreesConflictError
- except ImportError:
- class BTreesConflictError(ValueError):
- @property
- def reason(self):
- return self.args[-1]
-
- ###############################################################
- # IMPORTANT NOTE
- #
- # Getting the length of a BTree, TreeSet, or output of keys,
- # values, or items of same is expensive. If you need to get the
- # length, you need to maintain this separately.
- #
- # Eventually, I need to express this through the interfaces.
- #
- ################################################################
|