[Commits] (pje) Spike: define query framework interfaces,
and implement the "filters" layer
commits at osafoundation.org
commits at osafoundation.org
Fri Mar 11 16:32:50 PST 2005
Commit by: pje
Modified files:
internal/Spike/src/spike/interfaces.py None 1.1
internal/Spike/src/spike/query.py None 1.1
internal/Spike/src/spike/models.py 1.4 1.5
internal/Spike/src/spike/overview.txt 1.11 1.12
internal/Spike/src/spike/schema.py 1.7 1.8
internal/Spike/src/spike/tests/test_query.py None 1.1
internal/Spike/src/spike/tests/__init__.py 1.8 1.9
Log message:
Spike: define query framework interfaces, and implement the "filters" layer
(i.e. boolean algebra on criteria). Sets and entity classes are now usable
as filters, with support for union, intersect, difference, and negation.
However, the boolean algebra framework does not yet support iteration or
subscriptions on results, only membership testing.
ViewCVS links:
http://cvs.osafoundation.org/index.cgi/internal/Spike/src/spike/interfaces.py?rev=1.1&content-type=text/vnd.viewcvs-markup
http://cvs.osafoundation.org/index.cgi/internal/Spike/src/spike/query.py?rev=1.1&content-type=text/vnd.viewcvs-markup
http://cvs.osafoundation.org/index.cgi/internal/Spike/src/spike/models.py.diff?r1=text&tr1=1.4&r2=text&tr2=1.5
http://cvs.osafoundation.org/index.cgi/internal/Spike/src/spike/overview.txt.diff?r1=text&tr1=1.11&r2=text&tr2=1.12
http://cvs.osafoundation.org/index.cgi/internal/Spike/src/spike/schema.py.diff?r1=text&tr1=1.7&r2=text&tr2=1.8
http://cvs.osafoundation.org/index.cgi/internal/Spike/src/spike/tests/test_query.py?rev=1.1&content-type=text/vnd.viewcvs-markup
http://cvs.osafoundation.org/index.cgi/internal/Spike/src/spike/tests/__init__.py.diff?r1=text&tr1=1.8&r2=text&tr2=1.9
Index: internal/Spike/src/spike/overview.txt
diff -u internal/Spike/src/spike/overview.txt:1.11 internal/Spike/src/spike/overview.txt:1.12
--- internal/Spike/src/spike/overview.txt:1.11 Mon Feb 28 17:09:21 2005
+++ internal/Spike/src/spike/overview.txt Fri Mar 11 16:32:48 2005
@@ -474,16 +474,16 @@
to iterate over the entire database, but in practice you'd use filters like::
- for contact in ws[content.Contact]:
+ for contact in ws.where(content.Contact):
print contact.fullName
to iterate over a class extent. This brings me to the question of the query
interface. There are several basic operations that need to be supported:
Filtering
- I'm thinking that this can be represented via subscripting, e.g.
- ``someSet[criterion]``. The criterion could be a type, a callable, a
- filter object, or a string from which a filter definition can be parsed.
+ Filters can be invoked with the ``where()`` method on a set, or using
+ intersection (``&`` operator). The criterion could be a type, a callable,
+ a filter object, or a string from which a filter definition can be parsed.
For now, though, I'm punting on the question of what filter objects look
like or what the string syntax is. We'll just assume that filter objects
will also be callable, so the only special cases are types and strings.
@@ -497,7 +497,7 @@
a mapping-like object taking the same number of keys. So if you did
something like::
- byName = ws[Contact].groupedBy(
+ byName = ws.where(Contact).groupedBy(
Contact.lastName.of, Contact.firstName.of
)
@@ -552,6 +552,13 @@
should probably be punted on for now, as there are no specific requirements
yet.
+Misc.
+ There ought to be a way for filters to subscribe to items they're applied
+ to, so that they can inform the intersection when the corresponding object
+ changes. This needs to work even in the case of a filter that's a union
+ or a negation. And, it needs some thought in order to avoid over-creating
+ event subscriptions (at least for the in-memory implementation).
+
Schema
------
Index: internal/Spike/src/spike/models.py
diff -u internal/Spike/src/spike/models.py:1.4 internal/Spike/src/spike/models.py:1.5
--- internal/Spike/src/spike/models.py:1.4 Mon Feb 21 17:50:24 2005
+++ internal/Spike/src/spike/models.py Fri Mar 11 16:32:48 2005
@@ -1,11 +1,12 @@
"""Observable data structures -- see ``models.txt`` for docs"""
from events import Event
+from query import AbstractFilter
__all__ = ['Set', 'SetChanged', 'Validation']
-class Set(object):
+class Set(AbstractFilter):
"""Observable collection of unordered unique objects"""
__slots__ = 'data','type','__weakref__'
@@ -110,6 +111,9 @@
def __iter__(self):
return iter(self.data)
+ def __contains__(self,ob):
+ return ob in self.data
+
class SetChanged(Event):
"""Set has changed membership"""
Index: internal/Spike/src/spike/tests/__init__.py
diff -u internal/Spike/src/spike/tests/__init__.py:1.8 internal/Spike/src/spike/tests/__init__.py:1.9
--- internal/Spike/src/spike/tests/__init__.py:1.8 Fri Feb 25 19:50:24 2005
+++ internal/Spike/src/spike/tests/__init__.py Fri Mar 11 16:32:48 2005
@@ -16,6 +16,8 @@
test_codegen = make_docsuite('codegen.txt')
test_uuidgen = make_docsuite('uuidgen.txt')
+
+
def all():
# Return all tests
return TestSuite( [suite(), slow()] )
@@ -31,7 +33,8 @@
# Return all dependency-free unit tests
return TestSuite(
[test_uuidgen(), test_events(), test_models(), test_schema(),
- defaultTestLoader.loadTestsFromNames(['pim.tests.suite'])
+ defaultTestLoader.loadTestsFromNames(
+ ['pim.tests.suite', 'spike.tests.test_query'])
]
)
Index: internal/Spike/src/spike/schema.py
diff -u internal/Spike/src/spike/schema.py:1.7 internal/Spike/src/spike/schema.py:1.8
--- internal/Spike/src/spike/schema.py:1.7 Fri Feb 25 17:51:45 2005
+++ internal/Spike/src/spike/schema.py Fri Mar 11 16:32:48 2005
@@ -3,12 +3,13 @@
__all__ = [
'Entity', 'Role', 'Relationship', 'One', 'Many', 'NullSet', 'LoadEvent',
'Enumeration', 'Activator', 'RelationshipClass', 'EnumerationClass',
- 'ActiveDescriptor',
+ 'ActiveDescriptor', 'EntityClass',
]
from models import Set
from events import Event
from types import ClassType
+from query import AbstractFilter
ClassTypes = type, ClassType
NullSet = Set(type=())
@@ -403,10 +404,17 @@
ob.activateInClass(cls,name)
+class EntityClass(Activator,AbstractFilter):
+ """Filter support, so that entity classes can be used as query filters"""
+
+ def __contains__(cls,ob):
+ return isinstance(ob,cls)
+
+
class Entity(object):
"""Required base class for all entity types"""
- __metaclass__ = Activator
+ __metaclass__ = EntityClass
def __init__(self,**kw):
for k,v in kw.items():
More information about the Commits
mailing list