diff options
author | Benjamin Saller <bcsaller@objectrealms.net> | 2007-07-02 19:45:28 (GMT) |
---|---|---|
committer | Benjamin Saller <bcsaller@objectrealms.net> | 2007-07-02 19:45:28 (GMT) |
commit | 12a564c450f75121dc59919496290cbfe4c2704b (patch) | |
tree | a7cf9c24757084c6555e1760333b20cbfd8c37ac | |
parent | 07a88e504b544552915815e04bef235aca247aa2 (diff) |
propertys via the create/update dict
key:kind -> value
see test/properties.txt
-rw-r--r-- | src/olpc/datastore/backingstore.py | 5 | ||||
-rw-r--r-- | src/olpc/datastore/datastore.py | 14 | ||||
-rw-r--r-- | src/olpc/datastore/model.py | 25 | ||||
-rw-r--r-- | src/olpc/datastore/query.py | 27 |
4 files changed, 60 insertions, 11 deletions
diff --git a/src/olpc/datastore/backingstore.py b/src/olpc/datastore/backingstore.py index 04a9fa8..03cc54a 100644 --- a/src/olpc/datastore/backingstore.py +++ b/src/olpc/datastore/backingstore.py @@ -96,8 +96,10 @@ class BackingStore(object): def id(self): return self.descriptor()['id'] @property def title(self): return self.descriptor()['title'] + + class FileBackingStore(BackingStore): """ A backing store that directs maps the storage of content objects to an available filesystem. @@ -370,6 +372,8 @@ class FileBackingStore(BackingStore): if not allowMissing: raise KeyError("object for uid:%s missing" % uid) + def get_uniquevaluesfor(self, propertyname): + return self.querymanager.get_uniquevaluesfor(propertyname) def find(self, query): @@ -470,3 +474,4 @@ class InplaceFileBackingStore(FileBackingStore): if os.path.exists(path): os.unlink(path) + diff --git a/src/olpc/datastore/datastore.py b/src/olpc/datastore/datastore.py index b743e2c..a133dfe 100644 --- a/src/olpc/datastore/datastore.py +++ b/src/olpc/datastore/datastore.py @@ -331,6 +331,20 @@ class DataStore(dbus.service.Object): dictionary[prop.key] = prop.marshall() return dictionary + @dbus.service.method(DS_DBUS_INTERFACE, + in_signature='sa{sv}', + out_signature='as') + def get_uniquevaluesfor(self, propertyname, query=None): + if not query: query = {} + mountpoints = query.pop('mountpoints', self.mountpoints) + mountpoints = [self.mountpoints[str(m)] for m in mountpoints] + results = set() + + for mp in mountpoints: + result = mp.get_uniquevaluesfor(propertyname) + results = results.union(result) + return results + #@utils.sanitize_dbus @dbus.service.method(DS_DBUS_INTERFACE, diff --git a/src/olpc/datastore/model.py b/src/olpc/datastore/model.py index f70e68f..d678b59 100644 --- a/src/olpc/datastore/model.py +++ b/src/olpc/datastore/model.py @@ -11,7 +11,7 @@ __copyright__ = 'Copyright ObjectRealms, LLC, 2007' __license__ = 'The GNU Public License V2+' from sqlalchemy import Table, Column, UniqueConstraint -from sqlalchemy import String, Integer, Unicode, PickleType +from sqlalchemy import String, Integer, Unicode from sqlalchemy import ForeignKey, Sequence, Index from sqlalchemy import mapper, relation from sqlalchemy import create_session @@ -31,11 +31,15 @@ import time # we have a global thread local session factory context = {} +propertyTypes = {} +_marker = object() def get_session(backingstore): return context[backingstore] -_marker = object() +def registerPropertyType(kind, class_): propertyTypes[kind] = class_ +def propertyByKind(kind): return propertyTypes[kind] + class Content(object): def __repr__(self): @@ -56,7 +60,6 @@ class Content(object): query = session.query(Property) return query.select_by(content_id=self.id, **kwargs) - # Backingstore dependent bindings def get_file(self): @@ -206,6 +209,15 @@ class NumberProperty(Property): value = property(get_value, set_value) +class BinaryProperty(Property): + # base64 encode binary data + def __init__(self, key, value, type="binary"): + Property.__init__(self, key, value, type) + + def get_value(self): return self._value.decode('base64') + def set_value(self, value): self._value = value.encode('base64') + value = property(get_value, set_value) + class Model(object): """ Manages the global state of the metadata model index. This is @@ -259,7 +271,7 @@ class Model(object): Column('id', Integer, Sequence('property_id_seq'), primary_key=True), Column('content_id', Integer, ForeignKey('content.id')), Column('key', Unicode, ), - Column('value', PickleType, ), + Column('value', Unicode, ), Column('type', Unicode, ), # unique key to content mapping UniqueConstraint('content_id', 'key', @@ -325,7 +337,7 @@ class Model(object): self.addPropertyType(DateProperty, 'date') self.addPropertyType(NumberProperty, 'number') self.addPropertyType(TextProperty, 'text') - + self.addPropertyType(BinaryProperty, 'binary') @@ -355,3 +367,6 @@ class Model(object): polymorphic_identity=typename, properties=properties ) + + registerPropertyType(typename, PropertyClass) + diff --git a/src/olpc/datastore/query.py b/src/olpc/datastore/query.py index 03d24de..c2e534d 100644 --- a/src/olpc/datastore/query.py +++ b/src/olpc/datastore/query.py @@ -16,7 +16,7 @@ from datetime import datetime from lemur.xapian.sei import DocumentStore, DocumentPiece, SortableValue from olpc.datastore.converter import converter from olpc.datastore.model import DateProperty, TextProperty -from olpc.datastore.model import Model, Content, Property +from olpc.datastore.model import Model, Content, Property, propertyByKind from olpc.datastore.utils import create_uid from sqlalchemy import create_engine, BoundMetaData @@ -35,7 +35,14 @@ class SugarDomain(object): """resolves property names to the factory type that supports them in the model """ - return { + # key may be a two part form directly indicating the property + # type + if ':' in key: + key, kind = key.split(':', 1) + # now resolve the kind to a property class + return key, propertyByKind(kind) + + return key, { 'ctime' : DateProperty, 'mtime' : DateProperty, 'author' : Property, @@ -45,10 +52,10 @@ class SugarDomain(object): }.get(key, Property) def propertyFactory(self, key, value='', dict=None): - k = self.kind_by_key(key) - p = k(key, value) + key, kind = self.kind_by_key(key) + p = kind(key, value) if dict is not None: dict[key] = p - return k + return kind def _automaticProperties(self): d = {} @@ -74,7 +81,7 @@ class SugarDomain(object): # convert it into a dict of Property objects d = {} for k,v in props.iteritems(): - kind = self.kind_by_key(k) + k, kind = self.kind_by_key(k) p = kind(k, v) d[k] = p if creating and include_defaults: @@ -246,6 +253,14 @@ class QueryManager(SugarDomain): content_id=c.id) + def get_uniquevaluesfor(self, propertyname): + properties = self.model.tables['properties'] + return [r[0] for r in select([properties.c.value], + properties.c.key==propertyname, + distinct=True).execute().fetchall()] + + + def delete(self, content_or_uid): c = self._resolve(content_or_uid) s = self.model.session |