Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > 429d9064b451fbf785f6785aa01bfcf8 > files > 68

python-storm-0.13-3mdv2010.0.noarch.rpm

Copyright (c) 2006, 2007 Canonical

Written by Jamshed Kakar <jkakar@kakar.ca>

This file is part of Storm Object Relational Mapper.

Storm is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.

Storm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.


Introduction
------------

The storm.zope package contains the ZStorm utility which provides
seamless integration between Storm and Zope 3's transaction system.
Setting up ZStorm is quite easy.  In most cases, you want to include
storm/zope/configure.zcml in your application.  For the purposes of
this doctest we'll register ZStorm manually.

  >>> from zope.component import provideUtility, getUtility
  >>> import transaction
  >>> from storm.zope.interfaces import IZStorm
  >>> from storm.zope.zstorm import global_zstorm

  >>> provideUtility(global_zstorm, IZStorm)
  >>> zstorm = getUtility(IZStorm)
  >>> zstorm
  <storm.zope.zstorm.ZStorm object at ...>

Awesome, now that the utility is in place we can start to use it!


Getting stores
--------------

The ZStorm utility allows us work with named stores.

  >>> zstorm.set_default_uri("test", "sqlite:")

Setting a default URI for stores isn't strictly required.  We could
pass it as the second argument to zstorm.get.  Providing a default URI
makes it possible to use zstorm.get more easily; this is especially
handy when multiple threads are used as we'll see further on.

  >>> store = zstorm.get("test")
  >>> store
  <storm.store.Store object at ...>

ZStorm has automatically created a store instance for us.  If we ask
for a store by name again, we should get the same instance.

  >>> same_store = zstorm.get("test")
  >>> same_store is store
  True

The stores provided by ZStorm are per-thread.  If we ask for the named
store in a different thread we should get a different instance.

  >>> import threading

  >>> thread_store = []
  >>> def get_thread_store():
  ...     thread_store.append(zstorm.get("test"))

  >>> thread = threading.Thread(target=get_thread_store)
  >>> thread.start()
  >>> thread.join()
  >>> thread_store != [store]
  True

Great!  ZStorm abstracts away the process of creating and managing
named stores.  Let's move on and use the stores with Zope's
transaction system.


Committing transactions
-----------------------

The primary purpose of ZStorm is to integrate with Zope's transaction
system.  Let's create a schema so we can play with some real data and
see how it works.

  >>> result = store.execute("""
  ...     CREATE TABLE person (
  ...         id INTEGER PRIMARY KEY,
  ...         name TEXT)
  ... """)
  >>> store.commit()

We'll need a Person class to use with this database.

  >>> from storm.locals import Storm, Int, Unicode

  >>> class Person(Storm):
  ...
  ...     __storm_table__ = "person"
  ...
  ...     id = Int(primary=True)
  ...     name = Unicode()
  ...
  ...     def __init__(self, name):
  ...         self.name = name

Great!  Let's try it out.

  >>> person = Person(u"John Doe")
  >>> store.add(person)
  <Person object at ...>
  >>> transaction.commit()

Notice that we're not using store.commit directly; we're using Zope's
transaction system.  Let's make sure it worked.

  >>> store.rollback()
  >>> same_person = store.find(Person).one()
  >>> same_person is person
  True

Awesome!


Aborting transactions
---------------------

Let's make sure aborting transactions works, too.

  >>> store.add(Person(u"Imposter!"))
  <Person object at ...>

At this point a store.find should return the new object.

  >>> sorted([person.name for person in store.find(Person)])
  [u'Imposter!', u'John Doe']

All this means is that the data has been flushed to the database; it's
still not committed.  If we abort the transaction the new Person
object should disappear.

  >>> transaction.abort()
  >>> [person.name for person in store.find(Person)]
  [u'John Doe']

Excellent!  As you can see, ZStorm makes working with SQL databases
and Zope 3 very natural.


ZCML
----

In the examples above we setup our stores manually.  In many cases,
setting up named stores via ZCML directives is more desirable.  Add a
stanza similar to the following to your ZCML configuration to setup a
named store.

  <store name="test" uri="sqlite:" />

With that in place getUtility(IZStorm).get("test") will return the
store named "test".


Security Wrappers
-----------------

Storm knows how to deal with "wrapped" objects -- the identity of any
Storm-managed object does not need to be the same as the original
object, by way of the "object info" system. As long as the object info
can be retrieved from the wrapped objects, things work fine.

To interoperate with the Zope security wrapper system, storm.zope
tells Zope to exposes certain Storm-internal attributes which appear
on Storm-managed objects.

  >>> from storm.info import get_obj_info, ObjectInfo
  >>> from zope.security.checker import ProxyFactory
  >>> from pprint import pprint

  >>> person = store.find(Person).one()
  >>> type(get_obj_info(person)) is ObjectInfo
  True
  >>> type(get_obj_info(ProxyFactory(person))) is ObjectInfo
  True


ResultSet interfaces
--------------------

Query results provide IResultSet (or ISQLObjectResultSet if SQLObject's
compatibility layer is used).

  >>> from storm.zope.interfaces import IResultSet, ISQLObjectResultSet
  >>> from storm.store import EmptyResultSet, ResultSet
  >>> from storm.sqlobject import SQLObjectResultSet
  >>> IResultSet.implementedBy(ResultSet)
  True
  >>> IResultSet.implementedBy(EmptyResultSet)
  True

  >>> ISQLObjectResultSet.implementedBy(SQLObjectResultSet)
  True

# vim:ts=4:sw=4:et