[PEAK] Newbie Question
Phillip J. Eby
pje at telecommunity.com
Fri Dec 5 18:14:31 EST 2003
At 02:00 PM 12/5/03 +0000, William Trenker wrote:
>But I can't grok how to get it to work in Python. Here's a small example:
>
>Python 2.3.2 (#1, Oct 27 2003, 10:19:56)
>[GCC 2.95.3 20010315 (release)] on linux2
>Type "help", "copyright", "credits" or "license" for more information.
> >>> from peak.api import *
> >>> db=binding.bindTo('sqlite:foo.bar')
bindTo is deprecated; please use 'Obtain' instead.
> >>> type(db)
><class 'peak.binding.components.Obtain'>
> >>> db
>binding.Obtain(Base(body='foo.bar',scheme='sqlite'))
binding.Descriptors like Obtain, Make, and Require all have to be used in a
class. They are descriptors, like the Python builtin
'property'. Basically, what you're doing here is the equivalent of:
>>> db = property(lookupSomeDB)
>>> db
<property object>
You need to put this in a class, and then access the attribute of the
instance to use it, just like you would a property.
>Here's the silly part, I don't know how to figure out what method to use
>on the db object to feed it a simple SQL statmement. The advice given in
>this list to other newbies is to read the interfaces.py file for the
>object, but what object? The db variable is bound to a
>peak.binding.components.Obtain for which the interfaces file isn't going
>to document a method for firing off some SQL. But somewhere the Obtain
>object is bound internally to some sort of database object that probably
>does have appropriate methods documented in an interfaces file. In other
>words, I think where I'm stuck is to know how to use PEAK to introspect
>the db object and work my way down to the actual underlying database class
>so I can figure out which module it comes from. Then I'll know where to
>look in the source files for documentation.
The problem is that you don't actually have a db object here, you just have
an object that can look one up. Here's some simple code to get a real db
object:
>>> root = config.makeRoot()
>>> db = root.lookupComponent('sqlite:foo.bar')
>>> db
<SqliteConnection object at 75304754>
>When I noticed that the type of my db object was actually a class, I
>thought maybe I can only use binding.bindTo in a subclass of a
>binding.Component, so I tried the following (sorry for the long traceback):
>
>Python 2.3.2 (#1, Oct 27 2003, 10:19:56)
>[GCC 2.95.3 20010315 (release)] on linux2
>Type "help", "copyright", "credits" or "license" for more information.
> >>> from peak.api import *
> >>> class myDB(binding.Component):
>.. db = binding.bindTo('sqlite:foo.bar')
>..
> >>> x=myDB()
>[traceback snipped]
> File
> "/usr/local/lib/python2.3/site-packages/peak/config/interfaces.py", line
> 102, in propertyNotFound
> raise exceptions.InvalidRoot(
>peak.exceptions.InvalidRoot: Root component <__main__.myDB object at
>0x4044d52c> does not implement 'IConfigurationRoot' (was looking up
>peak.naming.initialContextFactory for <__main__.myDB object at 0x4044d52c>)
>
>Obviously I'm way off-track here. Can someone get me back into reality?
Actually, you're quite close here. All that you're missing is that your
'myDB' object doesn't have a parent component. It needs a root, e.g.:
>>> root = config.makeRoot()
>>> x = myDB(root)
>>> x.db
<SqliteConnection object at 75304754>
The root component is important, because it supplies configuration context
for all its child components. In particular, it loads 'peak.ini' and any
config files specified by PEAK_CONFIG. These configuration files define
(for example) how to look up an 'sqlite:' URL, and a great many other things.
Anyway, the interface you're looking for is ISQLConnection in
peak.storage.interfaces. It's a subclass of IManagedConnection, which
offers this method:
def __call__(*args, **kw):
"""Return a (possibly initialized) ICursor
Creates a new ICursor instance initialized with the passed
keyword arguments. If positional arguments are supplied,
they are passed to the new cursor's 'execute()' method before
it is returned.
This method is the primary way of interacting with a connection;
either you'll pass positional arguments and receive an
initialized and iterable cursor, or you'll call with no arguments
or keywords only to receive a cursor that you can use to perform
more "low-level" interactions with the database.
"""
So, executing 'x.db("some sql")' will return you a cursor, which will have
had its execute() method called with "some sql". You will then have a
storage.ICursor to play with.
More information about the PEAK
mailing list