The README that comes with Durus is missing a couple pieces of information that are critical if you actually want to write a program that uses Durus, and the only other documentation appears to be the 2005 Durus pycon presentation, which gives an admirable description of the technical underpinnings but doesn't fill in the blanks of how to use it, either.
Specifically, as far as code samples go, the README gives you this:
Example using FileStorage to open a Connection to a file: from durus.file_storage import FileStorage from durus.connection import Connection connection = Connection(FileStorage("test.durus"))
# Assume mymodule defines A as a subclass of Persistent. from mymodule import A x = A() root = connection.get_root() # connection set as shown above. root["sample"] = x # root is dict-like connection.commit() # Now x is stored.
That's all you get.
Okay, in this situation it's clear how to retrieve x -- look it up by the key we've hardcoded. But what if x is a list of Persistent objects, and I want to retrieve one of those. Do I have to keep track of its index in x? Do I need to generate my own unique IDs? (Note that the linked code has an obvious race condition in a multithreaded environment.)
No, you don't. Durus assigns each Persisent object an attribute called _p_oid. (P object id. Not sure if P stands for Persistent, or Private, or something else entirely.)
[in persistent.py] def __new__(klass, *args, **kwargs): [...] instance._p_oid = None # <-- this is the oid that get() cares about def _p_format_oid(self): return format_oid(self._p_oid)
_p_oid is a four-byte binary string, so for passing around as a GET or POST variable in a web application, the format function (which turns it into a string representation of the oid number) is handy.
Now that you're passing oids around, Durus gives you an easy way to retrieve the object it identifies:
[in connection.py] def get(self, oid): """(oid:str|int|long) -> Persistent | None Return object for `oid`. The object may be a ghost. """
Note that if you do pass around the formatted id, you'll need to turn it into a Python int (or long) before sending it to get; if you pass the string '123' get will assume it's a valid (binary) oid and not autoconvert it.
Now that the code diving is out of the way, I'm enjoying Durus a lot. Next post I'll give a short Spyce demo using Durus for persistence.