<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>boodebr</title>
        <link>http://www.boodebr.org/pages/boodebr</link>
        <description>A little library from boodebr.org</description>
        <lastBuildDate>Sun, 15 Jan 2012 23:18:00 +0000</lastBuildDate>
        <generator>WikklyText 1.9.4</generator>
        <docs>http://blogs.law.harvard.edu/tech/rss</docs>
        <atom:link href="http://www.boodebr.org/pages/boodebr/rss.xml" rel="self" type="application/rss+xml" />        <item>
            <title>boodebr</title>
            <link>http://www.boodebr.org/pages/boodebr/boodebr.html</link>
            <description><![CDATA[The boodebr library is collection of modules I've developed here and there and finally bundled together.<br/><br/>You might be interested in the <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/RecentChanges.html" >RecentChanges</a>.<br/><br/><h3 class="wikkly-h3">Contents</h3> <ul class="wikkly-ul"><li class="wikkly-ul-li1"><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.ion.html" >ion</a>: Pickling of objects to JSON or XML </li><li class="wikkly-ul-li1"><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.config.html" >config</a>: Configuration files in the spirit of .INI files, but using either JSON or XML. Much more flexible and easier to use than <a title="Link to http://docs.python.org" class="wikkly-a-www" href="http://docs.python.org/lib/module-ConfigParser.html" onclick="window.open(this.href);return false;">ConfigParser</a> </li><li class="wikkly-ul-li1"><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.sql.html" >sql</a>: Convenience wrapper for SQLite and APSW. <br/>Includes the multithreading-friendly <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.sql.sqliteQ.html" >boodebr.sql.sqliteQ</a> </li><li class="wikkly-ul-li1"><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.sql2.html" >sql2</a>: Common API for APSW, pysqlite and MySQL, with a focus on portable semantics and stability under high loads. <i class="">Considered beta quality for now; will eventually supercede <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.sql.html" >boodebr.sql</a></i> </li><li class="wikkly-ul-li1"><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.util.html" >util</a>: General utility functions </li><li class="wikkly-ul-li1"><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.disthelper.html" >disthelper</a>: Utilities that are useful when writing setup files, including replacements for some commonly needed POSIX tools. </li><li class="wikkly-ul-li1"><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.pyconfig.html" >pyconfig</a>: Dynamic introspection of the Python interpreter capabilities </li><li class="wikkly-ul-li1"><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.gui.html" >gui</a>: A convenience wrapper for <a title="Link to http://wxpython.org" class="wikkly-a-www" href="http://wxpython.org" onclick="window.open(this.href);return false;">wxPython</a>. </li><li class="wikkly-ul-li1"><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/license.html" >license</a>: The boodebr library is distributed under an OpenSource license </li></ul>   <h3 class="wikkly-h3">Installation</h3><br/><div class="wikkly-indent" > <i class=""><b class="">Requires</b>: Python 2.3 or higher. <br/><b class="">Optional</b>: <a title="Link to http://www.egenix.com" class="wikkly-a-www" href="http://www.egenix.com/products/python/mxBase/" onclick="window.open(this.href);return false;">egenix mxBase</a>, <a title="Link to http://www.initd.org" class="wikkly-a-www" href="http://www.initd.org/tracker/pysqlite" onclick="window.open(this.href);return false;">pysqlite</a>, <a title="Link to http://www.wxpython.org" class="wikkly-a-www" href="http://www.wxpython.org/" onclick="window.open(this.href);return false;">wxPython</a></i> </div><br/><br/>If you already have <a title="Link to http://cheeseshop.python.org" class="wikkly-a-www" href="http://cheeseshop.python.org/pypi/setuptools/" onclick="window.open(this.href);return false;">setuptools</a> installed, then  just do: <div class="wikkly-code-block">easy_install&nbsp;-U&nbsp;boodebr&nbsp;</div><br/><br/>If not, download the sources:  <table class="wikkly-table"><tr class="wikkly-tr"><th class="wikkly-th" colspan="2" rowspan="1" style="text-align: center;">Current Stable Release</th></tr><tr class="wikkly-tr"><th class="wikkly-th" colspan="1" rowspan="1" style="text-align: center;">Source (.zip)</th><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <a title="Link to http://boodebr.googlecode.com" class="wikkly-a-www" href="http://boodebr.googlecode.com/files/boodebr-1.5.1.zip" onclick="window.open(this.href);return false;">boodebr-1.5.1.zip</a> </td></tr><tr class="wikkly-tr"><th class="wikkly-th" colspan="1" rowspan="1" style="text-align: center;">Source (.tar.gz)</th><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <a title="Link to http://boodebr.googlecode.com" class="wikkly-a-www" href="http://boodebr.googlecode.com/files/boodebr-1.5.1.tar.gz" onclick="window.open(this.href);return false;">boodebr-1.5.1.tar.gz</a> </td></tr></table> Unpack and install: <div class="wikkly-code-block">python&nbsp;setup.py&nbsp;install</div><br/><br/>]]></description>
            <guid isPermaLink="false">8f29fc5bfde4b78ee17a04e4c7343895bbfcb01b</guid>
            <pubDate>Sun, 15 Jan 2012 23:18:00 +0000</pubDate>
        </item>
        <item>
            <title>RecentChanges</title>
            <link>http://www.boodebr.org/pages/boodebr/RecentChanges.html</link>
            <description><![CDATA[<h3 class="wikkly-h3">Version 1.5.1 (2010-09-06)</h3> <ul class="wikkly-ul"><li class="wikkly-ul-li1">boodebr.sql2: <ul class="wikkly-ul"><li class="wikkly-ul-li2">Warn on mixed-case table names (not portable) </li><li class="wikkly-ul-li2">Removed BLOB type, not portable </li><li class="wikkly-ul-li2">Use InnoDB tables by default for MySQL<br/><br/></li></ul></li></ul><h3 class="wikkly-h3">Version 1.5.0 (2009-09-26)</h3> <ul class="wikkly-ul"><li class="wikkly-ul-li1">boodebr.sql: Added sqliteConn with same API as sqliteQ for non-threaded use. </li><li class="wikkly-ul-li1">boodebr.util.locking: Add <span class="wikkly-code-inline">.lock</span> to lockfiles so it is easy to find them.<br/><br/></li></ul><h3 class="wikkly-h3">Version 1.4.1 (2009-08-16)</h3> <ul class="wikkly-ul"><li class="wikkly-ul-li1">Added missing import that prevented <span class="wikkly-code-inline">disthelper/scripts/rmfind.py</span> from working.<br/><br/></li></ul><h3 class="wikkly-h3">Version 1.4.0 (2009-07-14)</h3> <ul class="wikkly-ul"><li class="wikkly-ul-li1">Added C version of JSON deserializer<br/><br/></li></ul><h3 class="wikkly-h3">Version 1.3.0 (2008-08-06)</h3> <ul class="wikkly-ul"><li class="wikkly-ul-li1">Added multithread/multiprocess locking semantics, <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.util.locking.html" >boodebr.util.locking</a> </li><li class="wikkly-ul-li1">Updated <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.config.html" >boodebr.config</a> to use file locking. </li><li class="wikkly-ul-li1">makeGUID() can be called with no args </li><li class="wikkly-ul-li1">New module <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.util.modules.html" >boodebr.util.modules</a> </li><li class="wikkly-ul-li1">Fixes in <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.sql.html" >boodebr.sql</a> to enhance stability under high load </li><li class="wikkly-ul-li1">New module <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.sql2.html" >boodebr.sql2</a> (<i class="">considered beta quality for now; will eventually replace boodebr.sql</i>) </li><li class="wikkly-ul-li1">New module <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.util.threadQ.html" >boodebr.util.threadQ</a> provides serialization of method calls across threads.<br/><br/></li></ul><h3 class="wikkly-h3">Version 1.2.0 (2008-06-08)</h3><br/>This is a minor feature release with a few bugfixes as well. <ul class="wikkly-ul"><li class="wikkly-ul-li1"><span class="wikkly-tt">boodebr.gui</span> <ul class="wikkly-ul"><li class="wikkly-ul-li2">Redid stock images as SVG.  </li><li class="wikkly-ul-li2">Embed stock images via img2py for easier use with py2exe. </li><li class="wikkly-ul-li2">Synced fixed_colsorter.py with wxPython 2.8.7.1 </li></ul></li><li class="wikkly-ul-li1"><span class="wikkly-tt">boodebr.ion</span>: Added support for pickling of complex numbers. </li><li class="wikkly-ul-li1"><span class="wikkly-tt">boodebr.config</span>: Added file_exits() to fileconfig objects. </li><li class="wikkly-ul-li1">Moved test suite down one level in tree.<br/><br/></li></ul><h3 class="wikkly-h3">Version 1.1.0 (2008-03-01)</h3><br/>This release adds several table-altering methods to sqliteQ. These routines provide replacements for functionality that is missing from SQLite's native <span class="wikkly-code-inline">ALTER&nbsp;TABLE</span> implementation. This functionality is already available in <span class="wikkly-tt">boodebr.sql.sqlite_util</span> but has now be brought up to the sqliteQ layer.<br/><br/>Added in this release are: <ul class="wikkly-ul"><li class="wikkly-ul-li1"><span class="wikkly-tt">sqliteQ.add_table_column</span> </li><li class="wikkly-ul-li1"><span class="wikkly-tt">sqliteQ.delete_table</span> </li><li class="wikkly-ul-li1"><span class="wikkly-tt">sqliteQ.delete_table_columns</span> </li><li class="wikkly-ul-li1"><span class="wikkly-tt">sqliteQ.get_table_columns</span> </li><li class="wikkly-ul-li1"><span class="wikkly-tt">sqliteQ.modify_table_column</span> </li><li class="wikkly-ul-li1"><span class="wikkly-tt">sqliteQ.rename_table</span><br/><br/></li></ul>See <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.sql.sqliteQ.html" >boodebr.sql.sqliteQ</a> for more.<br/><br/><h3 class="wikkly-h3">Version 1.0.0 (2008-02-19)</h3>  <ul class="wikkly-ul"><li class="wikkly-ul-li1"><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.sql.sqliteQ.html" >boodebr.sql.sqliteQ</a> <ul class="wikkly-ul"><li class="wikkly-ul-li2">New module for sharing SQLite connections across multiple threads. </li></ul></li><li class="wikkly-ul-li1"><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.util.guid.html" >boodebr.util.guid</a>  <ul class="wikkly-ul"><li class="wikkly-ul-li2">A simple module for creating unique identifiers. </li></ul></li><li class="wikkly-ul-li1"><span class="wikkly-highlight">API change</span>:  <ul class="wikkly-ul"><li class="wikkly-ul-li2"><span class="wikkly-tt">boodebr.sql.sqlite_util.get_tables()</span> no longer returns special <span class="wikkly-tt">sqlite_*</span> tables names. Pass <span class="wikkly-code-inline">special=True</span> to get the previous behavior. </li></ul></li><li class="wikkly-ul-li1">Other small bugfixes<br/><br/></li></ul><h3 class="wikkly-h3">Version 0.9 (2008-01-21)</h3>  <ul class="wikkly-ul"><li class="wikkly-ul-li1"><b class=""><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.ion.html" >boodebr.ion</a></b>: <ul class="wikkly-ul"><li class="wikkly-ul-li2">An object can define <span class="wikkly-tt">__ionize__()</span> if it just wants to flatten itself for pickling and doesn't care about being rebuilt in deionize(). </li><li class="wikkly-ul-li2">ionize() now takes <span class="wikkly-tt">flatten_only</span> parameter which strips out any extra attributes added during pickling (in case you are sending data to a JSON client that can't handle them).<br/><br/></li></ul></li></ul><ul class="wikkly-ul"><li class="wikkly-ul-li1"><b class=""><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.config.html" >boodebr.config</a></b>:   <ul class="wikkly-ul"><li class="wikkly-ul-li2">fileconfig is now threadsafe. </li><li class="wikkly-ul-li2">Make paths as needed when saving config file.<br/><br/></li></ul></li></ul><ul class="wikkly-ul"><li class="wikkly-ul-li1"><b class=""><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.gui.html" >boodebr.gui</a></b>:  <ul class="wikkly-ul"><li class="wikkly-ul-li2">This is a new module (a convenience layer for <a title="Link to http://wxpython.org" class="wikkly-a-www" href="http://wxpython.org" onclick="window.open(this.href);return false;">wxPython</a>).<br/><br/></li></ul></li></ul><ul class="wikkly-ul"><li class="wikkly-ul-li1"><b class=""><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.sql.html" >boodebr.sql</a></b>:  <ul class="wikkly-ul"><li class="wikkly-ul-li2">Marked fpmsql.run() obsolete (does nothing that query() doesn't do). </li><li class="wikkly-ul-li2">Added defaults so that fpmsql() can be called with just a filename argument.<br/><br/></li></ul></li></ul><ul class="wikkly-ul"><li class="wikkly-ul-li1">Other bugfixes<br/><br/></li></ul><h3 class="wikkly-h3">Version 0.8.1 (2007-11-11)</h3><br/>Initial public release. ]]></description>
            <guid isPermaLink="false">aeb3fa49552f72d60aee0b2e37eccfadd77e7259</guid>
            <pubDate>Tue, 07 Sep 2010 01:56:00 +0000</pubDate>
        </item>
        <item>
            <title>boodebr.ion</title>
            <link>http://www.boodebr.org/pages/boodebr/boodebr.ion.html</link>
            <description><![CDATA[<span class="wikkly-tt">boodebr.ion</span> is a serialization library. It follows the JSON (RFC 4627) data model, but can read &amp; write either JSON or XML. In addition, it provides a simple hook system that implements full object pickling (within the limitations of RFC 4627) while remaining 100% JSON compatible.<br/><br/>Quick start:  <div class="wikkly-code-block">from&nbsp;boodebr.ion&nbsp;import&nbsp;ionize,&nbsp;deionize<br/><br/>#&nbsp;pickle&nbsp;object&nbsp;'obj'&nbsp;to/from&nbsp;JSON<br/>json&nbsp;=&nbsp;ionize(obj)&nbsp;#&nbsp;'json'&nbsp;is&nbsp;the&nbsp;default&nbsp;format<br/>obj&nbsp;=&nbsp;deionize(json)<br/><br/>#&nbsp;pickle&nbsp;object&nbsp;'obj'&nbsp;to/from&nbsp;XML<br/>xml&nbsp;=&nbsp;ionize(obj,&nbsp;'xml')<br/>obj&nbsp;=&nbsp;deionize(xml)</div><br/><br/>Links: <ul class="wikkly-ul"><li class="wikkly-ul-li1"><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/ion.api.html" >Pickling API</a> </li><li class="wikkly-ul-li1"><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/ion.hooks.html" >Writing hooks</a> </li><li class="wikkly-ul-li1"><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/IonVsOthers.html" >Comparison of boodebr.ion with other serialization modules</a><br/><br/><div id="disqus_thread"></div><script type="text/javascript" src="http://disqus.com/forums/boodebr-library/embed.js"></script><noscript><a href="http://boodebr-library.disqus.com/?url=ref">View the forum thread.</a></noscript><a href="http://disqus.com" class="dsq-brlink">blog comments powered by <span class="logo-disqus">Disqus</span></a></li></ul>]]></description>
            <guid isPermaLink="false">54efa451dec4dd264ab30b7b92b22a1bea513552</guid>
            <pubDate>Sat, 29 Aug 2009 12:55:00 +0000</pubDate>
        </item>
        <item>
            <title>boodebr.sql2</title>
            <link>http://www.boodebr.org/pages/boodebr/boodebr.sql2.html</link>
            <description><![CDATA[<div ><div class="pydocs-module-box" ><div class="pydocs-module-title" >Module boodebr.sql2.api</div><div class="pydocs-module-doc pydocs-indent" ><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/index.html" >boodebr</a> : <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.sql2.html" >boodebr.sql2</a><br/><br/>SQL2 <br/> <i class="">A common interface for APSW, pysqlite and ~MySQL</i><br/><br/>The goals of this module are: <ul class="wikkly-ul"><li class="wikkly-ul-li1">Portability of code/SQL across database types </li><li class="wikkly-ul-li1">Stability under high load </li><li class="wikkly-ul-li1">Minimal API<br/><br/></li></ul>The goals <b class="">are not</b>: <ul class="wikkly-ul"><li class="wikkly-ul-li1">Efficiency (<i class="">although SQL2 isn't particulary slow, you might prefer using the native interface for optimal performance</i>) </li><li class="wikkly-ul-li1">Supporting every feature (<i class="">only portable semantics are supported; if you need to use   database-specific features, use the native interface instead</i>)<br/><br/><div class="wikkly-notebox" >This module will eventually replace <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.sql.html" >boodebr.sql</a>. It has a very similar API,  yet some API-breaking changes were required to ensure stability under high loads.  Rather than breaking code that uses boodebr.sql, a new module was created.</div></li></ul></div><div class="pydocs-classes-outer" ><div class="pydocs-classes-outer-text" >Classes</div><div class="pydocs-indent" ><div class="pydocs-class-box" ><div class="pydocs-class-title" ><a name="CLASS_SqlBusy" class="wikkly-a-internal"> </a>SqlBusy(Exception)</div><div class="pydocs-class-doc pydocs-indent" >Exception raised when database is busy <b class="">and</b> timeout period has expired.</div><div class="pydocs-methods-outer" ><div class="pydocs-indent" ></div></div></div><div class="pydocs-class-box" ><div class="pydocs-class-title" ><a name="CLASS_SqlBadBinding" class="wikkly-a-internal"> </a>SqlBadBinding(Exception)</div><div class="pydocs-class-doc pydocs-indent" >Exception raised when an invalid type is passed to <span class="wikkly-code-inline">run()</span></div><div class="pydocs-methods-outer" ><div class="pydocs-indent" ></div></div></div><div class="pydocs-class-box" ><div class="pydocs-class-title" ><a name="CLASS_SqlConnection" class="wikkly-a-internal"> </a>SqlConnection(object)</div><div class="pydocs-class-doc pydocs-indent" >Returned by <a title="#FUNC_opensql" class="wikkly-a-internal" href="#FUNC_opensql" >opensql()</a> - do not instantiate directly.</div><div class="pydocs-methods-outer" ><div class="pydocs-indent" ><div class="pydocs-methods-outer-text" >Methods</div><div class="pydocs-method-box" ><div class="pydocs-method-title" >add_table_column(self, table, column, initval=None)</div><div class="pydocs-method-doc pydocs-indent" >Add a column to a table. <dl class="wikkly-dl"><dt class="wikkly-dt">table </dt><dd class="wikkly-dd">Table name </dd><dt class="wikkly-dt">column </dt><dd class="wikkly-dd">(name, type) </dd><dt class="wikkly-dt">initval </dt><dd class="wikkly-dd">Initial value to fill column </dd></dl></div></div><div class="pydocs-method-box" ><div class="pydocs-method-title" >change_table_column(self, table, oldname, newname, newtype=None)</div><div class="pydocs-method-doc pydocs-indent" >Rename a column and/or change the datatype of a column.<br/><br/><dl class="wikkly-dl"><dt class="wikkly-dt">table </dt><dd class="wikkly-dd">Name of table </dd><dt class="wikkly-dt">oldname </dt><dd class="wikkly-dd">Name of column to change </dd><dt class="wikkly-dt">newname </dt><dd class="wikkly-dd">New name for column (can equal oldname). </dd><dt class="wikkly-dt">newtype </dt><dd class="wikkly-dd">New type for column, or None to keep original. </dd></dl></div></div><div class="pydocs-method-box" ><div class="pydocs-method-title" >close(self)</div><div class="pydocs-method-doc pydocs-indent" >Close connection, releasing any locks.</div></div><div class="pydocs-method-box" ><div class="pydocs-method-title" >create_table(self, name, columns)</div><div class="pydocs-method-doc pydocs-indent" >Create a table, (only) if it does not already exist. <dl class="wikkly-dl"><dt class="wikkly-dt">name </dt><dd class="wikkly-dd">Name of table </dd><dt class="wikkly-dt">columns </dt><dd class="wikkly-dd">list of tuples: <span class="wikkly-code-inline">(name,&nbsp;type)</span><br/> 		Where 'type' is one of the basic types (INTEGER, REAL, etc.) </dd></dl></div></div><div class="pydocs-method-box" ><div class="pydocs-method-title" >delete_table(self, name)</div><div class="pydocs-method-doc pydocs-indent" >Permanently delete a table (if it exists) from the named database.</div></div><div class="pydocs-method-box" ><div class="pydocs-method-title" >delete_table_column(self, table, colname)</div><div class="pydocs-method-doc pydocs-indent" >Delete named column from table.</div></div><div class="pydocs-method-box" ><div class="pydocs-method-title" >get_table_colnames(self, table)</div><div class="pydocs-method-doc pydocs-indent" >Get a list of just the column names from table.</div></div><div class="pydocs-method-box" ><div class="pydocs-method-title" >get_table_columns(self, table)</div><div class="pydocs-method-doc pydocs-indent" >Get a list of column names &amp; types for the given table.<br/> Returns a list of tuples <span class="wikkly-code-inline">(colname,&nbsp;coltype)</span> where: <div class="wikkly-indent" ><dl class="wikkly-dl"><dt class="wikkly-dt">colname </dt><dd class="wikkly-dd">Name of column </dd><dt class="wikkly-dt">coltype </dt><dd class="wikkly-dd">The SQL type string (<b class="">not</b> INTEGER, etc., so that arbitrary tables are supported) </dd></dl></div><br/><br/>The list will be in the same order as the order of the SQL statements used to create the table.<br/><br/>Returns [] if table doesn't exist. </div></div><div class="pydocs-method-box" ><div class="pydocs-method-title" >get_tables(self, special=False)</div><div class="pydocs-method-doc pydocs-indent" >Get a list of all tables in the given SQL database. If special==False, removes special names (database-specific). </div></div><div class="pydocs-method-box" ><div class="pydocs-method-title" >has_table(self, name)</div><div class="pydocs-method-doc pydocs-indent" >Convenience - does database contain table?</div></div><div class="pydocs-method-box" ><div class="pydocs-method-title" >last_insert_id(self)</div><div class="pydocs-method-doc pydocs-indent" >Returns the last autoincrement id generated</div></div><div class="pydocs-method-box" ><div class="pydocs-method-title" >rename_table(self, oldname, newname)</div><div class="pydocs-method-doc pydocs-indent" >Rename a table from oldname to newname.</div></div><div class="pydocs-method-box" ><div class="pydocs-method-title" >run(self, stmt, bindings=())</div><div class="pydocs-method-doc pydocs-indent" >Run query and returns <a title="#CLASS_SqlResultSet" class="wikkly-a-internal" href="#CLASS_SqlResultSet" >SqlResultSet</a> or raises: <ul class="wikkly-ul"><li class="wikkly-ul-li1">SqlBusy: Database busy and timed-out waiting. </li><li class="wikkly-ul-li1">Other: API error etc. Should not retry. </li></ul> If called from <span class="wikkly-code-inline">runfunc()</span>, runs as part of current transaction.<br/> Else, runs in its own transaction. </div></div><div class="pydocs-method-box" ><div class="pydocs-method-title" >runfunc(self, func, args=(), kwargs={})</div><div class="pydocs-method-doc pydocs-indent" >Run a user-supplied function inside a transaction. <dl class="wikkly-dl"><dt class="wikkly-dt">func </dt><dd class="wikkly-dd">Function, will be called as: <span class="wikkly-code-inline">func(sql,&nbsp;*args,&nbsp;**kwargs)</span><br/> 		Where <span class="wikkly-code-inline">sql</span> is an <a title="#CLASS_SqlProxy" class="wikkly-a-internal" href="#CLASS_SqlProxy" >SqlProxy</a> for func() to use. </dd><dt class="wikkly-dt">args, kwargs </dt><dd class="wikkly-dd">Args to pass to func.<br/><br/></dd></dl>No return value. On error, raises: <ul class="wikkly-ul"><li class="wikkly-ul-li1">SqlBusy: Database busy and timed-out. </li><li class="wikkly-ul-li1">Other: API error or other error in func(). </li></ul></div></div></div></div></div><div class="pydocs-class-box" ><div class="pydocs-class-title" ><a name="CLASS_SqlResultSet" class="wikkly-a-internal"> </a>SqlResultSet(object)</div><div class="pydocs-class-doc pydocs-indent" >The .run() method returns this. You use it like an iterator to fetch results as rows or objects:<br/><br/>Examples:  <div class="wikkly-code-block">#&nbsp;as&nbsp;rows<br/>for&nbsp;x,y&nbsp;in&nbsp;sql.run('select&nbsp;x,y&nbsp;from&nbsp;foo'):<br/>&nbsp;&nbsp;&nbsp;&nbsp;...<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>#&nbsp;as&nbsp;objects<br/>for&nbsp;obj&nbsp;in&nbsp;sql.run('select&nbsp;*&nbsp;from&nbsp;foo').obj():<br/>&nbsp;&nbsp;&nbsp;&nbsp;print&nbsp;obj.x,&nbsp;obj.y</div> </div><div class="pydocs-methods-outer" ><div class="pydocs-indent" ><div class="pydocs-methods-outer-text" >Methods</div><div class="pydocs-method-box" ><div class="pydocs-method-title" >__init__(self)</div><div class="pydocs-method-doc pydocs-indent" ></div></div><div class="pydocs-method-box" ><div class="pydocs-method-title" >__iter__(self)</div><div class="pydocs-method-doc pydocs-indent" ></div></div><div class="pydocs-method-box" ><div class="pydocs-method-title" >_next(self, itertype, klass=None)</div><div class="pydocs-method-doc pydocs-indent" ></div></div><div class="pydocs-method-box" ><div class="pydocs-method-title" >getobj(self, klass=None)</div><div class="pydocs-method-doc pydocs-indent" >Get next row of result as object, or None if no more data.  Does not change iterator type or iterclass. If klass is None, uses the currently set classtype. </div></div><div class="pydocs-method-box" ><div class="pydocs-method-title" >getrow(self)</div><div class="pydocs-method-doc pydocs-indent" >Get next row of result or None if no more data. Does not change iterator type.</div></div><div class="pydocs-method-box" ><div class="pydocs-method-title" >next(self, klass=None)</div><div class="pydocs-method-doc pydocs-indent" >Get next row or object, depending on currently set iterator type. If iterator is set to return objects, can pass klass to set the returned class (if klass is None, uses the currently set classtype). </div></div><div class="pydocs-method-box" ><div class="pydocs-method-title" >obj(self, klass=&lt;class 'boodebr.sql2.common.SqlResultObj'&gt;)</div><div class="pydocs-method-doc pydocs-indent" >Change iterator to object type and set the class to use for returned objects. </div></div></div></div></div><div class="pydocs-class-box" ><div class="pydocs-class-title" ><a name="CLASS_SqlProxy" class="wikkly-a-internal"> </a>SqlProxy(object)</div><div class="pydocs-class-doc pydocs-indent" >Callbacks passed to runfunc() receive an object of this type. This is the only API that the called function is allowed to access. (Using <span class="wikkly-code-inline">self.sql</span> directly is unsupported.)<br/><br/><a title="#CLASS_SqlProxy" class="wikkly-a-internal" href="#CLASS_SqlProxy" >SqlProxy</a> has the same API as <a title="#CLASS_SqlConnection" class="wikkly-a-internal" href="#CLASS_SqlConnection" >SqlConnection</a> but only supports the following members/functions: <ul class="wikkly-ul"><li class="wikkly-ul-li1">run </li><li class="wikkly-ul-li1">last_insert_id </li><li class="wikkly-ul-li1">INTEGER </li><li class="wikkly-ul-li1">REAL </li><li class="wikkly-ul-li1">TEXT </li><li class="wikkly-ul-li1">AUTO_PRIMARY_KEY </li><li class="wikkly-ul-li1">get_tables </li><li class="wikkly-ul-li1">has_table </li></ul></div><div class="pydocs-methods-outer" ><div class="pydocs-indent" ><div class="pydocs-methods-outer-text" >Methods</div><div class="pydocs-method-box" ><div class="pydocs-method-title" >__getattr__(self, name)</div><div class="pydocs-method-doc pydocs-indent" ></div></div></div></div></div></div></div><div class="pydocs-funcs-outer" ><div class="pydocs-funcs-outer-text" >Functions</div><div class="pydocs-indent" ><div class="pydocs-func-box" ><a name="FUNC_APIs" class="wikkly-a-internal"> </a><div class="pydocs-func-title" ><a name="FUNC_APIs" class="wikkly-a-internal"> </a>APIs()</div><div class="pydocs-func-doc pydocs-indent" >Return list of available APIs (for 'api' arg in opensql)</div></div><div class="pydocs-func-box" ><a name="FUNC_opensql" class="wikkly-a-internal"> </a><div class="pydocs-func-title" ><a name="FUNC_opensql" class="wikkly-a-internal"> </a>opensql(api, *args, **kwargs)</div><div class="pydocs-func-doc pydocs-indent" >Open a database connection. The exact calling sequence depends on the type of database you are opening. All possibilities are shown below: <dl class="wikkly-dl"><dt class="wikkly-dt">APSW </dt><dd class="wikkly-dd"><div class="wikkly-code-block">from&nbsp;boodebr.sql2&nbsp;import&nbsp;*<br/>db&nbsp;=&nbsp;opensql('apsw',&nbsp;filename,&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;binder=binder_raw,&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeout=DEFAULT_LOCK_TIMEOUT,&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;expirelock=DEFAULT_LOCK_LIFETIME)</div> </dd><dt class="wikkly-dt">~MySQL </dt><dd class="wikkly-dd"><div class="wikkly-code-block">from&nbsp;boodebr.sql2&nbsp;import&nbsp;*<br/>db&nbsp;=&nbsp;opensql('mysql',&nbsp;host,&nbsp;db,&nbsp;user,&nbsp;passwd,&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;binder=binder_raw,&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeout=DEFAULT_LOCK_TIMEOUT):</div> </dd><dt class="wikkly-dt">pysqlite </dt><dd class="wikkly-dd"><div class="wikkly-code-block">from&nbsp;boodebr.sql2&nbsp;import&nbsp;*<br/>db&nbsp;=&nbsp;opensql('pysqlite',&nbsp;filename,&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;binder=binder_raw,&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeout=DEFAULT_LOCK_TIMEOUT,&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;expirelock=DEFAULT_LOCK_LIFETIME)</div> </dd></dl></div></div><div class="pydocs-func-box" ><a name="FUNC_versions" class="wikkly-a-internal"> </a><div class="pydocs-func-title" ><a name="FUNC_versions" class="wikkly-a-internal"> </a>versions(api)</div><div class="pydocs-func-doc pydocs-indent" >Get version information for the given API.<br/><br/>Returns a dict containing <i class="">at least</i> these fields: <ul class="wikkly-ul"><li class="wikkly-ul-li1">'module_file': Module filename (native interface) </li><li class="wikkly-ul-li1">'api': Name of API </li><li class="wikkly-ul-li1">'apiversion': Version number string, as '#.#.#'<br/><br/></li></ul>Individual modules may define extra fields. </div></div><div class="pydocs-func-box" ><a name="FUNC_binder_raw" class="wikkly-a-internal"> </a><div class="pydocs-func-title" ><a name="FUNC_binder_raw" class="wikkly-a-internal"> </a>binder_raw(value)</div><div class="pydocs-func-doc pydocs-indent" >Raw binder - performs no conversions. Accepts only types that map trivially to INTEGER, REAL, or TEXT.<br/><br/>This is the default binder used by opensql() </div></div></div></div></div></div><div id="disqus_thread"></div><script type="text/javascript" src="http://disqus.com/forums/boodebr-library/embed.js"></script><noscript><a href="http://boodebr-library.disqus.com/?url=ref">View the forum thread.</a></noscript><a href="http://disqus.com" class="dsq-brlink">blog comments powered by <span class="logo-disqus">Disqus</span></a>]]></description>
            <guid isPermaLink="false">7b7ea604de97f0572f3c9eb5af1e952c80b15f13</guid>
            <pubDate>Thu, 07 Aug 2008 01:15:00 +0000</pubDate>
        </item>
        <item>
            <title>boodebr.util.locking</title>
            <link>http://www.boodebr.org/pages/boodebr/boodebr.util.locking.html</link>
            <description><![CDATA[<div ><div class="pydocs-module-box" ><div class="pydocs-module-title" >Module boodebr.util.locking</div><div class="pydocs-module-doc pydocs-indent" ><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/index.html" >boodebr</a> : <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.util.html" >boodebr.util</a> : <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.util.locking.html" >boodebr.util.locking</a><br/><br/>This module provides multiprocess/multithread safe cooperative(<sup class=""><a title="#FOOT1" class="wikkly-a-internal" href="#FOOT1" >1</a></sup>) locking semantics.<br/><br/><b class="">boodebr.util.locking</b> provides two public functions. <ol class="wikkly-ol"><li class="wikkly-ol-li1"><a title="#FUNC_open_locked" class="wikkly-a-internal" href="#FUNC_open_locked" >open_locked()</a> Open a file for read+write access with an exclusive lock. </li><li class="wikkly-ol-li1"><a title="#FUNC_Locker" class="wikkly-a-internal" href="#FUNC_Locker" >Locker()</a> Lock a name in a caller-defined namespace.<br/><br/><div class="wikkly-notebox" ><b class="">open_locked()</b> uses <b class="">Locker()</b> internally. However, <b class="">Locker()</b> is provided  separately here since it can be useful on its own.</div></li></ol><br/><br/><hr class="wikkly-separator"/><a name="FOOT1" class="wikkly-a-internal"> </a> <sup class="">1. Cooperative locking is the only style of locking that is supported across platforms. <i class="">"Cooperative"</i> means that nothing prevents another process/thread from overwriting the locked object.  Cooperative locking works by having all processes/threads use the same API, i.e. agreeing on locking  rules for a given object.</sup> </div><div class="pydocs-classes-outer" ><div class="pydocs-classes-outer-text" >Classes</div><div class="pydocs-indent" ><div class="pydocs-class-box" ><div class="pydocs-class-title" ><a name="CLASS_CannotGetLock" class="wikkly-a-internal"> </a>CannotGetLock(Exception)</div><div class="pydocs-class-doc pydocs-indent" >Raised by open_locked() when unable to acquire lock.</div><div class="pydocs-methods-outer" ><div class="pydocs-indent" ></div></div></div><div class="pydocs-class-box" ><div class="pydocs-class-title" ><a name="CLASS_LockerFailed" class="wikkly-a-internal"> </a>LockerFailed(Exception)</div><div class="pydocs-class-doc pydocs-indent" >Raised by Locker.lock() when unable to acquire lock.</div><div class="pydocs-methods-outer" ><div class="pydocs-indent" ></div></div></div></div></div><div class="pydocs-funcs-outer" ><div class="pydocs-funcs-outer-text" >Functions</div><div class="pydocs-indent" ><div class="pydocs-func-box" ><a name="FUNC_open_locked" class="wikkly-a-internal"> </a><div class="pydocs-func-title" ><a name="FUNC_open_locked" class="wikkly-a-internal"> </a>open_locked(filename, timeout=10, lockdir=None, expire=300, method='mkdir')</div><div class="pydocs-func-doc pydocs-indent" >Open the given filename for <b class="">READ+WRITE</b> access with an exclusive lock (cooperative locking). File will be created if it does not exist and positioned at start of file if it does. <br/><br/><span class="wikkly-u">Inputs</span> <dl class="wikkly-dl"><dt class="wikkly-dt">filename </dt><dd class="wikkly-dd">File to open, will be created if it does not exist. </dd><dt class="wikkly-dt">timeout </dt><dd class="wikkly-dd">Wait timeout seconds to succeed before raising <a title="#CLASS_CannotGetLock" class="wikkly-a-internal" href="#CLASS_CannotGetLock" >CannotGetLock</a>. </dd><dt class="wikkly-dt">lockdir </dt><dd class="wikkly-dd">Directory to place locking information (defaults to path of filename).<br/><br/></dd></dl><dl class="wikkly-dl"><dt class="wikkly-dt">expire </dt><dd class="wikkly-dd">An expiration time in seconds. Locks older than this may be automatically removed to avoid deadlocks.<br/><br/></dd></dl><dl class="wikkly-dl"><dt class="wikkly-dt">method </dt><dd class="wikkly-dd">The lowlevel method to use for lock creation. Choices are:  				'mkdir': Use mkdir() to create lock. 				'opencreate': Use open(os.O_CREAT..) 				'fake': Fake locking (no locking at all). Mainly for test purposes. 	<br/><br/></dd></dl>Returns file object.<br/><br/><div class="wikkly-notebox" > It is <b class="">strongly recommended</b> that you call <b class="">.close()</b> on the returned fileobj rather than letting it go out of scope and assuming it will be deleted, since there is no guarantee about when that will happen. </div> </div></div><div class="pydocs-func-box" ><a name="FUNC_Locker" class="wikkly-a-internal"> </a><div class="pydocs-func-title" ><a name="FUNC_Locker" class="wikkly-a-internal"> </a>Locker(objname, lockdir, ns='file', timeout=10, expire=300, method='mkdir')</div><div class="pydocs-func-doc pydocs-indent" >Create an opaque multiprocess and multithreading safe cooperative lock. Does not lock a file or any concrete object, but rather creates a lock on  a name within a caller-defined namespace.<br/><br/><span class="wikkly-u"><i class="">Inputs:</i></span> <dl class="wikkly-dl"><dt class="wikkly-dt">objname </dt><dd class="wikkly-dd">Name of object to be locked.<br/> 		<i class="">Although objname can be any string, I recommend <span class="wikkly-u">not</span> using 	file pathnames, since multiple pathnames may be aliased 	to the same file under some operating systems. A recommended usage when using filenames 	is:</i> <span class="wikkly-indent"> <span class="wikkly-code-inline wikkly-indent">lockdir,&nbsp;objname&nbsp;=&nbsp;os.path.split(filename)</span> </span><br/> 		It is up to the caller to ensure the objname is invariant across multiple calls. </dd><dt class="wikkly-dt">lockdir </dt><dd class="wikkly-dd">A directory in which to store locking information. Will be created if 	it does not exist. Note that <b class="">ns:objname</b> must be unique within lockdir. </dd><dt class="wikkly-dt">ns </dt><dd class="wikkly-dd">The object namespace. This is any freeform string. This allows you to have e.g. 	<span class="wikkly-code-inline">(ns='one',&nbsp;objname='foo')</span> and <span class="wikkly-code-inline">(ns='two',&nbsp;objname='foo')</span> be two distinct objects. </dd><dt class="wikkly-dt">timeout </dt><dd class="wikkly-dd">How long to wait on lock before raising <a title="#CLASS_LockerFailed" class="wikkly-a-internal" href="#CLASS_LockerFailed" >LockerFailed</a> (seconds) </dd><dt class="wikkly-dt">expire </dt><dd class="wikkly-dd">Expiration time on lock (seconds). Previously created locks may be broken 	if they are older than this. </dd><dt class="wikkly-dt">method </dt><dd class="wikkly-dd">The lowlevel method to use for lock creation. Choices are:<ul class="wikkly-ul"><li class="wikkly-ul-li1"><span class="wikkly-code-inline">'mkdir'</span>: Use <b class="">mkdir()</b> to create lock. </li><li class="wikkly-ul-li1"><span class="wikkly-code-inline">'opencreate'</span>: Use <b class="">open(os.O_CREAT..)</b> to create lock. </li><li class="wikkly-ul-li1"><span class="wikkly-code-inline">'fake'</span>: Fake locking, mainly for test purposes. </li></ul><br/><br/></dd></dl>Public API: <div class="wikkly-code-block">lock&nbsp;=&nbsp;Locker(..)<br/>lock.lock()<br/>del&nbsp;lock</div><br/><br/>You should <b class="">always</b> explicitly delete locks - do not count on Python to autodelete them when they go out of scope.<br/><br/>Usage: <div class="wikkly-code-block">#&nbsp;Closed&nbsp;form<br/>lock&nbsp;=&nbsp;Locker('abc',&nbsp;'.')<br/>#&nbsp;use&nbsp;nested&nbsp;try..finally&nbsp;for&nbsp;Python&nbsp;&lt;&nbsp;2.5<br/>try:<br/>&nbsp;&nbsp;&nbsp;&nbsp;try:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock.lock()<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;do&nbsp;locked&nbsp;operations&nbsp;..<br/>&nbsp;&nbsp;&nbsp;&nbsp;except&nbsp;LockerFailed:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;locking&nbsp;failed,&nbsp;handle&nbsp;error&nbsp;..<br/>finally:<br/>&nbsp;&nbsp;&nbsp;&nbsp;del&nbsp;lock<br/><br/>#&nbsp;Open&nbsp;form<br/>lock&nbsp;=&nbsp;Locker('abc',&nbsp;'.')<br/>try:<br/>&nbsp;&nbsp;&nbsp;&nbsp;lock.lock()<br/>except&nbsp;LockerFailed:<br/>&nbsp;&nbsp;&nbsp;&nbsp;..&nbsp;locking&nbsp;failed,&nbsp;handle&nbsp;error&nbsp;..<br/>&nbsp;&nbsp;&nbsp;&nbsp;del&nbsp;lock<br/>&nbsp;&nbsp;&nbsp;&nbsp;return<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>..&nbsp;continue&nbsp;with&nbsp;locked&nbsp;operation&nbsp;...<br/>..&nbsp;eventually&nbsp;doing&nbsp;..<br/>del&nbsp;lock</div> </div></div></div></div></div></div><div id="disqus_thread"></div><script type="text/javascript" src="http://disqus.com/forums/boodebr-library/embed.js"></script><noscript><a href="http://boodebr-library.disqus.com/?url=ref">View the forum thread.</a></noscript><a href="http://disqus.com" class="dsq-brlink">blog comments powered by <span class="logo-disqus">Disqus</span></a>]]></description>
            <guid isPermaLink="false">78aecc7b251c1793a2e25249836025a1409d7dae</guid>
            <pubDate>Thu, 07 Aug 2008 01:14:00 +0000</pubDate>
        </item>
        <item>
            <title>Sql2: Portability</title>
            <link>http://www.boodebr.org/pages/boodebr/Sql2- Portability.html</link>
            <description><![CDATA[These notes provide tips for writing portable SQL with boodebr.sql2.<br/><br/>To aid in portability, boodebr.sql2 limits the builtin datatypes to those in the following table:<br/><br/><table class="wikkly-table"><tr class="wikkly-tr"><th class="wikkly-th" colspan="1" rowspan="1" style="text-align: center;"> SQL    </th><th class="wikkly-th" colspan="1" rowspan="1" style="text-align: center;"> To DB<br/><i class="">Passed <span class="wikkly-u">to</span> database from Python</i>      </th><th class="wikkly-th" colspan="1" rowspan="1" style="text-align: center;"> From DB<br/><i class="">Passed <span class="wikkly-u">from</span> database to Python</i> </th></tr><tr class="wikkly-tr"><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> INTEGER </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> int,long    </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> int,long </td></tr><tr class="wikkly-tr"><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> REAL    </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> float       </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> float    </td></tr><tr class="wikkly-tr"><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> TEXT    </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> str,unicode </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> unicode  </td></tr><tr class="wikkly-tr"><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> BLOB    </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> buffer      </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> str      </td></tr><tr class="wikkly-tr"><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> NULL    </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> None        </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> None     </td></tr></table><div class="wikkly-notebox" >Notes: <ul class="wikkly-ul"><li class="wikkly-ul-li1">Some of the types change between passing <b class="">to</b> and <b class="">from</b> the database. This is required for portability between lowlevel APIs, beyond the control of boodebr.sql2 </li><li class="wikkly-ul-li1">You can write a custom converter to support more types, but the converter must output one of the basic types listed above.</li></ul></div><br/><br/>Portability tips: <ul class="wikkly-ul"><li class="wikkly-ul-li1">Always use <span class="wikkly-code-inline">'?'</span> as the placeholder for values in query strings. It will be converted as needed. </li><li class="wikkly-ul-li1">Avoid hardcoding typenames in CREATE TABLE. The below example shows how to create a table using, all available types: <div class="wikkly-code-block">from&nbsp;boodebr.sql2&nbsp;import&nbsp;*<br/><br/>sql&nbsp;=&nbsp;opensql(..)<br/>sql.create_table('foo',&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[('id',&nbsp;AUTO_PRIMARY_KEY),<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;('an_int',&nbsp;INTEGER),&nbsp;('a_float',&nbsp;REAL),<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;('a_text',&nbsp;TEXT),&nbsp;('a_blob',&nbsp;BLOB)])</div> </li><li class="wikkly-ul-li1">Use INSERT like this: <div class="wikkly-code-block">INSERT&nbsp;into&nbsp;tablename&nbsp;(a,b,c)&nbsp;values&nbsp;(?,?,?)</div> </li><li class="wikkly-ul-li1">Do NOT use the following statements inside a transaction (they cannot be portably rolled back): <ul class="wikkly-ul"><li class="wikkly-ul-li2">CREATE TABLE </li><li class="wikkly-ul-li2">DROP TABLE </li><li class="wikkly-ul-li2">ALTER TABLE </li></ul></li></ul>]]></description>
            <guid isPermaLink="false">20d1b5c4a50b32737ee3857b1ec58643ed8b559e</guid>
            <pubDate>Thu, 07 Aug 2008 01:11:00 +0000</pubDate>
        </item>
        <item>
            <title>boodebr.pyconfig</title>
            <link>http://www.boodebr.org/pages/boodebr/boodebr.pyconfig.html</link>
            <description><![CDATA[This module essentially performs introspection on the Python interpreter itself, to discover which language features are available.<br/><br/><h3 class="wikkly-h3">Usage notes:</h3><br/>The recommended way to use this module is: <div class="wikkly-code-block">from&nbsp;boodebr.pyconfig&nbsp;import&nbsp;pyconfig&nbsp;&nbsp;#&nbsp;or&nbsp;'import&nbsp;*'<br/><br/>if&nbsp;pyconfig.Have_Iterators():<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...</div><br/><br/>Using the 'pyconfig' object like this auto-caches results so you can use the function calls inline without a speed penalty of rerunning the test each time.<br/><br/><h3 class="wikkly-h3">Background/rationale:</h3><br/>At first glance, this module seems odd &mdash; why not just check sys.version_info? Well, for example:<br/><br/><ul class="wikkly-ul"><li class="wikkly-ul-li1">You could be running under a nonstandard/alternative Python implementation (e.g. Jython, or maybe a cut-down embedded version that eliminated some features) and you want to dynamically figure out what is available.<br/><br/></li></ul><ul class="wikkly-ul"><li class="wikkly-ul-li1">It seems more self-documenting to write something like: <div class="wikkly-code-block">&nbsp;&nbsp;&nbsp;&nbsp;<br/>if&nbsp;Have_Iterators():<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;do&nbsp;something&nbsp;with&nbsp;iterators&nbsp;...</div> Than to write: <div class="wikkly-code-block">&nbsp;&nbsp;&nbsp;&nbsp;<br/>if&nbsp;sys.version_info[0]&nbsp;&gt;=&nbsp;2&nbsp;and&nbsp;sys.version_info[1]&nbsp;&gt;=&nbsp;2:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;do&nbsp;something&nbsp;with&nbsp;iterators&nbsp;...</div> In other words, your code now says "here is the capability I need", making it more maintainable down the road than a hardcoded version match. Plus, it is more robust in the presence of a nonstandard interpreter.<br/><br/></li></ul><ul class="wikkly-ul"><li class="wikkly-ul-li1">You're writing an installer, and want to pick different modules to install, based on platform.<br/><br/></li></ul><ul class="wikkly-ul"><li class="wikkly-ul-li1">Some oddball (or future) version of Python might break sys.version_info (expand the number of values, etc.), so you don't want to rely on it.<br/><br/><div id="disqus_thread"></div><script type="text/javascript" src="http://disqus.com/forums/boodebr-library/embed.js"></script><noscript><a href="http://boodebr-library.disqus.com/?url=ref">View the forum thread.</a></noscript><a href="http://disqus.com" class="dsq-brlink">blog comments powered by <span class="logo-disqus">Disqus</span></a></li></ul>]]></description>
            <guid isPermaLink="false">1cf47cfdf7971cf4b5aa4c755d1e817cd648e2c3</guid>
            <pubDate>Mon, 04 Aug 2008 01:36:00 +0000</pubDate>
        </item>
        <item>
            <title>ion.hooks</title>
            <link>http://www.boodebr.org/pages/boodebr/ion.hooks.html</link>
            <description><![CDATA[<span class="wikkly-tt">boodebr.ion</span> uses a simple object-in/object-out hook system to allow serializing objects that RFC 4627 wouldn't otherwise allow. <br/><br/><h3 class="wikkly-h3">ionization hooks</h3><br/>The <span class="wikkly-tt">ionize()</span> API is: <div class="wikkly-code-block">ionize(obj,&nbsp;format='json',&nbsp;indent=True,&nbsp;userhooks=None,&nbsp;flatten_only=False):</div><br/><br/>The <span class="wikkly-tt">userhooks</span> parameter allows you to pass a list of hooks to be used during serialization. This is simply a list of functions as defined below. Whenever <span class="wikkly-tt">boodebr.ion</span> is unable to serialize an object, the object is passed to the hooks to see if any of them want to handle it. If so, the hook should convert it to a serializable type.<br/><br/>Hooks are called as: <div class="wikkly-indent" > <b class="">(handled, name, obj) = hook(obj)</b> </div>    Where: <div class="wikkly-indent" ><dl class="wikkly-dl"><dt class="wikkly-dt">handled: </dt><dd class="wikkly-dd">True/False if hook handled/modified obj. </dd><dt class="wikkly-dt">name: </dt><dd class="wikkly-dd">Name of this hook (used during deionization). Can be <b class="">None</b> if you don't need a deionization hook to be called.  <div class="wikkly-block-indent"> Only used if <b class="">handled==True</b> </div> </dd><dt class="wikkly-dt">obj: </dt><dd class="wikkly-dd">The modified object. <br/><br/> Can by <b class="">any</b> Python object, but dicts are most useful since you can cause a hook to be called during deserialization (i.e. to recreate the original object).  <div class="wikkly-block-indent"> Only used if <b class="">handled==True</b> </div> </dd></dl></div><br/><br/>Any hooks you pass will be called <i class="">before</i> the builtin hooks, so that you can override any builtin behavior you want to.<br/><br/><span class="wikkly-tt">boodebr.ion</span>'s builtin hooks are located in the package <span class="wikkly-tt">boodebr.ion.hooks</span>, if you want to use them as a reference.<br/><br/><h3 class="wikkly-h3">deionization</h3><br/>The <span class="wikkly-tt">deionize()</span> API is: <div class="wikkly-code-block">obj&nbsp;=&nbsp;deionize(buf,&nbsp;userhooks=None)</div><br/><br/>The <span class="wikkly-tt">userhooks</span> parameter is a dictionary mapping names to hook functions. The names are the names returned by the ionization hooks. For example, if your ionization hook returned <span class="wikkly-tt">name='MyHook'</span>, then you would pass <span class="wikkly-tt">userhooks={'MyHook': my_deionize_hook}​</span>. As with <span class="wikkly-tt">ionize</span>, any hooks you pass will override the builtin hooks.<br/><br/>Hooks are called as: <div class="wikkly-indent" > <b class="">obj = hook(mod_obj)</b> </div>  Where:  <div class="wikkly-indent" ><dl class="wikkly-dl"><dt class="wikkly-dt">mod_obj </dt><dd class="wikkly-dd">The object that the ionization hook returned. </dd></dl></div>  Returns the (presumably) recreated object.<br/><br/><h3 class="wikkly-h3">Brief example</h3><br/>A brief example to demonstrate.<br/><br/>Here is a generic pair of hooks: <div class="wikkly-code-block">from&nbsp;boodebr.ion.hooks&nbsp;import&nbsp;ignore<br/><br/>def&nbsp;ionize_hook(obj):<br/>&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;decide&nbsp;if&nbsp;I&nbsp;want&nbsp;to&nbsp;handle&nbsp;'obj'&nbsp;...<br/>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;dont_want_object(obj):<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;ignore()<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;turn&nbsp;obj&nbsp;into&nbsp;mod_obj&nbsp;...<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(True,&nbsp;'MyHookName',&nbsp;mod_obj)<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>def&nbsp;deionize_hook(mod_obj):<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;do&nbsp;work&nbsp;to&nbsp;recreate&nbsp;original&nbsp;obj&nbsp;from&nbsp;mod_obj&nbsp;...<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;obj</div><br/><br/>To use the hooks you would do:  <div class="wikkly-code-block">s&nbsp;=&nbsp;ionize(obj,&nbsp;userhooks=[ionize_hook])<br/>obj&nbsp;=&nbsp;deionize(s,&nbsp;userhooks={'MyHookName':&nbsp;deionize_hook})</div><br/><br/><h3 class="wikkly-h3">Adding <span class="wikkly-tt">__ionize__()</span></h3><br/>If you simply want to flatten your data, i.e. for sending to a JSON client, you can avoid writing a full-blown hook by adding an <span class="wikkly-tt">__ionize__()</span> function to your objects.<br/><br/>A simple example: <div class="wikkly-code-block">class&nbsp;ObjA(object):<br/>&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;__init__(self,&nbsp;a,&nbsp;b,&nbsp;c):<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.a&nbsp;=&nbsp;a<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.b&nbsp;=&nbsp;b<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.c&nbsp;=&nbsp;c<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;__ionize__(self):<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;flatten&nbsp;myself&nbsp;to&nbsp;a&nbsp;dict&nbsp;(can&nbsp;be&nbsp;any&nbsp;object)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;{'A':&nbsp;self.a,&nbsp;'B':&nbsp;self.b,&nbsp;'C':&nbsp;self.c}<br/><br/>from&nbsp;boodebr.ion&nbsp;import&nbsp;ionize<br/>print&nbsp;"Result"<br/>print&nbsp;ionize(ObjA(1,'222',&nbsp;33.333))</div><br/><br/><div id="disqus_thread"></div><script type="text/javascript" src="http://disqus.com/forums/boodebr-library/embed.js"></script><noscript><a href="http://boodebr-library.disqus.com/?url=ref">View the forum thread.</a></noscript><a href="http://disqus.com" class="dsq-brlink">blog comments powered by <span class="logo-disqus">Disqus</span></a>]]></description>
            <guid isPermaLink="false">9fea18a085c248f78f9d7825ef366366e6e1ae8d</guid>
            <pubDate>Mon, 04 Aug 2008 01:35:00 +0000</pubDate>
        </item>
        <item>
            <title>IonVsOthers</title>
            <link>http://www.boodebr.org/pages/boodebr/IonVsOthers.html</link>
            <description><![CDATA[<span class="wikkly-tt">boodebr.ion</span> is designed to be a middle-ground between simple JSON serialization (which doesn't preserve full class information) and the "industrial strength" <a title="Link to http://freshmeat.net" class="wikkly-a-www" href="http://freshmeat.net/projects/gnosisxml/" onclick="window.open(this.href);return false;">{{tt{xml.pickle}}}</a> (which is overkill for many applications). The comparison chart below highlights the key differences.<br/><br/><table class="wikkly-table"><tr class="wikkly-tr"><th class="wikkly-th" colspan="1" rowspan="1" style="text-align: center;">Topic</th><th class="wikkly-th" colspan="1" rowspan="1" style="text-align: center;">pickle</th><th class="wikkly-th" colspan="1" rowspan="1" style="text-align: center;">JSON</th><th class="wikkly-th" colspan="1" rowspan="1" style="text-align: center;"><span class="wikkly-tt">boodebr.ion</span></th><th class="wikkly-th" colspan="1" rowspan="1" style="text-align: center;"><span class="wikkly-tt">xml.pickle</span></th></tr><tr class="wikkly-tr"><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: left;">True object pickling? <sup class=""><a title="#NOTE1" class="wikkly-a-internal" href="#NOTE1" >1</a></sup></td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:green; font-weight: bold;"> YES</span> </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:red; font-weight: bold;"> NO</span> </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:green; font-weight: bold;"> YES</span> </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:green; font-weight: bold;"> YES</span> </td></tr><tr class="wikkly-tr"><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: left;">Strict typing? <sup class=""><a title="#NOTE2" class="wikkly-a-internal" href="#NOTE2" >2</a></sup></td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:green; font-weight: bold;"> YES</span> </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:red; font-weight: bold;"> NO</span> </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:red; font-weight: bold;"> NO</span> </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:green; font-weight: bold;"> YES</span> </td></tr><tr class="wikkly-tr"><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: left;">Maintains referential integrity? <sup class=""><a title="#NOTE3" class="wikkly-a-internal" href="#NOTE3" >3</a></sup></td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:green; font-weight: bold;"> YES</span> </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:red; font-weight: bold;"> NO</span> </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:red; font-weight: bold;"> NO</span> </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:green; font-weight: bold;"> YES</span> </td></tr><tr class="wikkly-tr"><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: left;">Dictionary keys can be arbitrary objects?</td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:green; font-weight: bold;"> YES</span> </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:red; font-weight: bold;"> NO</span> </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:red; font-weight: bold;"> NO</span> </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:green; font-weight: bold;"> YES</span> </td></tr><tr class="wikkly-tr"><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: left;">Human-readable format?</td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:red; font-weight: bold;"> NO</span> </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:green; font-weight: bold;"> YES</span> </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:green; font-weight: bold;"> YES</span> </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:green; font-weight: bold;"> YES</span> </td></tr><tr class="wikkly-tr"><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: left;">Output formats</td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> Proprietary </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> JSON </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> JSON, XML </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> XML </td></tr><tr class="wikkly-tr"><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: left;">Handles arbitrary binary data? <sup class=""><a title="#NOTE4" class="wikkly-a-internal" href="#NOTE4" >4</a></sup></td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:green; font-weight: bold;"> YES</span> </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:red; font-weight: bold;"> NO</span> </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:green; font-weight: bold;"> YES</span> </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:green; font-weight: bold;"> YES</span> </td></tr><tr class="wikkly-tr"><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: left;">Fine-grained control of pickling process? <sup class=""><a title="#NOTE5" class="wikkly-a-internal" href="#NOTE5" >5</a></sup></td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:red; font-weight: bold;"> NO</span> </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:#71733d; font-weight: bold;"> MAYBE</span> </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:green; font-weight: bold;"> YES</span> </td><td class="wikkly-td" colspan="1" rowspan="1" style="text-align: center;"> <span style="color:green; font-weight: bold;"> YES</span> </td></tr></table>Footnotes: <ol class="wikkly-ol"><li class="wikkly-ol-li1"><a name="NOTE1" class="wikkly-a-internal"> </a> The only data structures RFC 4627 recognizes natively are dictionaries and lists. All other types have to be converted to one of these types. <span class="wikkly-tt">boodebr.ion</span> provides a layer on top of RFC 4627 to allow full pickling (while remaining 100% compatible with JSON). </li><li class="wikkly-ol-li1"><a name="NOTE2" class="wikkly-a-internal"> </a> Due to the limitations of RFC 4627, JSON and <span class="wikkly-tt">boodebr.ion</span> will convert tuple-&gt;list and string-&gt;unicode. All data is preserved, but the exact type may change. </li><li class="wikkly-ol-li1"><a name="NOTE3" class="wikkly-a-internal"> </a> Preserving references (espcially self-referencing data) while allowing user-defined hooks is quite difficult. Dropping this requirement allows <span class="wikkly-tt">boodebr.ion</span> to have a much simpler design than <span class="wikkly-tt">xml.pickle</span>. If you need this capability, use <span class="wikkly-tt">xml.pickle</span> instead.  </li><li class="wikkly-ol-li1"><a name="NOTE4" class="wikkly-a-internal"> </a> Neither JSON nor XML are binary-clean formats. <span class="wikkly-tt">boodebr.ion</span> and <span class="wikkly-tt">xml.pickle</span> transparently encode/decode binary data so you never have to worry about it. </li><li class="wikkly-ol-li1"><a name="NOTE5" class="wikkly-a-internal"> </a> Depending on the JSON library you use, it may allow more fine-grained control. Both <span class="wikkly-tt">boodebr.ion</span> and <span class="wikkly-tt">xml.pickle</span> have a hook/plugin system for fine-grained control, although <span class="wikkly-tt">xml.pickle</span> has a more extensive (and complicated) system.<br/><br/><div id="disqus_thread"></div><script type="text/javascript" src="http://disqus.com/forums/boodebr-library/embed.js"></script><noscript><a href="http://boodebr-library.disqus.com/?url=ref">View the forum thread.</a></noscript><a href="http://disqus.com" class="dsq-brlink">blog comments powered by <span class="logo-disqus">Disqus</span></a></li></ol>]]></description>
            <guid isPermaLink="false">22ecc9b83dae37eff78bcf8dd197ad8267defc76</guid>
            <pubDate>Mon, 04 Aug 2008 01:35:00 +0000</pubDate>
        </item>
        <item>
            <title>boodebr.util.threadQ</title>
            <link>http://www.boodebr.org/pages/boodebr/boodebr.util.threadQ.html</link>
            <description><![CDATA[<div ><div class="pydocs-module-box" ><div class="pydocs-module-title" >Module boodebr.util.threadQ</div><div class="pydocs-module-doc pydocs-indent" ><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/index.html" >boodebr</a> : <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.util.html" >boodebr.util</a> : <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.util.threadQ.html" >boodebr.util.threadQ</a><br/><br/>threadQ: Queues providing threadsafe access to non-threadsafe objects via serialization of method calls.<br/><br/>Usage pattern: <div class="wikkly-code-block">import&nbsp;boodebr.util.threadQ&nbsp;as&nbsp;tQ<br/><br/>#&nbsp;a&nbsp;non-threadsafe&nbsp;object<br/>class&nbsp;Foo(object):<br/>&nbsp;&nbsp;&nbsp;&nbsp;...<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>#&nbsp;start&nbsp;queue&nbsp;on&nbsp;namespace&nbsp;'foo'&nbsp;which&nbsp;will<br/>#&nbsp;produce&nbsp;wrapped&nbsp;versions&nbsp;of&nbsp;'Foo'&nbsp;objects<br/>tQ.start('foo',&nbsp;Foo)<br/><br/>#&nbsp;create&nbsp;as&nbsp;many&nbsp;wrapped&nbsp;Foo&nbsp;objects&nbsp;as&nbsp;you&nbsp;need.<br/>#&nbsp;objects&nbsp;can&nbsp;be&nbsp;safely&nbsp;shared&nbsp;by&nbsp;multiple&nbsp;threads.<br/>foo&nbsp;=&nbsp;threadQ.QProxyObj('foo')<br/><br/>#&nbsp;when&nbsp;finished&nbsp;with&nbsp;queue,&nbsp;don't&nbsp;forget&nbsp;to&nbsp;shut&nbsp;it&nbsp;down<br/>#&nbsp;or&nbsp;your&nbsp;program&nbsp;will&nbsp;hang<br/>tQ.shutdown('foo')</div><br/><br/><div class="wikkly-warnbox-container" ><div class="wikkly-warnbox-title" >Usage Notes</div><div class="wikkly-warnbox-body" ><ul class="wikkly-ul"><li class="wikkly-ul-li1">Queues are for <i class="">serialization</i> of calls, not <i class="">locking</i>. If you need to make several method calls atomically, you have to do your own locking. These queues only guarantee that no more than one thread will call an object method at a time. </li><li class="wikkly-ul-li1">Queues wrap <i class="">methods</i> not <i class="">attributes</i>. Attempting to get/set an attribute through the proxy object will not work. </li></ul></div></div></div><div class="pydocs-classes-outer" ><div class="pydocs-classes-outer-text" >Classes</div><div class="pydocs-indent" ><div class="pydocs-class-box" ><div class="pydocs-class-title" ><a name="CLASS_QProxyObj" class="wikkly-a-internal"> </a>QProxyObj(object)</div><div class="pydocs-class-doc pydocs-indent" ></div><div class="pydocs-methods-outer" ><div class="pydocs-indent" ><div class="pydocs-methods-outer-text" >Methods</div><div class="pydocs-method-box" ><div class="pydocs-method-title" >__getattr__(self, name)</div><div class="pydocs-method-doc pydocs-indent" ></div></div><div class="pydocs-method-box" ><div class="pydocs-method-title" >__init__(self, ns, args=(), kwargs={})</div><div class="pydocs-method-doc pydocs-indent" >Create an object from the given namespace with a threadsafe wrapper.<br/><br/><span class="wikkly-u">Inputs</span> <dl class="wikkly-dl"><dt class="wikkly-dt">ns </dt><dd class="wikkly-dd">Namespace to create object from (must have been previously 			started via <span class="wikkly-code-inline">start(ns)</span> </dd><dt class="wikkly-dt">args,kwargs </dt><dd class="wikkly-dd">Arguments to pass to namespace factory function to create object.<br/><br/></dd></dl>Returns new object. Returned object can be safely shared between multiple threads. The proxy object will have all the same methods as the wrapped object. Attribute access is not possible. </div></div></div></div></div></div></div><div class="pydocs-funcs-outer" ><div class="pydocs-funcs-outer-text" >Functions</div><div class="pydocs-indent" ><div class="pydocs-func-box" ><a name="FUNC_start" class="wikkly-a-internal"> </a><div class="pydocs-func-title" ><a name="FUNC_start" class="wikkly-a-internal"> </a>start(ns, factory)</div><div class="pydocs-func-doc pydocs-indent" >Begin a thread command queue for the given namespace.<br/><br/><span class="wikkly-u">Inputs</span> <dl class="wikkly-dl"><dt class="wikkly-dt">ns </dt><dd class="wikkly-dd">Namespace (string) </dd><dt class="wikkly-dt">factory </dt><dd class="wikkly-dd">Factory function that creates objects for this namespace. Factory 		function takes any number of caller-defined parameters &mdash; you will pass the 		args when you 		create a <a title="#CLASS_QProxyObj" class="wikkly-a-internal" href="#CLASS_QProxyObj" >QProxyObj</a> </dd></dl></div></div><div class="pydocs-func-box" ><a name="FUNC_shutdown" class="wikkly-a-internal"> </a><div class="pydocs-func-title" ><a name="FUNC_shutdown" class="wikkly-a-internal"> </a>shutdown(ns)</div><div class="pydocs-func-doc pydocs-indent" >Stop either a single thread by passing its namespace, or shutdown <b class="">all</b> threads by passing <span class="wikkly-code-inline">ns=None</span>.<br/><br/>Once you call <b class="">start(ns)</b> you <span class="wikkly-u">must</span> call <b class="">shutdown(ns)</b> before your application exits, else your application will hang on exit.<br/><br/>You may call <b class="">shutdown(ns)</b> multiple times without error. </div></div></div></div></div></div><div id="disqus_thread"></div><script type="text/javascript" src="http://disqus.com/forums/boodebr-library/embed.js"></script><noscript><a href="http://boodebr-library.disqus.com/?url=ref">View the forum thread.</a></noscript><a href="http://disqus.com" class="dsq-brlink">blog comments powered by <span class="logo-disqus">Disqus</span></a>]]></description>
            <guid isPermaLink="false">fb8d818307956db7d0421f59adf7b2e549edab4e</guid>
            <pubDate>Mon, 04 Aug 2008 01:34:00 +0000</pubDate>
        </item>
        <item>
            <title>ion.api</title>
            <link>http://www.boodebr.org/pages/boodebr/ion.api.html</link>
            <description><![CDATA[Pickling (serializing) data is performed with <span class="wikkly-tt">ionize()</span>: <div class="wikkly-code-block">from&nbsp;boodebr.ion&nbsp;import&nbsp;ionize<br/>bytes&nbsp;=&nbsp;ionize(obj,&nbsp;format='json',&nbsp;indent=True,&nbsp;userhooks=None,&nbsp;flatten_only=False):</div><br/><br/>Where: <div class="wikkly-indent" ><dl class="wikkly-dl"><dt class="wikkly-dt">obj </dt><dd class="wikkly-dd">Object to pickle (serialize) </dd><dt class="wikkly-dt">format </dt><dd class="wikkly-dd">Format to write, either <span class="wikkly-tt">'json'</span> or <span class="wikkly-tt">'xml'</span> (case sensitive). </dd><dt class="wikkly-dt">indent </dt><dd class="wikkly-dd"><span class="wikkly-tt">True|False</span>: Should output be indented ("pretty-formatted")? </dd><dt class="wikkly-dt">userhooks </dt><dd class="wikkly-dd">A list of user-defined hooks. See <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/ion.hooks.html" >hooks API</a>. </dd><dt class="wikkly-dt">flatten_only </dt><dd class="wikkly-dd">If True, data will be strictly flattened, with no hooks added to               enable reconstruction via deionize(). This may be needed when passing data to some JSON implementations that cannot handle the extra hook attributes. </dd></dl></div><br/><br/>The return value (<span class="wikkly-tt">bytes</span>) is <b class="">always</b> a UTF-8 encoded bytestring.<br/><br/>Unpickling (deserializing) is performed with <span class="wikkly-tt">deionize()</span>: <div class="wikkly-code-block">from&nbsp;boodebr.ion&nbsp;import&nbsp;deionize<br/>obj&nbsp;=&nbsp;deionize(buf,&nbsp;userhooks=None)</div><br/><br/>Where: <div class="wikkly-indent" ><dl class="wikkly-dl"><dt class="wikkly-dt">buf </dt><dd class="wikkly-dd">Normally this is the UTF-8 bytestream returned from <span class="wikkly-code-inline">ionize</span>, but may be a Unicode value as well. </dd><dt class="wikkly-dt">userhooks </dt><dd class="wikkly-dd">A dictionary of user-defined hooks. See <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/ion.hooks.html" >hooks API</a>. </dd></dl></div><br/><br/>Returns the unpickled object.<br/><br/><div id="disqus_thread"></div><script type="text/javascript" src="http://disqus.com/forums/boodebr-library/embed.js"></script><noscript><a href="http://boodebr-library.disqus.com/?url=ref">View the forum thread.</a></noscript><a href="http://disqus.com" class="dsq-brlink">blog comments powered by <span class="logo-disqus">Disqus</span></a>]]></description>
            <guid isPermaLink="false">e3b28832747efd770b51390aba3f4a4230001356</guid>
            <pubDate>Mon, 04 Aug 2008 01:34:00 +0000</pubDate>
        </item>
        <item>
            <title>boodebr.util.guid</title>
            <link>http://www.boodebr.org/pages/boodebr/boodebr.util.guid.html</link>
            <description><![CDATA[<div ><div class="pydocs-module-box" ><div class="pydocs-module-title" >Module boodebr.util.guid</div><div class="pydocs-module-doc pydocs-indent" ><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/index.html" >boodebr</a> : <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.util.html" >boodebr.util</a> : <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.util.guid.html" >boodebr.util.guid</a><br/><br/>Creation of globally unique IDs.<br/><br/>This is a simple module for generating unique IDs, along the same lines as a <a title="Link to http://en.wikipedia.org" class="wikkly-a-www" href="http://en.wikipedia.org/wiki/Globally_Unique_Identifier" onclick="window.open(this.href);return false;">GUID</a>, but not matching  any specific standard.<br/><br/>Example: <div class="wikkly-code-block">from&nbsp;boodebr.util&nbsp;import&nbsp;makeGUID<br/>print&nbsp;"A&nbsp;new&nbsp;GUID",makeGUID('some&nbsp;string')</div> </div><div class="pydocs-classes-outer" ></div><div class="pydocs-funcs-outer" ><div class="pydocs-funcs-outer-text" >Functions</div><div class="pydocs-indent" ><div class="pydocs-func-box" ><a name="FUNC_makeGUID" class="wikkly-a-internal"> </a><div class="pydocs-func-title" ><a name="FUNC_makeGUID" class="wikkly-a-internal"> </a>makeGUID(seed='')</div><div class="pydocs-func-doc pydocs-indent" >Create a new unique identifier (40-character string of <span class="wikkly-tt">[0-9a-f]</span>).  Will be sufficiently random so you can assume it is unique.<br/><br/><span class="wikkly-u">Inputs</span> <dl class="wikkly-dl"><dt class="wikkly-dt">seed </dt><dd class="wikkly-dd">Used to provide extra randomness to the GUID. The GUID is <span class="wikkly-u">NOT</span> in any way tied to this seed.<br/><br/></dd></dl>Returns GUID (<i class="">string</i>) </div></div></div></div></div></div><div id="disqus_thread"></div><script type="text/javascript" src="http://disqus.com/forums/boodebr-library/embed.js"></script><noscript><a href="http://boodebr-library.disqus.com/?url=ref">View the forum thread.</a></noscript><a href="http://disqus.com" class="dsq-brlink">blog comments powered by <span class="logo-disqus">Disqus</span></a> ]]></description>
            <guid isPermaLink="false">fc99d69f811d03198af877f09f86b5aa035f9f9d</guid>
            <pubDate>Mon, 04 Aug 2008 01:33:00 +0000</pubDate>
        </item>
        <item>
            <title>boodebr.util.modules</title>
            <link>http://www.boodebr.org/pages/boodebr/boodebr.util.modules.html</link>
            <description><![CDATA[<div ><div class="pydocs-module-box" ><div class="pydocs-module-title" >Module boodebr.util.modules</div><div class="pydocs-module-doc pydocs-indent" ><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/index.html" >boodebr</a> : <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.util.html" >boodebr.util</a> : <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.util.modules.html" >boodebr.util.modules</a><br/><br/>Module-related utilities. </div><div class="pydocs-classes-outer" ></div><div class="pydocs-funcs-outer" ><div class="pydocs-funcs-outer-text" >Functions</div><div class="pydocs-indent" ><div class="pydocs-func-box" ><a name="FUNC_load_module" class="wikkly-a-internal"> </a><div class="pydocs-func-title" ><a name="FUNC_load_module" class="wikkly-a-internal"> </a>load_module(name)</div><div class="pydocs-func-doc pydocs-indent" >Load a module, given a full name like <b class="">AAA.BBB.CCC</b>.<br/><br/>Returns module.<br/><br/><span class="wikkly-u">Example</span><br/><br/>If <b class="">AAA.BBB.CCC</b> has a function named <b class="">DDD</b>, it can be loaded and 	referenced with: <div class="wikkly-code-block">mod&nbsp;=&nbsp;load_module('AAA.BBB.CCC')<br/>func&nbsp;=&nbsp;getattr(mod,&nbsp;'DDD')</div><br/><br/>Using <span class="wikkly-code-inline">__import__("AAA.BBB.CCC")</span> or <span class="wikkly-code-inline">imp.load_module()</span> will NOT do the same thing. </div></div></div></div></div></div><div id="disqus_thread"></div><script type="text/javascript" src="http://disqus.com/forums/boodebr-library/embed.js"></script><noscript><a href="http://boodebr-library.disqus.com/?url=ref">View the forum thread.</a></noscript><a href="http://disqus.com" class="dsq-brlink">blog comments powered by <span class="logo-disqus">Disqus</span></a>]]></description>
            <guid isPermaLink="false">c2e48fae794ae1f748c6f9a0064008bcad6b8aa6</guid>
            <pubDate>Mon, 04 Aug 2008 01:33:00 +0000</pubDate>
        </item>
        <item>
            <title>boodebr.util.errors</title>
            <link>http://www.boodebr.org/pages/boodebr/boodebr.util.errors.html</link>
            <description><![CDATA[Catches unhandled exceptions and logs them to a file.<br/><br/>Usage: <div class="wikkly-code-block">import&nbsp;boodebr.util.errors<br/>boodebr.util.errors.catch_exceptions()</div><br/><br/>You can also specify a log directory with: <div class="wikkly-code-block">boodebr.util.errors.catch_exceptions('/some/log/dir')</div><br/><br/>If not given, <span class="wikkly-code-inline">os.getcwd()</span> is used.<br/><br/><div id="disqus_thread"></div><script type="text/javascript" src="http://disqus.com/forums/boodebr-library/embed.js"></script><noscript><a href="http://boodebr-library.disqus.com/?url=ref">View the forum thread.</a></noscript><a href="http://disqus.com" class="dsq-brlink">blog comments powered by <span class="logo-disqus">Disqus</span></a>]]></description>
            <guid isPermaLink="false">65b48236b1dc8f9f8493be58cdff217159c41ead</guid>
            <pubDate>Mon, 04 Aug 2008 01:32:00 +0000</pubDate>
        </item>
        <item>
            <title>boodebr.config</title>
            <link>http://www.boodebr.org/pages/boodebr/boodebr.config.html</link>
            <description><![CDATA[<b class="">boodebr.config</b> provides configuration files in the spirit of .INI files, but using either JSON or XML. It provides a more flexible and easier to use API than Much more flexible and easier to use than <a title="Link to http://docs.python.org" class="wikkly-a-www" href="http://docs.python.org/lib/module-ConfigParser.html" onclick="window.open(this.href);return false;">ConfigParser</a><br/><br/>The main entry point is the <span class="wikkly-tt">configfile</span> factory function: <div class="wikkly-code-block">cfg&nbsp;=&nbsp;configfile(filename,&nbsp;format='json',&nbsp;allow_dict=False)</div><br/><br/>Where: <div class="wikkly-indent" ><dl class="wikkly-dl"><dt class="wikkly-dt">filename </dt><dd class="wikkly-dd">Configuration filename (does not have to exist). Guarantees <b class="">not</b> to create the file until you add data. </dd><dt class="wikkly-dt">format </dt><dd class="wikkly-dd">'json' or 'xml' (will be autodetected when reading; this specifies the format to write). </dd><dt class="wikkly-dt">allow_dict </dt><dd class="wikkly-dd"><span class="wikkly-tt">True</span>/<span class="wikkly-tt">False</span> - should set() allow you to pass a dict? (The downside of setting this to 'True' is a larger/more verbose configuration file, so only use this you really need it.) </dd></dl></div> Returns a configuration object.<br/><br/>You get and set data with simple path:key pairs. Here is a short example that demonstrates the API: <div class="wikkly-code-block">from&nbsp;boodebr.config&nbsp;import&nbsp;configfile<br/><br/>#&nbsp;a&nbsp;test&nbsp;object&nbsp;--&nbsp;subtlety&nbsp;here,&nbsp;must&nbsp;define&nbsp;before&nbsp;calling&nbsp;'configfile()'<br/>#&nbsp;since&nbsp;it&nbsp;will&nbsp;immediately&nbsp;try&nbsp;to&nbsp;deserialize&nbsp;the&nbsp;configfile&nbsp;(if&nbsp;it&nbsp;exists)<br/>class&nbsp;Foo(object):<br/>&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;__init__(self,&nbsp;a,&nbsp;b):<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.a&nbsp;=&nbsp;a<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.b&nbsp;=&nbsp;b<br/><br/>#&nbsp;create&nbsp;config&nbsp;file&nbsp;in&nbsp;JSON&nbsp;format<br/>cfg&nbsp;=&nbsp;configfile('test.json',&nbsp;'json')<br/><br/>#&nbsp;first,&nbsp;use&nbsp;the&nbsp;typesafe&nbsp;setters<br/>cfg.set_int('/Root/PathA',&nbsp;'loops',&nbsp;100)<br/>cfg.set_float('/Root/PathB',&nbsp;'a_pct',&nbsp;0.25)<br/>cfg.set_str('/Root/A/B/C',&nbsp;'name',&nbsp;'FooBar')<br/>cfg.set_bool('/Root/A/B',&nbsp;'run',&nbsp;False)<br/>cfg.set_list('/Root/A',&nbsp;'a_list',&nbsp;[1,&nbsp;2.3,&nbsp;'abc'])<br/><br/>#&nbsp;or,&nbsp;can&nbsp;just&nbsp;set&nbsp;arbitrary&nbsp;objects<br/>f&nbsp;=&nbsp;Foo((1,2,3),&nbsp;['456',&nbsp;'xyz'])<br/>cfg.set('/Root/PathC',&nbsp;'an_object',&nbsp;f)<br/><br/>#&nbsp;reload&nbsp;first&nbsp;with&nbsp;typesafe&nbsp;getters&nbsp;-&nbsp;the&nbsp;final&nbsp;arg&nbsp;<br/>#&nbsp;is&nbsp;the&nbsp;default&nbsp;value<br/>print&nbsp;"Loops",&nbsp;cfg.get_int('/Root/PathA',&nbsp;'loops',&nbsp;None)<br/>print&nbsp;"a_pct",&nbsp;cfg.get_float('/Root/PathB',&nbsp;'a_pct',&nbsp;None)<br/>print&nbsp;"name",&nbsp;cfg.get_str('/Root/A/B/C',&nbsp;'name',&nbsp;None)<br/>print&nbsp;"do_run",&nbsp;cfg.get_bool('/Root/A/B',&nbsp;'do_run',&nbsp;None)<br/>print&nbsp;"a_list",&nbsp;cfg.get_list('/Root/A',&nbsp;'a_list',&nbsp;None)<br/><br/>#&nbsp;now,&nbsp;any&nbsp;object<br/>f&nbsp;=&nbsp;cfg.get('/Root/PathC',&nbsp;'an_object',&nbsp;None)<br/>print&nbsp;"Foo.a,&nbsp;Foo.b",f.a,f.b<br/><br/>#&nbsp;loading&nbsp;non-existant&nbsp;values&nbsp;will&nbsp;return&nbsp;the&nbsp;default&nbsp;values<br/>print&nbsp;"Expect&nbsp;'aaa':",&nbsp;cfg.get_str('/Root/NoPath',&nbsp;'a_value',&nbsp;'aaa')<br/>print&nbsp;"Expect&nbsp;54321:",&nbsp;cfg.get_int('/Root/PathA',&nbsp;'NoSuchValue',&nbsp;54321)</div><br/><br/>Now you can examine <span class="wikkly-code-inline">test.json</span> to see the results. Try passing <span class="wikkly-code-inline">'xml'</span> instead of <span class="wikkly-code-inline">'json'</span> to <span class="wikkly-code-inline">configfile()</span> to see the difference.<br/><br/><div id="disqus_thread"></div><script type="text/javascript" src="http://disqus.com/forums/boodebr-library/embed.js"></script><noscript><a href="http://boodebr-library.disqus.com/?url=ref">View the forum thread.</a></noscript><a href="http://disqus.com" class="dsq-brlink">blog comments powered by <span class="logo-disqus">Disqus</span></a>]]></description>
            <guid isPermaLink="false">e5d6162365257db6eebccaa0504f13e8721bc8b8</guid>
            <pubDate>Mon, 04 Aug 2008 01:30:00 +0000</pubDate>
        </item>
        <item>
            <title>boodebr.util</title>
            <link>http://www.boodebr.org/pages/boodebr/boodebr.util.html</link>
            <description><![CDATA[General utility functions: <ul class="wikkly-ul"><li class="wikkly-ul-li1"><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.util.errors.html" >boodebr.util.errors</a>: Easy handling and logging of exceptions. </li><li class="wikkly-ul-li1"><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.util.guid.html" >boodebr.util.guid</a>: Creation of unique IDs </li><li class="wikkly-ul-li1"><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.util.locking.html" >boodebr.util.locking</a>: Multithreading/multiprocess safe cooperative locking. </li><li class="wikkly-ul-li1"><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.util.modules.html" >boodebr.util.modules</a>: Module-related utilities </li><li class="wikkly-ul-li1"><a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.util.threadQ.html" >boodebr.util.threadQ</a>: Queues providing threadsafe access to non-threadsafe objects via serialization of method calls. </li></ul>]]></description>
            <guid isPermaLink="false">9242ebd1cfabe9cb5220d153a7719e57ebec2d0d</guid>
            <pubDate>Mon, 04 Aug 2008 01:09:00 +0000</pubDate>
        </item>
        <item>
            <title>boodebr.sql</title>
            <link>http://www.boodebr.org/pages/boodebr/boodebr.sql.html</link>
            <description><![CDATA[<b class="">boodebr.sql</b> is a light wrapper for <a title="Link to http://www.initd.org" class="wikkly-a-www" href="http://www.initd.org/tracker/pysqlite/wiki/pysqlite" onclick="window.open(this.href);return false;">pysqlite</a> and <a title="Link to http://www.initd.org" class="wikkly-a-www" href="http://www.initd.org/tracker/pysqlite/wiki/APSW" onclick="window.open(this.href);return false;">APSW</a>.<br/><br/><div class="wikkly-warnbox-container" ><div class="wikkly-warnbox-title" >Use latest version of pysqlite</div><div class="wikkly-warnbox-body" >I recommend updating to the most recent version of <a title="Link to http://pysqlite.org" class="wikkly-a-www" href="http://pysqlite.org/" onclick="window.open(this.href);return false;">pysqlite</a>. The stock version bundled with Python 2.5 (pysqlite 2.3.2 with SQLite 3.3.4) appears to have issues under high loads. pysqlite 2.4.1 (with SQLite 3.5.2) seems stable.</div></div><br/><br/>See also: <a title="Link to http://www.boodebr.org" class="wikkly-a-internal" href="http://www.boodebr.org/pages/boodebr/boodebr.sql.sqliteQ.html" >boodebr.sql.sqliteQ</a> for easy multithreaded use.<br/><br/>Advantages over the standard <a title="Link to http://www.python.org" class="wikkly-a-www" href="http://www.python.org/dev/peps/pep-0249/" onclick="window.open(this.href);return false;">DB-API 2.0</a> interface: <ul class="wikkly-ul"><li class="wikkly-ul-li1">Wraps PyDB with iterators for nicer code </li><li class="wikkly-ul-li1">Iterator can return rows, dicts, or objects </li><li class="wikkly-ul-li1">Shorthand function names </li><li class="wikkly-ul-li1">When loading objects, calls <span class="wikkly-code-inline">obj.__postload__()</span> so objects can perform their own SQL-&gt;object conversions.<br/><br/></li></ul>I've divided functionality between the connection &amp; cursor objects differently that the Python DB API does (i.e. <span class="wikkly-tt">query()</span> is an attribute of the connection, not the cursor).<br/><br/>I think this leads to nicer code, and it allows cursors to be generated/used transparently.<br/><br/>For example, with Python DB API you'd do: <div class="wikkly-code-block">&nbsp;&nbsp;&nbsp;&nbsp;sql&nbsp;=&nbsp;sqlite.connect(&nbsp;connect_args&nbsp;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;cursor&nbsp;=&nbsp;sql.cursor()<br/>&nbsp;&nbsp;&nbsp;&nbsp;cursor.execute(&nbsp;query&nbsp;)<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;row&nbsp;=&nbsp;cursor.fetchone()<br/>&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;row&nbsp;is&nbsp;not&nbsp;None:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;do&nbsp;something&nbsp;with&nbsp;row<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;row&nbsp;=&nbsp;cursor.fetchone()</div><br/><br/><br/>With my wrapper, you can do things like: <div class="wikkly-code-block">&nbsp;&nbsp;&nbsp;&nbsp;sql&nbsp;=&nbsp;fpmsql(&nbsp;connect_args&nbsp;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;row&nbsp;in&nbsp;sql.query(&nbsp;query&nbsp;):<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;do&nbsp;something&nbsp;with&nbsp;row<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;dict_row&nbsp;in&nbsp;sql.query(&nbsp;query&nbsp;).dict():<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;dict_row&nbsp;is&nbsp;row&nbsp;as&nbsp;dict&nbsp;where&nbsp;dict_row[colname]&nbsp;=&nbsp;value<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;obj&nbsp;in&nbsp;sql.query(&nbsp;query&nbsp;).obj():<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;obj&nbsp;is&nbsp;row&nbsp;as&nbsp;an&nbsp;object&nbsp;(ie.&nbsp;obj.colname&nbsp;=&nbsp;value)</div><br/><br/><br/><span class="wikkly-code-inline">import&nbsp;*</span> will import (fpmsql, DatabaseError)<br/><br/><div class="wikkly-infobox-container" ><div class="wikkly-infobox-title" >NOTE</div><div class="wikkly-infobox-body" >Recent versions of pysqlite have adopted iterator methods also, so you could use those directly, but I prefer my wrapper anyways for other niceties.</div></div><br/><br/>]]></description>
            <guid isPermaLink="false">5ecb2c4c7aa788848284e713f190f4044539d55a</guid>
            <pubDate>Sat, 21 Jun 2008 15:59:00 +0000</pubDate>
        </item>
        <item>
            <title>AboutTheseDocs</title>
            <link>http://www.boodebr.org/pages/boodebr/AboutTheseDocs.html</link>
            <description><![CDATA[This documentation is written in and served by WikklyText, a lightweight set of wiki tools written in Python.<br/><br/>You can read more about it at the <a title="Link to http://wikklytext.com" class="wikkly-a-www" href="http://wikklytext.com" onclick="window.open(this.href);return false;">WikklyText home page</a> ]]></description>
            <guid isPermaLink="false">41e9f0f2d2d363abe8947c9ef096ffbd61049fda</guid>
            <pubDate>Thu, 06 Mar 2008 21:26:00 +0000</pubDate>
        </item>
        <item>
            <title>boodebr.sql.sqliteQ</title>
            <link>http://www.boodebr.org/pages/boodebr/boodebr.sql.sqliteQ.html</link>
            <description><![CDATA[This module allows you to share an SQLite connection across multiple threads. (Normally, you can only use an SQLite connection within the thread that created it.)<br/><br/>Example usage: <div class="wikkly-code-block">import&nbsp;boodebr.sql.sqliteQ&nbsp;as&nbsp;sQ<br/><br/>#&nbsp;begin&nbsp;queue&nbsp;manager&nbsp;thread&nbsp;-&nbsp;do&nbsp;this&nbsp;before&nbsp;creating<br/>#&nbsp;any&nbsp;sqliteQ&nbsp;objects.<br/>sQ.start()&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>q&nbsp;=&nbsp;sQ.sqliteQ('mydb.db')<br/><br/>#&nbsp;pass&nbsp;'q'&nbsp;to&nbsp;as&nbsp;many&nbsp;threads&nbsp;as&nbsp;you'd&nbsp;like,&nbsp;it&nbsp;is&nbsp;threadsafe.<br/>#&nbsp;you&nbsp;can&nbsp;create&nbsp;as&nbsp;many&nbsp;sqliteQ&nbsp;objects&nbsp;as&nbsp;you&nbsp;like;&nbsp;multiple<br/>#&nbsp;sqliteQ&nbsp;objects&nbsp;can&nbsp;even&nbsp;use&nbsp;the&nbsp;same&nbsp;filename&nbsp;without&nbsp;error.<br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/>#&nbsp;end&nbsp;queue&nbsp;manager&nbsp;thread&nbsp;-&nbsp;always&nbsp;do&nbsp;this&nbsp;before<br/>#&nbsp;your&nbsp;application&nbsp;exits<br/>sQ.shutdown()</div><br/><br/><div class="wikkly-warnbox-mini" >When using sqliteQ, <b class="">make sure</b> you have a toplevel exception handler that calls <span class="wikkly-code-inline">shutdown()</span> so your application won't hang on  unexpected errors.</div><br/><br/><h3 class="wikkly-h3">sqliteQ API</h3><br/>The sqliteQ API is grouped into two categories: <ul class="wikkly-ul"><li class="wikkly-ul-li1">Low-level querying methods </li><li class="wikkly-ul-li1">Higher-level functions, including replacements for functionality missing from SQLite's native <span class="wikkly-code-inline">ALTER&nbsp;TABLE</span> function.<br/><br/></li></ul><h4 class="wikkly-h4">Querying</h4><br/><dl class="wikkly-dl"><dt class="wikkly-dt">run(cmdlist) </dt><dd class="wikkly-dd"> Run a list of commands inside a transaction.<br/><br/>The entire transaction is rolled back if any commands fail.<br/><br/>Accepts cmdlist as either: <ul class="wikkly-ul"><li class="wikkly-ul-li1">multiple commands: <span class="wikkly-code-inline">((query,args),&nbsp;(query,args),&nbsp;...)</span> </li><li class="wikkly-ul-li1">single command: <span class="wikkly-code-inline">(query,args)</span><br/><br/></li></ul>There is no return value. Raises an exception on error.<br/><br/>Example: <div class="wikkly-code-block">s&nbsp;=&nbsp;sqliteQ('mydb.db')<br/>cmds&nbsp;=&nbsp;[<br/>&nbsp;&nbsp;&nbsp;('create&nbsp;table&nbsp;AAA&nbsp;(name&nbsp;text)',&nbsp;None),<br/>&nbsp;&nbsp;&nbsp;('create&nbsp;table&nbsp;BBB&nbsp;(name&nbsp;text)',&nbsp;None),<br/>&nbsp;&nbsp;&nbsp;]<br/>s.run(cmds)</div> <br/><br/></dd></dl><dl class="wikkly-dl"><dt class="wikkly-dt">getrows(query, args=None) </dt><dd class="wikkly-dd"> Run given query and return result as a list of rows.<br/><br/>Example: <div class="wikkly-code-block">s&nbsp;=&nbsp;sqliteQ('mydb.db')<br/>q&nbsp;=&nbsp;'select&nbsp;id,name&nbsp;from&nbsp;MyTable&nbsp;where&nbsp;last=?'<br/>a&nbsp;=&nbsp;('Smith',)<br/>for&nbsp;row&nbsp;in&nbsp;s.getrows(q,a):<br/>&nbsp;&nbsp;&nbsp;print&nbsp;"ID,name",&nbsp;row[0],&nbsp;row[1]</div> <br/><br/></dd></dl><dl class="wikkly-dl"><dt class="wikkly-dt">getobjs(query, args=None, klass=None) </dt><dd class="wikkly-dd"> Run given query and return result as a list of objects.<br/> Objects will be of type <span class="wikkly-tt">klass</span>, if given, or an anonymous  type if not.<br/><br/>Example: <div class="wikkly-code-block">s&nbsp;=&nbsp;sqliteQ('mydb.db')<br/>q&nbsp;=&nbsp;'select&nbsp;id,name&nbsp;from&nbsp;MyTable&nbsp;where&nbsp;last=?'<br/>a&nbsp;=&nbsp;('Smith',)<br/>for&nbsp;obj&nbsp;in&nbsp;s.getobjs(q,a):<br/>&nbsp;&nbsp;&nbsp;print&nbsp;"ID,name",&nbsp;obj.id,&nbsp;obj.name</div><br/><br/></dd></dl><dl class="wikkly-dl"><dt class="wikkly-dt">get_tables(special=False) </dt><dd class="wikkly-dd"> Get a list of table names from database.<br/> If special==False, filters out special <span class="wikkly-code-inline">sqlite_</span> table names.<br/><br/>Returns list of names. <br/><br/></dd></dl><h4 class="wikkly-h4">Table-Alteration</h4><br/>  <dl class="wikkly-dl"><dt class="wikkly-dt">add_table_column(table, colname, coltype, colcomment, initval=None) </dt><dd class="wikkly-dd"> Add a column to a table, creating the table if it doesn't yet exist.<br/><br/><dl class="wikkly-dl"><dt class="wikkly-dt">table </dt><dd class="wikkly-dd">Name of table to modify. </dd><dt class="wikkly-dt">colname </dt><dd class="wikkly-dd">Name for new column. </dd><dt class="wikkly-dt">coltype </dt><dd class="wikkly-dd">Datatype for new column. </dd><dt class="wikkly-dt">colcomment </dt><dd class="wikkly-dd">Comment for new column. Should be passed WITHOUT the <span class="wikkly-code-inline">/*&nbsp;*/</span> </dd><dt class="wikkly-dt">initval </dt><dd class="wikkly-dd">Value to fill new column with.<br/><br/></dd></dl>If an error occurs, the database is rolled-back to its original state, so the caller doesn't have to do anything but inform the user of the error (a DatabaseError exception will be raised).<br/><br/>There is no return value.<br/><br/><div class="wikkly-warnbox-mini" >This will also drop any indexes on the table so you'll  need to recreate those.<br/><br/>This limitation <i class="">may</i> be removed at some point, so I recommend you create your indexes using the form <span class="wikkly-code-inline">CREATE&nbsp;INDEX&nbsp;IF&nbsp;NOT&nbsp;EXISTS&nbsp;...</span></div><div class="wikkly-infobox-mini" >Recent versions of SQLite offer an <span class="wikkly-code-inline">ALTER&nbsp;TABLE&nbsp;ADD&nbsp;COLUMN</span> command. You may want to try both and see which works best for your application.</div> <br/><br/></dd></dl><dl class="wikkly-dl"><dt class="wikkly-dt">delete_table(table) </dt><dd class="wikkly-dd"> Permanently delete a table from the named database.<br/><br/>If an error occurs, the database is rolled-back to its original state, so the caller doesn't have to do anything but inform the user of the error (a DatabaseError exception will be raised). <br/><br/></dd></dl><dl class="wikkly-dl"><dt class="wikkly-dt">delete_table_columns(table, columns) </dt><dd class="wikkly-dd"> Delete a list of columns from the given table.<br/><br/>If an error occurs, the database is rolled-back to its original state, so the caller doesn't have to do anything but inform the user of the error (a DatabaseError exception will be raised).<br/><br/><div class="wikkly-warnbox-mini" >This will also drop any indexes on the table so you'll  need to recreate those.<br/><br/>This limitation <i class="">may</i> be removed at some point, so I recommend you create your indexes using the form <span class="wikkly-code-inline">CREATE&nbsp;INDEX&nbsp;IF&nbsp;NOT&nbsp;EXISTS&nbsp;...</span></div> <br/><br/></dd></dl><dl class="wikkly-dl"><dt class="wikkly-dt">get_table_columns(table) </dt><dd class="wikkly-dd"> Get a list of column names &amp; types for the given table.<br/><br/>Returns a list of entries: <div class="wikkly-code-block">&nbsp;&nbsp;(colname,&nbsp;coltype,&nbsp;colcomment)</div><br/><br/>Where: <div class="wikkly-indent" ><dl class="wikkly-dl"><dt class="wikkly-dt">colname </dt><dd class="wikkly-dd">Name of column </dd><dt class="wikkly-dt">coltype </dt><dd class="wikkly-dd">The SQL type string </dd><dt class="wikkly-dt">colcomment </dt><dd class="wikkly-dd">Aggregated comments found for column (<span class="wikkly-code-inline">/*&nbsp;..&nbsp;*/</span> and/or <span class="wikkly-code-inline">--</span> will be removed.) </dd></dl></div> <br/>						  The list will be in the same order as the order of the SQL statements used to create the table.<br/><br/>Returns [] if table doesn't exist. <br/><br/></dd></dl><dl class="wikkly-dl"><dt class="wikkly-dt">modify_table_column(table, cur_colname, new_colname, new_coltype=None, new_colcomment=None) </dt><dd class="wikkly-dd"> Rename and/or change the type of a column and/or associated comment.<br/><br/><div class="wikkly-indent" ><dl class="wikkly-dl"><dt class="wikkly-dt">table </dt><dd class="wikkly-dd">Table to modify </dd><dt class="wikkly-dt">cur_colname </dt><dd class="wikkly-dd">Column to change </dd><dt class="wikkly-dt">new_colname </dt><dd class="wikkly-dd">New name for column. </dd><dt class="wikkly-dt">new_coltype </dt><dd class="wikkly-dd">New type for column; if None, don't change the type. </dd><dt class="wikkly-dt">new_colcomment </dt><dd class="wikkly-dd">New comment for column; if None, don't change comment. </dd></dl></div> If an error occurs, the database is rolled-back to its original state, so the caller doesn't have to do anything but inform the user of the error (a DatabaseError exception will be raised).<br/><br/><div class="wikkly-warnbox-mini" >This will also drop any indexes on the table so you'll  need to recreate those.<br/><br/>This limitation <i class="">may</i> be removed at some point, so I recommend you create your indexes using the form <span class="wikkly-code-inline">CREATE&nbsp;INDEX&nbsp;IF&nbsp;NOT&nbsp;EXISTS&nbsp;...</span></div> <br/><br/></dd></dl><dl class="wikkly-dl"><dt class="wikkly-dt">rename_table(table, newname, newcomment=None) </dt><dd class="wikkly-dd"> Rename a table to newname.<br/><br/>If an error occurs, the database is rolled-back to its original state, so the caller doesn't have to do anything but inform the user of the error (a DatabaseError exception will be raised).<br/><br/>There is no return value.<br/><br/><div class="wikkly-warnbox-mini" >This will also drop any indexes on the table so you'll  need to recreate those.<br/><br/>This limitation <i class="">may</i> be removed at some point, so I recommend you create your indexes using the form <span class="wikkly-code-inline">CREATE&nbsp;INDEX&nbsp;IF&nbsp;NOT&nbsp;EXISTS&nbsp;...</span></div><br/><br/></dd></dl>]]></description>
            <guid isPermaLink="false">eda3609e0dfb5d77451eb8d12cdcd2b23a43dac1</guid>
            <pubDate>Sat, 01 Mar 2008 16:47:00 +0000</pubDate>
        </item>
        <item>
            <title>license</title>
            <link>http://www.boodebr.org/pages/boodebr/license.html</link>
            <description><![CDATA[The boodebr library is licensed under the <a title="Link to http://www.opensource.org" class="wikkly-a-www" href="http://www.opensource.org/licenses/mit-license.php" onclick="window.open(this.href);return false;">MIT opensource license</a>.<br/><br/><div class="wikkly-codebox-container" ><div class="wikkly-codebox-title" >LICENSE</div><div class="wikkly-codebox-body" >boodebr&nbsp;library<br/><br/>Copyright&nbsp;(C)&nbsp;2007,2008&nbsp;Frank&nbsp;McIngvale<br/><br/>Contact:&nbsp;fmcingvale@boodebr.org<br/><br/>Permission&nbsp;is&nbsp;hereby&nbsp;granted,&nbsp;free&nbsp;of&nbsp;charge,&nbsp;to&nbsp;any&nbsp;person&nbsp;obtaining&nbsp;a&nbsp;copy<br/>of&nbsp;this&nbsp;software&nbsp;and&nbsp;associated&nbsp;documentation&nbsp;files&nbsp;(the&nbsp;"Software"),&nbsp;to&nbsp;deal<br/>in&nbsp;the&nbsp;Software&nbsp;without&nbsp;restriction,&nbsp;including&nbsp;without&nbsp;limitation&nbsp;the&nbsp;rights<br/>to&nbsp;use,&nbsp;copy,&nbsp;modify,&nbsp;merge,&nbsp;publish,&nbsp;distribute,&nbsp;sublicense,&nbsp;and/or&nbsp;sell<br/>copies&nbsp;of&nbsp;the&nbsp;Software,&nbsp;and&nbsp;to&nbsp;permit&nbsp;persons&nbsp;to&nbsp;whom&nbsp;the&nbsp;Software&nbsp;is<br/>furnished&nbsp;to&nbsp;do&nbsp;so,&nbsp;subject&nbsp;to&nbsp;the&nbsp;following&nbsp;conditions:<br/><br/>The&nbsp;above&nbsp;copyright&nbsp;notice&nbsp;and&nbsp;this&nbsp;permission&nbsp;notice&nbsp;shall&nbsp;be&nbsp;included&nbsp;in<br/>all&nbsp;copies&nbsp;or&nbsp;substantial&nbsp;portions&nbsp;of&nbsp;the&nbsp;Software.<br/><br/>THE&nbsp;SOFTWARE&nbsp;IS&nbsp;PROVIDED&nbsp;"AS&nbsp;IS",&nbsp;WITHOUT&nbsp;WARRANTY&nbsp;OF&nbsp;ANY&nbsp;KIND,&nbsp;EXPRESS&nbsp;OR<br/>IMPLIED,&nbsp;INCLUDING&nbsp;BUT&nbsp;NOT&nbsp;LIMITED&nbsp;TO&nbsp;THE&nbsp;WARRANTIES&nbsp;OF&nbsp;MERCHANTABILITY,<br/>FITNESS&nbsp;FOR&nbsp;A&nbsp;PARTICULAR&nbsp;PURPOSE&nbsp;AND&nbsp;NONINFRINGEMENT.&nbsp;IN&nbsp;NO&nbsp;EVENT&nbsp;SHALL&nbsp;THE<br/>AUTHORS&nbsp;OR&nbsp;COPYRIGHT&nbsp;HOLDERS&nbsp;BE&nbsp;LIABLE&nbsp;FOR&nbsp;ANY&nbsp;CLAIM,&nbsp;DAMAGES&nbsp;OR&nbsp;OTHER<br/>LIABILITY,&nbsp;WHETHER&nbsp;IN&nbsp;AN&nbsp;ACTION&nbsp;OF&nbsp;CONTRACT,&nbsp;TORT&nbsp;OR&nbsp;OTHERWISE,&nbsp;ARISING&nbsp;FROM,<br/>OUT&nbsp;OF&nbsp;OR&nbsp;IN&nbsp;CONNECTION&nbsp;WITH&nbsp;THE&nbsp;SOFTWARE&nbsp;OR&nbsp;THE&nbsp;USE&nbsp;OR&nbsp;OTHER&nbsp;DEALINGS&nbsp;IN<br/>THE&nbsp;SOFTWARE.</div></div><br/><br/>]]></description>
            <guid isPermaLink="false">efd9cc14ac62cd5ea1d5f813b552ba6e5e0f9e3e</guid>
            <pubDate>Wed, 20 Feb 2008 01:20:00 +0000</pubDate>
        </item>
        <item>
            <title>boodebr.disthelper</title>
            <link>http://www.boodebr.org/pages/boodebr/boodebr.disthelper.html</link>
            <description><![CDATA[Nothing here yet.<br/><br/>]]></description>
            <guid isPermaLink="false">372fe54d7d57514efbcbc888566ccaa529d172c5</guid>
            <pubDate>Mon, 21 Jan 2008 14:40:00 +0000</pubDate>
        </item>
        <item>
            <title>boodebr.gui</title>
            <link>http://www.boodebr.org/pages/boodebr/boodebr.gui.html</link>
            <description><![CDATA[A light (but getting longer :-) wrapper for wxPython<br/><br/>Purposes: <ul class="wikkly-ul"><li class="wikkly-ul-li1">Provide a simpler API for the most common cases </li><li class="wikkly-ul-li1">ids are autogenerated &amp; callbacks set in constructors </li><li class="wikkly-ul-li1">I try to always write vs. this interface, so I can fix bugs/provide workarounds in one location. </li><li class="wikkly-ul-li1">Add some common convenience functions/classes </li><li class="wikkly-ul-li1">I prefer shortnames &amp; everything in lowercase<br/><br/></li></ul>]]></description>
            <guid isPermaLink="false">a202b0c1ec07ee3622631c2787132652c9afd4a5</guid>
            <pubDate>Mon, 21 Jan 2008 14:38:00 +0000</pubDate>
        </item>
        <item>
            <title>Support</title>
            <link>http://www.boodebr.org/pages/boodebr/Support.html</link>
            <description><![CDATA[Please post questions to the <a title="Link to http://groups.google.com" class="wikkly-a-www" href="http://groups.google.com/group/boodebr/topics" onclick="window.open(this.href);return false;">mailing list</a> so others may benefit from the answers. ]]></description>
            <guid isPermaLink="false">b976083735e7ab5868493832842f948b55c20c98</guid>
            <pubDate>Mon, 12 Nov 2007 21:38:00 +0000</pubDate>
        </item>
    </channel>
</rss>

