A high level api to working with Alchemist

progress from basics to higher level in terms of yaml configuration during the talk

>> import transaction
>> from ore.alchemist import ModelFactory
>> model = ModelFactory("mysql://root@localhost/alc", package="myapp.generated")

>> PersonClass = model["Persons"]
>> AddressClass = model["Addresses"]

>> model.load()
>> model.loadFile("myapp.yaml")

what about specification of import considerations for startup semantics. because alchemist
generates zope integration classes on the fly, for it to be consumed by zope, alchemist needs
to have done most of its work during before the zcml configuration process. 

myapp.yaml

mappings:

  Persons:
    domain class : Products.Book.content.Users
    interface module : Products.Book.interfaces

    columns:
      first_name :
        label : First Name
        column : True # set as a displayed column in default zc.table views
        vocabulary : # 
      last_name :
        label : Last Name
    

  Column Defaults:
    label :
    column : True
    
  Table Defaults:
    domain class :
    generated columns specified
    list display : question, pub date
    modified events : False
    sort on :
       first_name
       last_name
       
    omit-not-specified : False # default      
    
    #plone specific dialect
    workflow :
    discussable :
    searchable text :
    database notifications : # enable triggers for db notification
    # as any plone index state requires db synchronization for changes.
  

>> from myapp.generated.interfaces import IPersonTable, IAddressTable
>> from myapp.generated.domain import Person, Address

>> new_address = Address()
>> new_address.state = 123
ValidationError

Connecting to the web

generic containers and marker interface views
  - select conditions
  
custom generic containers

view adapation to bind arbitrary containers

customizing the user interface

- table annotations - from file yaml?

- layout - from file.. what? svg graphics.. would be ideal

>> model.load( ["Persons", "Addresses", "Users" ] )

lets access the person table, we have easy access to on demand loading of tables along
with their foriegn key dependencies.

>> PersonTable = model.loadTable( "Persons" )

We can also generate zope3 interfaces on the fly from database tables.

>> IPersonTable = model.loadInterface( "Persons" )

against which we can now define views and adapters for our model, alchemist ships with some
basic default views for viewing and editing content, as well as json, xml views.

Of course the database schema is a pretty poor place to look for semantic information to use
in views, so its typical instead to use a TableAnnotation to define semantic information about
the model, so that the Zope3 schema is generated with appropriate metadata.

>> from ore.alchemist import TableAnnotation
>> PersonAnnotation = TableAnnotation( PersonTable )
>> PersonAnnotation["first_name"] = { "label":"First Name" }
>> IPersonTable = model.defineInterface( PersonAnnotation )

in general the load* api provides for easy automation, and the define api 

>> PersonClass = model[ "Persons" ]
>> AddressClass = model[ "Addresses" ]

lets create a person and set their address
>> instance = PersonClass( first_name="Kapil", last_name="Rx")
>> instance.address = Address( city="San Francisco", state="CA" )

>> PersonClass.
>> 
>> PersonSpec.interface.isImplementedBy( instance )
True

how bout a nice shortcut to get us the domain class, z3 interface, and mapper at once

load up the person table, create interfaces, define mapping classes, for persons and all
foreign key dependencies.

>> PersonSpec = model.loadSpecification( "Persons" )


Custom domain classes

>> class bar( object ): pass
>> instance.redefineMapper( "Addresses", bar)



