[Zope-Checkins] CVS: Zope3/lib/python/Zope/App/RDB - Connection.stx:1.1 IConnection.py:1.1 IConnectionService.py:1.1 ICursor.py:1.1 IDBIConnection.py:1.1 IDBICursor.py:1.1 IDBITypeInfo.py:1.1 IDBITypeInfoProvider.py:1.1 IDatabaseAdapter.py:1.1 IResultSet.py:1.1 IZopeConnection.py:1.1 IZopeCursor.py:1.1 SQLQuery.stx:1.1

Stephan Richter srichter@cbu.edu
Mon, 24 Jun 2002 07:14:18 -0400


Update of /cvs-repository/Zope3/lib/python/Zope/App/RDB
In directory cvs.zope.org:/tmp/cvs-serv28851/RDB

Added Files:
	Connection.stx IConnection.py IConnectionService.py ICursor.py 
	IDBIConnection.py IDBICursor.py IDBITypeInfo.py 
	IDBITypeInfoProvider.py IDatabaseAdapter.py IResultSet.py 
	IZopeConnection.py IZopeCursor.py SQLQuery.stx 
Log Message:
EP Sprint: RDB team

Check-in of the interfaces, so that we can start working in pairs 
independently. 


=== Added File Zope3/lib/python/Zope/App/RDB/Connection.stx ===
RDB Connection implementation


  The RDB Connection has basically three parts to its functionality:
  
    - Database-specific information

    - SQL command execution (includes Zope transaction integration)

    - Result interpretation/conversion


  Database-specific information

    Before we can start making connections, we need to know what databases are
    available for usage and what their specific information are. These
    database-specific information are handled by an object that implements the
    IDBIInformation interface. This interface basically consists of three sub
    interfaces:

      o IFieldTypeConverter - This interface specifies how to convert database
        output fields into its native Python type.  
        For example: '2002/01/01' --> Date(2002, 01, 01)

      o IDBIParamStyle - This interface specifies the query parameter style
        used for the database query. This maps directly to the Python DB API.

      o IThreadSafetyLevel - Specifies the thread level safety of this
        particular DBI API implementation. The minimum should be 1.

    The IDBIInformation objects are managed by an IDBIInformationService,
    which is most likely implemented as a global service.


  SQL command execution
  
    All available Database connections (IConnection) are manage by the
    IConnectionService. The IConnection mainly implements the DB API
    connection API, including the ICursor. It also handles the transaction
    management, which requires an adapter to
    Transaction.IDataManager. Finally, there must be an adapter to
    IDBIInformation to query for necessary data.
 

  Result interpretation/conversion

    The result of a query is an IResultSet object that provides us with meta
    data about the contained rows and fields such as field names, number of
    columns, field types and the actual records.

    At the moment I am not sure how we are going to port Brains, but it seems
    like that Steve's plugin architecture for the ObjectHub will be more
    suitable than the current implementation of Brains.


=== Added File Zope3/lib/python/Zope/App/RDB/IConnection.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""

Revision information:
$Id: IConnection.py,v 1.1 2002/06/24 11:14:17 srichter Exp $
"""
from Interface import Interface

class IConnection(Interface):
    """A DB-API based Interface
    """
    
    def cursor():
        """Return a new ICursor Object using the connection. If the database
        does not provide a direct cursor concept, the module will have to
        emulate cursors using other means to the extent needed by this
        specification.  """

    def commit():
        """Commit any pending transaction to the database. Note that if the
        database supports an auto-commit feature, this must be initially off.
        An interface method may be provided to turn it back on.

        Database modules that do not support transactions should implement
        this method with void functionality.
        """
        
    def rollback():
        """In case a database does provide transactions this method causes the
        database to roll back to the start of any pending transaction. Closing
        a connection without committing the changes first will cause an
        implicit rollback to be performed.  """

    def close():
        """Close the connection now (rather than whenever __del__ is
        called). The connection will be unusable from this point forward; an
        Error (or subclass) exception will be raised if any operation is
        attempted with the connection. The same applies to all cursor objects
        trying to use the connection.  """


=== Added File Zope3/lib/python/Zope/App/RDB/IConnectionService.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""

Revision information:
$Id: IConnectionService.py,v 1.1 2002/06/24 11:14:17 srichter Exp $
"""
from Interface import Interface, Attribute

class IConnectionService(Interface):

    def getConnection(name):
        """Returns a connection object by name. """
        
    def queryConnection(name, default):
        """return a connection object by name or default"""        

    def getAvailableConnections():
        """returns the connections known to this connection service"""

        


=== Added File Zope3/lib/python/Zope/App/RDB/ICursor.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""
Revision information:
$Id: ICursor.py,v 1.1 2002/06/24 11:14:17 srichter Exp $
"""

from Interface import Interface, Attribute

class ICursor(Interface):

    """
    DB API ICursor interface
    """

    description = Attribute("""This read-only attribute is a sequence of 7-item sequences. Each of
        these sequences contains information describing one result column:
        (name, type_code, display_size, internal_size, precision, scale,
        null_ok). This attribute will be None for operations that do not
        return rows or if the cursor has not had an operation invoked via the
        executeXXX() method yet.

        The type_code can be interpreted by comparing it to the Type Objects
        specified in the section below. """)

    arraysize = Attribute("""This read/write attribute specifies the number of
        rows to fetch at a time with fetchmany(). It defaults to 1 meaning to
        fetch a single row at a time.

        Implementations must observe this value with respect to the
        fetchmany() method, but are free to interact with the database a
        single row at a time. It may also be used in the implementation of
        executemany().
        """)

    def close():
        """Close the cursor now (rather than whenever __del__ is called).  The
        cursor will be unusable from this point forward; an Error (or
        subclass) exception will be raised if any operation is attempted with
        the cursor.
        """

    def execute(operation, parameters=None):
        """Prepare and execute a database operation (query or
        command). Parameters may be provided as sequence or mapping and will
        be bound to variables in the operation. Variables are specified in a
        database-specific notation (see the module's paramstyle attribute for
        details). [5]

        A reference to the operation will be retained by the cursor. If the
        same operation object is passed in again, then the cursor can optimize
        its behavior. This is most effective for algorithms where the same
        operation is used, but different parameters are bound to it (many
        times).

        For maximum efficiency when reusing an operation, it is best to use
        the setinputsizes() method to specify the parameter types and sizes
        ahead of time. It is legal for a parameter to not match the predefined
        information; the implementation should compensate, possibly with a
        loss of efficiency.

        The parameters may also be specified as list of tuples to e.g. insert
        multiple rows in a single operation, but this kind of usage is
        depreciated: executemany() should be used instead.

        Return values are not defined.
        """


    def executemany(operation, seq_of_parameters):
        """Prepare a database operation (query or command) and then execute it
        against all parameter sequences or mappings found in the sequence
        seq_of_parameters.

        Modules are free to implement this method using multiple calls to the
        execute() method or by using array operations to have the database
        process the sequence as a whole in one call.
        
        The same comments as for execute() also apply accordingly to this
        method.

        Return values are not defined. 
        """
        
    def fetchone():
        """Fetch the next row of a query result set, returning a single sequence,
        or None when no more data is available. [6]

        An Error (or subclass) exception is raised if the previous call to
        executeXXX() did not produce any result set or no call was issued yet.
        """

    def fetchmany(size=ICursor.arraysize):
        """Fetch the next set of rows of a query result, returning a sequence of
        sequences (e.g. a list of tuples). An empty sequence is returned when
        no more rows are available.

        The number of rows to fetch per call is specified by the parameter. If
        it is not given, the cursor's arraysize determines the number of rows
        to be fetched. The method should try to fetch as many rows as
        indicated by the size parameter. If this is not possible due to the
        specified number of rows not being available, fewer rows may be
        returned.

        An Error (or subclass) exception is raised if the previous call to
        executeXXX() did not produce any result set or no call was issued yet.

        Note there are performance considerations involved with the size
        parameter. For optimal performance, it is usually best to use the
        arraysize attribute. If the size parameter is used, then it is best
        for it to retain the same value from one fetchmany() call to the next.
        """

    def fetchall():
        """
        Fetch all (remaining) rows of a query result, returning them as a
        sequence of sequences (e.g. a list of tuples). Note that the cursor's
        arraysize attribute can affect the performance of this operation.

        An Error (or subclass) exception is raised if the previous call to
        executeXXX() did not produce any result set or no call was issued yet.
        """
        


=== Added File Zope3/lib/python/Zope/App/RDB/IDBIConnection.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""

Revision information:
$Id: IDBIConnection.py,v 1.1 2002/06/24 11:14:17 srichter Exp $
"""

from Interface import Interface

class IDBIConnection(Interface):
    """A DB-API based Interface """
    
    def cursor():
        """Return a new ICursor Object using the connection.
        
        If the database does not provide a direct cursor concept, the module
        will have to emulate cursors using other means to the extent needed by
        this specification.  """

    def commit():
        """Commit any pending transaction to the database. Note that if the
        database supports an auto-commit feature, this must be initially off.
        An interface method may be provided to turn it back on.

        Database modules that do not support transactions should implement
        this method with void functionality.
        """
        
    def rollback():
        """In case a database does provide transactions this method causes the
        database to roll back to the start of any pending transaction. Closing
        a connection without committing the changes first will cause an
        implicit rollback to be performed.  """

    def close():
        """Close the connection now (rather than whenever __del__ is
        called). The connection will be unusable from this point forward; an
        Error (or subclass) exception will be raised if any operation is
        attempted with the connection. The same applies to all cursor objects
        trying to use the connection.  """


=== Added File Zope3/lib/python/Zope/App/RDB/IDBICursor.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""
Revision information:
$Id: IDBICursor.py,v 1.1 2002/06/24 11:14:17 srichter Exp $
"""

from Interface import Interface, Attribute

class IDBICursor(Interface):
    """DB API ICursor interface"""

    description = Attribute("""This read-only attribute is a sequence of 7-item sequences. Each of
        these sequences contains information describing one result column:
        (name, type_code, display_size, internal_size, precision, scale,
        null_ok). This attribute will be None for operations that do not
        return rows or if the cursor has not had an operation invoked via the
        executeXXX() method yet.

        The type_code can be interpreted by comparing it to the Type Objects
        specified in the section below. """)

    arraysize = Attribute("""This read/write attribute specifies the number of
        rows to fetch at a time with fetchmany(). It defaults to 1 meaning to
        fetch a single row at a time.

        Implementations must observe this value with respect to the
        fetchmany() method, but are free to interact with the database a
        single row at a time. It may also be used in the implementation of
        executemany().
        """)

    def close():
        """Close the cursor now (rather than whenever __del__ is called).  The
        cursor will be unusable from this point forward; an Error (or
        subclass) exception will be raised if any operation is attempted with
        the cursor.
        """

    def execute(operation, parameters=None):
        """Prepare and execute a database operation (query or
        command). Parameters may be provided as sequence or mapping and will
        be bound to variables in the operation. Variables are specified in a
        database-specific notation (see the module's paramstyle attribute for
        details). [5]

        A reference to the operation will be retained by the cursor. If the
        same operation object is passed in again, then the cursor can optimize
        its behavior. This is most effective for algorithms where the same
        operation is used, but different parameters are bound to it (many
        times).

        For maximum efficiency when reusing an operation, it is best to use
        the setinputsizes() method to specify the parameter types and sizes
        ahead of time. It is legal for a parameter to not match the predefined
        information; the implementation should compensate, possibly with a
        loss of efficiency.

        The parameters may also be specified as list of tuples to e.g. insert
        multiple rows in a single operation, but this kind of usage is
        depreciated: executemany() should be used instead.

        Return values are not defined.
        """


    def executemany(operation, seq_of_parameters):
        """Prepare a database operation (query or command) and then execute it
        against all parameter sequences or mappings found in the sequence
        seq_of_parameters.

        Modules are free to implement this method using multiple calls to the
        execute() method or by using array operations to have the database
        process the sequence as a whole in one call.
        
        The same comments as for execute() also apply accordingly to this
        method.

        Return values are not defined. 
        """
        
    def fetchone():
        """Fetch the next row of a query result set, returning a single sequence,
        or None when no more data is available. [6]

        An Error (or subclass) exception is raised if the previous call to
        executeXXX() did not produce any result set or no call was issued yet.
        """

    def fetchmany(size=ICursor.arraysize):
        """Fetch the next set of rows of a query result, returning a sequence of
        sequences (e.g. a list of tuples). An empty sequence is returned when
        no more rows are available.

        The number of rows to fetch per call is specified by the parameter. If
        it is not given, the cursor's arraysize determines the number of rows
        to be fetched. The method should try to fetch as many rows as
        indicated by the size parameter. If this is not possible due to the
        specified number of rows not being available, fewer rows may be
        returned.

        An Error (or subclass) exception is raised if the previous call to
        executeXXX() did not produce any result set or no call was issued yet.

        Note there are performance considerations involved with the size
        parameter. For optimal performance, it is usually best to use the
        arraysize attribute. If the size parameter is used, then it is best
        for it to retain the same value from one fetchmany() call to the next.
        """

    def fetchall():
        """
        Fetch all (remaining) rows of a query result, returning them as a
        sequence of sequences (e.g. a list of tuples). Note that the cursor's
        arraysize attribute can affect the performance of this operation.

        An Error (or subclass) exception is raised if the previous call to
        executeXXX() did not produce any result set or no call was issued yet.
        """
        


=== Added File Zope3/lib/python/Zope/App/RDB/IDBITypeInfo.py ===
from Interface import Interface, Attribute
class IDBITypeInfo(Interface):
    """
    Database adapter specific information
    """
    paramstyle = Attribute("""
        String constant stating the type of parameter marker formatting
        expected by the interface. Possible values are [2]:

       'qmark' = Question mark style, e.g. '...WHERE name=?'
       'numeric' = Numeric, positional style, e.g. '...WHERE name=:1'
       'named' = Named style, e.g. '...WHERE name=:name'
       'format' = ANSI C printf format codes, e.g. '...WHERE name=%s'
       'pyformat' = Python extended format codes, e.g. '...WHERE name=%(name)s'
       """)

    threadsafety = Attribute("""
        Integer constant stating the level of thread safety the interface
        supports. Possible values are:

            0 = Threads may not share the module.
            1 = Threads may share the module, but not connections.
            2 = Threads may share the module and connections.
            3 = Threads may share the module, connections and cursors.

        Sharing in the above context means that two threads may use a resource
        without wrapping it using a mutex semaphore to implement resource
        locking. Note that you cannot always make external resources thread safe
        by managing access using a mutex: the resource may rely on global
        variables or other external sources that are beyond your control.
        """)

    def getConverter():
        """
        Return the field type converter.
        """

class IFieldTypeConverter(Interface):
    """
    
    """

    def __getitem__(key):
        """
        return a converter function for field type matching key
        """


=== Added File Zope3/lib/python/Zope/App/RDB/IDBITypeInfoProvider.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""XXX short summary goes here.

XXX longer description goes here.

$Id: IDBITypeInfoProvider.py,v 1.1 2002/06/24 11:14:17 srichter Exp $
"""

from Interface import Interface

class IDBITypeInfoProvider(Interface):

    def getTypeInfo():
        """return an ITypeInfo object"""


=== Added File Zope3/lib/python/Zope/App/RDB/IDatabaseAdapter.py ===
from Interface import Interface

class IDatabaseAdapter(Interface):
    """ interface for persistent object that returns
    volatile IConnections. """

    def __call__():
        """return an Iconnection object"""



=== Added File Zope3/lib/python/Zope/App/RDB/IResultSet.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""XXX short summary goes here.

XXX longer description goes here.

$Id: IResultSet.py,v 1.1 2002/06/24 11:14:17 srichter Exp $
"""


from Interface import Interface

class IResultSet(Interface):

    pass


=== Added File Zope3/lib/python/Zope/App/RDB/IZopeConnection.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""

Revision information:
$Id: IZopeConnection.py,v 1.1 2002/06/24 11:14:17 srichter Exp $
"""

from IDBIConnection import IDBIConnection
from IDBITypeInfoProvider import IDBITypeInfoProvider
from Transactions.IDataManager import IDataManager

class IZopeConnection(IDBIConnection, IDataManager, IDBITypeInfoProvider):

    def cursor():
        """
        return a ZopeCursor object
        """
    

        


=== Added File Zope3/lib/python/Zope/App/RDB/IZopeCursor.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""XXX short summary goes here.

XXX longer description goes here.

$Id: IZopeCursor.py,v 1.1 2002/06/24 11:14:17 srichter Exp $
"""

from IDBICursor import IDBICursor

class IZopeCursor(IDBICursor):

    """an iCursor that integrates with zope's transactions"""

    def execute(operation, parameters=None):
        """executes an operation, registering the underlying connection with
        the transaction system.

        See ICursor for more detailed execute information.
        """

    def executemany(operation, seq_of_parameters=None):
        """executes an operation, registering the underlying connection with
        the transaction system.

        See ICursor for more detailed executemany information.
        """
        


=== Added File Zope3/lib/python/Zope/App/RDB/SQLQuery.stx ===
SQL Query Interface


  Examples

    1. Simple variable replacement::

       SELECT * 
         FROM Table
         WHERE id = <tal replace="attributes/id" />


    2. Two variable replacement::

       SELECT * 
         FROM Table
         WHERE id = <tal replace="attributes/id" />
           AND title = <tal replace="attributes/title" />


    3. Conditional constraint::
   
       <sql>
       SELECT *
         FROM Table
         <tal condition="python: attributes['id'] != None">
           WHERE id &le; <tal replace="attributes/id" />
         </tal>
       </sql>
    
    4. Multicommand script::

       INSERT INTO Table (id, title) VALUES (
         <tal replace="attributes/id">,
         <tal replace="attributes/title">)

       <tal replace="sql/delimiter">

       SELECT uid 
         FROM Table 
         WHERE id = <tal replace="attributes/id">


  There will be an interface called ISQLScript that provides the basic methods
  to make the script working. Most likely we are going to have at least two
  implementations of this interface::

    - SimpleSQLScript - This script cannot contain any dynamically generated
      SQL code.

    - PTSQLScript - This script's dynamic behavior is realized using regular
      Zope Page Templates and TAL.

  Note that both scripts can live in Content and Service space as well as
  being a filesystem-based view.


  SQLScript::

    class ISQLScript(Interface):
        """This interface describes the minimal methods required to implement
        an SQL script."""
    
        def getConnection():
            """Get the database connection from the service."""

        def execute(arguments):
            """Execute the query. Note that simple implementations might not
            make use of the arguments at all."""

	def setSource(source):
            """Save the source of the query."""

        def getSource():
            """Get the source of the query."""

	def __call_(**kw):
	    """Well, methods should be callable. ;)"""


  The simple SQLScript class basically implements these methods. 


  PTSQLScript::

    class IPTSQLScript(ISQLScript):
        """This interface defines a PageTemplate-based SQL Script."""

        def render(arguments):
            """Render the page template."""

        def pt_getContext(self, arguments):
	    """This is the really interesting method as it defines the
	    available namespaces for our PT-based SQL Script.

            I propose that we should have two namespaces:
        
              - arguments: This namespace contains the arguments that were
                passed to the method.

              - sql: This namespace will contain some helper functions to make
                life easier. One example would be a sql_encode method.
            """


    class PTSQLScript(AppPT, PageTemplate, Persistent):

        __implements__ = IFileContent, IPTSQLScript

	# and so on...