g'day. This is dbcook, a framework to cook databases from recipes, written as python declarations. Eventually the result may be edible (;-) repository: svn co https://dbcook.svn.sf.net/svnroot/dbcook/trunk http://dbcook.sf.net If u're interested, have a look, dbcook/usage/example1.py might be a start. The directory-structure is still in flux. To use it, the internal dbcook/ has to be accessible somehow (PYTHONPATH or else). Licensed under MIT-license. Dependencies: * SQLAlchemy, v0.5 or v0.4 series. Support for v0.3 and early-v0.4 is dropped at rev259 * kjbuckets (from gadfly) for graph-arithmetics Here a short description what it probably is, and can do: A framework for declarative abstract mapping of object hierarchies/relations into a (relational or not) database, completely hiding the DB where possible. The "language/syntax" itself is DB-backend independent. Currently the available builder is over SQLAlchemy as backend (so it looks like another wrapping declarative translator). Eventual future backends may include RDFalchemy or other non-SQL data storages. Usage cases/levels: * DB-definition - completely hides/automates the table/ column/ key/ constraint/ mapper/ whatever creation. The user can control certain characteristics of the way the mapping happens, mostly related to hierarchy and relations between objects (subclasses, instances, leafs, uniqueness etc). * generate a source of equivalent plain SQLAlchemy-calls to build the DB-definition - very useful for testing and/or generating routine mappings, with or without actualy using dbcook afterwards * use plain SQLAlchemy once the definition is done - e.g. session.query( class).. * dbcook.expressions can partialy abstract the query generation, converting from plain python functions/expressions (of objects' attributes) into backend/SQL clauses: ``lambda self: (self.friend.manager.age < 40) & self.name.endswith('a')`` * writing own reflectors (that walk the declared classes and extracts info from them), eventualy allowing different "language/syntax" Work started somewhen in october 2006. Now it can handle: * data column types - the actual mapping is separate from object declaration * reference columns - plain, forward-declared, self-referential -> foreign keys * automatic solving of cyclical references/ dependencies (putting proper alter_table / post_update) * class inheritance, class inclusion (inheritance without database mapping of the base), and virtual classes (those never have instances). More in mapcontext._Base * polymorphism - giving 3 kinds of queries for each mapped class: all, base-only, subclasses only * any combination of table-inheritance-types within the tree (concrete/joined/no-single-yet) - defined localy or hierarchicaly; beware that sql-polymorphism only works with joined-table for now * associations (many-to-many) - implicit and explicit * collections (one-to-many) * dbcook.usage.samanager is a correct context-like keeper of all db-related SQLAlchemy things in one place, on destroy() will try hard to clear _all_ side-effects of its existence, allowing use of same objects within several/different subsequent DB-mappings. Example declarations: import dbcook.usage.plainwrap as o2r class Text( o2r.Type): pass class Int( o2r.Type): pass class Address( o2r.Base): place = Text() class Person( o2r.Base): name = Text() age = Int() address = o2r.Type4Reference( Address) friend = o2r.Type4Reference( 'Person') class Employee( Person): job = Text() #build it o2r.Builder( metadata, locals(), { Text: sqlalchemy.String } ) ... for p in expression.query1( lambda self: self.friend.friend.friend.age > 24, klas=Person, session=session) ): print p ..... thats it. and no mentioning of tables, columns etc whatsoever ..... So far it is just a library. There is no single way to use it. The directory usage/ has 2 possible reflectors (that walk the declared classes and extract info from them), one is just plain python (plainwrap.py), another is for my static_type/ framework, for makeing staticly-declared structs (a-la java/C++ semantics) in python - do mail if interested. Certain pieces are (almost) independent and are usable as is without all the rest: expression.py, usage/hack*py, sa_generator.py - all SQLAlchemy related. The tests/ directory contains 2 types of tests - sa/ which proves that the way SA is used in dbcook is correct/working, and mapper/other which check whether the cooker does right thing as result. It still uses makefile to run all stuff. Some todo's, long- or short- term: - some documentation, translate all in both languages - tests for all the stuff, systematically in most of combinations - expressions.joins need rethinking (upgraded to SA 0.4 ok) - generate sql-server-side functions, triggers etc - single-table inheritance - concrete-polymorphism: polymunion of (type,id) key - SA doesnot fully do it - other reflectors/"syntaxes" - e.g. elixir-like - sub-structures as value (contained IN the parent class, not a reference to elsewhere, but still used as x.y; think C memory layout) - user-notion types for reflector, e.g. aggregators are like a relation - caching tables/columns - e.g. aggregators - autoload / reverse-engineering / upgrade / migration (see misc/metadata/) see dbcook/misc/readme.txt for some usable recipes. have fun svil svilen_dobrev at users . sourceforge . net az at svilendobrev . com or see me at sqlalchemy's newsgroup - sqlalchemy at googlegroups . com =================== > Isn't it what does already Elixir? not really. Frankly, i dont know much elixir, just some impressions. elixir is sort of syntax sugar over SA, with very little decision-making inside. It leaves all the decisions - the routine ones too - to the programmer. At least thats how i got it. dbcook hides / automates _everything_ possible - the very concept of existing of relational SQL underneath is seen only by side-effects, e.g. the DB_inheritance types "concrete-", "joined-", "single-" table. It decides things like where to break cyclical references with alter_table/post_update; makes up the polymorphic inheritances - whatever the tree, etc. Of course this is only the declaration/creation part (model-definition - building the DB); after that it can cover only small/simple part of the queries (model usage) - possibilities there are endless. That's why there is plain SA underneath, once the "python function over objects converted into SA-expression over tables" path gets too narrow - or just ends. dbcook does not have assign_mapper-like things, putting query methods on the objects. it leaves all that to you. Although one day there will be a usage-case/example of some way to do it - once i get there. more differences maybe - no idea, someone has to have time to try both (:-)