Added convenience get() wrappers.
[didex.git] / didex / values.py
index 9a501eb..ecb78dd 100644 (file)
@@ -2,7 +2,7 @@ import threading
 from . import store, lib, index
 from .store import storedesc
 
-__all__ = ["simple", "multi"]
+__all__ = ["simple", "multi", "compound"]
 
 class cursor(lib.closable):
     def __init__(self, bk, st):
@@ -40,6 +40,27 @@ class base(storedesc):
     def get(self, **kwargs):
         return cursor(self.index().get(**kwargs), self.store)
 
+    def get1(self, *, check=False, default=KeyError, **kwargs):
+        with self.get(**kwargs) as cursor:
+            try:
+                k, v = next(cursor)
+            except StopIteration:
+                if default is not KeyError:
+                    return default
+                raise KeyError("no matches in " + self.name, kwargs)
+            if check:
+                try:
+                    next(cursor)
+                except StopIteration:
+                    pass
+                else:
+                    raise ValueError("unexpected multiple matchies in " + self.name, kwargs)
+            return v
+
+    def list(self, **kwargs):
+        with self.get(**kwargs) as cursor:
+            return [v for k, v in cursor]
+
 class descbase(base):
     def __init__(self, store, indextype, name, datatype, default):
         super().__init__(store, indextype, name, datatype)
@@ -113,6 +134,17 @@ class compound(base):
         self.parts = parts
         self.iattr = "__idx_%s_cur" % name
 
+    def minim(self, *parts):
+        return self.typ.minim(*parts)
+    def maxim(self, *parts):
+        return self.typ.maxim(*parts)
+
+    def get(self, *, partial=None, **spec):
+        if partial is not None:
+            return super().get(ge=self.minim(*partial), le = self.maxim(*partial), **spec)
+        else:
+            return super().get(**spec)
+
     def register(self, id, obj, tx):
         val = tuple(part.__get__(obj, None) for part in self.parts)
         self.index().put(val, id, tx=tx)