1 What is this?
It's an object-relational mapper for use with SQL DB's. It's based on peak.storage and peak.model and is an evolution of some code Ulrich Eck posted to the mailing list.
2 Development Status
You can use it. It works great.
SQLEntityDM and SQLQueryDM work: inserting rows, deleting them, and updating them are all hit by my production code. In addition, the API should be pretty stable (until the model metadata metamorphosis (explained below) if it happens). I have a dozen SQLEntityDM subclasses (with more on the way) to maintain now, so future changes will be considered with commensurate gravity. I hereby dub this version 0.1. As always, this code has no warranty and no guarantees.
I still intend to have a Trac+svn set up for this someplace before long; I'll post a link when I do.
I'm also still interested in comments on the API. Does anybody actually use SQLQueryDM? (I don't think it adds much value.) Are there useful cases my design is too brittle to support? (Do note the changes to the API I've already planned: do a case-sensitive grep for "Field".) (Okay, never mind that "Field" stuff; now, from ?PhillipEby's prompting, I'm thinking about scrapping the whole fields attribute and using binding.metadata somehow instead. I have to go learn that, though, before I say more.)
I'm not much interested (yet) in comments on the implementation, which is still as ugly as sin and will improve gradually. However, if anybody can answer the questions by the XXXs and TODOs, I'm all ears!
Thanks for your thoughts!
2005-10-11 (r943). Goal: API stability.
- EntityDM no longer blows up if you don't have any read?OnlyFields.
- Brought _oid?ForElement() (renamed from oid?ForElement()) to the top level of its class so it can be overridden.
- get() now auto-tuples its oid arg.
- Renamed state?ForRelations() to _other?StateForRow(), made it private, and stopped passing it a state dict. Now it has to make its own, which is good because it decreases coupling with its caller.
- Renamed foreign?KeysFromElement() to _other?DbValuesForElement(), since you could certainly use it to return other things than just foreign keys (though that remains its typical use). Privatized it; you shouldn't need to call it from the outside.
- Renamed writable?ValuesFromElement() to db?ValuesFromElement(), since I think "db" is more important to convey than "writable".
- Renamed state?ForElement() to state?ForRow() for consistency with how PEAK's oidFor() uses the term "for".
- Broke the guts of state?ForRow() and db?ValuesForElement() off into helper methods to provide more flexibility in overriding.
- Cleaned up SQL generation: both the code and the results. Also no longer computes all the SQL when only some is needed.
- Added oid?ForRow().
- Got rid of unneeded include of ?ActiveClass.
- Broke the actual SELECT querying off into _loadRow() so subclasses can use it as a utility function.
- _new() no longer sets ob._p_oid directly; that's the caller's job. (To make this work, _set?ReadOnlyFields() now takes oid as a param and no longer requires _p_oid to be set as a precondition.)
- Decreased the scope of get?FeatureClass() and _fillHole().
- Commented out _defaultState(), which was never used.
- Improved docs. Moved some of them to interface.py.
- Coded things more functionally, less iteratively.
- state?ForRelations() and state?ForElement() no longer take apparently-unnecessary oid or ob args.
- Now import ?InvalidKeyError, which I'd forgot to do.
- Improved documentation a little.
2005-08-23: Tweaked to conform to the interfaces it claims and to clean things up a bit.
- Noted future direction.
- _load() now raises ?InvalidKeyError instead of ?KeyError, so it conforms to I?DataManager_SPI.
- Removed _thunk(), which was unnecessary.
- Fixed some spelling, spacing, and style, and improved comments.
Get the package.