]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Connection.begin() no longer accepts nested=True, a possible source of confusion...
authorJason Kirtland <jek@discorporate.us>
Sun, 19 Aug 2007 17:57:51 +0000 (17:57 +0000)
committerJason Kirtland <jek@discorporate.us>
Sun, 19 Aug 2007 17:57:51 +0000 (17:57 +0000)
- Docstring love for the engine package.  More is needed.

lib/sqlalchemy/engine/__init__.py
lib/sqlalchemy/engine/base.py
lib/sqlalchemy/engine/default.py
lib/sqlalchemy/engine/strategies.py
lib/sqlalchemy/engine/threadlocal.py
lib/sqlalchemy/engine/url.py

index 070ff3c3e53e5f4645082545ee2ea257eee2ffd3..ae32b40bbc325eab5cf27dbd2b71717ba63c30c1 100644 (file)
@@ -4,45 +4,50 @@
 # This module is part of SQLAlchemy and is released under
 # the MIT License: http://www.opensource.org/licenses/mit-license.php
 
-"""defines the basic components used to interface DBAPI modules with
-higher-level statement-construction, connection-management, 
-execution and result contexts.  The primary "entry point" class into
-this package is the Engine.
-
-The package is represented among several individual modules, including:
-
-    base.py
-        Defines interface classes and some implementation classes
-        which comprise the basic components used to interface between
-        a DBAPI, constructed and plain-text statements, 
-        connections, transactions, and results.
-        
-    default.py
-        Contains default implementations of some of the components 
-        defined in base.py.  All current database dialects use the 
-        classes in default.py as base classes for their own database-specific
-        implementations.
-    
-    strategies.py
-        the mechanics of constructing ``Engine`` objects are represented here.
-        Defines the ``EngineStrategy`` class which represents how to go from 
-        arguments specified to the ``create_engine()`` function, to a fully
-        constructed ``Engine``, including initialization of connection pooling,
-        dialects, and specific subclasses of ``Engine``.
-        
-    threadlocal.py
-        the ``TLEngine`` class is defined here, which is a subclass of the generic
-        ``Engine`` and tracks ``Connection`` and ``Transaction`` objects against
-        the identity of the current thread.  This allows certain programming patterns
-        based around the concept of a "thread-local connection" to be possible.  The
-        ``TLEngine`` is created by using the "threadlocal" engine strategy in 
-        conjunction with the ``create_engine()`` function.
-        
-    url.py
-        Defines the ``URL`` class which represents the individual components of a 
-        string URL passed to ``create_engine()``.  Also defines a basic module-loading
-        strategy for the dialect specifier within a URL.
-        
+"""SQL connections, SQL execution and high-level DB-API interface.
+
+The engine package defines the basic components used to interface
+DB-API modules with higher-level statement construction,
+connection-management, execution and result contexts.  The primary
+"entry point" class into this package is the Engine and it's public
+constructor ``create_engine()``.
+
+This package includes:
+
+base.py
+    Defines interface classes and some implementation classes which
+    comprise the basic components used to interface between a DB-API,
+    constructed and plain-text statements, connections, transactions,
+    and results.
+
+default.py
+    Contains default implementations of some of the components defined
+    in base.py.  All current database dialects use the classes in
+    default.py as base classes for their own database-specific
+    implementations.
+
+strategies.py
+    The mechanics of constructing ``Engine`` objects are represented
+    here.  Defines the ``EngineStrategy`` class which represents how
+    to go from arguments specified to the ``create_engine()``
+    function, to a fully constructed ``Engine``, including
+    initialization of connection pooling, dialects, and specific
+    subclasses of ``Engine``.
+
+threadlocal.py
+    The ``TLEngine`` class is defined here, which is a subclass of
+    the generic ``Engine`` and tracks ``Connection`` and
+    ``Transaction`` objects against the identity of the current
+    thread.  This allows certain programming patterns based around
+    the concept of a "thread-local connection" to be possible.
+    The ``TLEngine`` is created by using the "threadlocal" engine
+    strategy in conjunction with the ``create_engine()`` function.
+
+url.py
+    Defines the ``URL`` class which represents the individual
+    components of a string URL passed to ``create_engine()``.  Also
+    defines a basic module-loading strategy for the dialect specifier
+    within a URL.
 """
 
 import sqlalchemy.databases
@@ -64,7 +69,7 @@ def engine_descriptors():
 
     arguments
       a dictionary describing the name and description of each
-      parameter used to connect to this engine's underlying DBAPI.
+      parameter used to connect to this engine's underlying DB-API.
 
     This function is meant for usage in automated configuration tools
     that wish to query the user for database and connection
@@ -73,7 +78,8 @@ def engine_descriptors():
 
     result = []
     for module in sqlalchemy.databases.__all__:
-        module = getattr(__import__('sqlalchemy.databases.%s' % module).databases, module)
+        module = getattr(
+            __import__('sqlalchemy.databases.%s' % module).databases, module)
         result.append(module.descriptor())
     return result
 
@@ -86,10 +92,11 @@ def create_engine(*args, **kwargs):
     dialect and connection arguments, with additional keyword
     arguments sent as options to the dialect and resulting Engine.
 
-    The URL is a string in the form 
-    ``dialect://user:password@host/dbname[?key=value..]``, where 
+    The URL is a string in the form
+    ``dialect://user:password@host/dbname[?key=value..]``, where
     ``dialect`` is a name such as ``mysql``, ``oracle``, ``postgres``,
-    etc.  Alternatively, the URL can be an instance of ``sqlalchemy.engine.url.URL``.
+    etc.  Alternatively, the URL can be an instance of
+    ``sqlalchemy.engine.url.URL``.
 
     `**kwargs` represents options to be sent to the Engine itself as
     well as the components of the Engine, including the Dialect, the
@@ -97,17 +104,17 @@ def create_engine(*args, **kwargs):
     follows:
 
     poolclass
-      a subclass of ``sqlalchemy.pool.Pool`` which will be used to 
+      a subclass of ``sqlalchemy.pool.Pool`` which will be used to
       instantiate a connection pool.
-      
+
     pool
       an instance of ``sqlalchemy.pool.DBProxy`` or
       ``sqlalchemy.pool.Pool`` to be used as the underlying source for
-      connections (DBProxy/Pool is described in the previous
-      section).  This argument supercedes "poolclass".
+      connections (DBProxy/Pool is described in the previous section).
+      This argument supercedes "poolclass".
 
     echo
-      Defaults to False: if True, the Engine will log all statements
+      defaults to False: if True, the Engine will log all statements
       as well as a repr() of their parameter lists to the engines
       logger, which defaults to ``sys.stdout``.  A Engine instances'
       `echo` data member can be modified at any time to turn logging
@@ -115,38 +122,36 @@ def create_engine(*args, **kwargs):
       printed to the standard output as well.
 
     logger
-      Defaults to None: a file-like object where logging output can be
+      defaults to None: a file-like object where logging output can be
       sent, if `echo` is set to True.  This defaults to
       ``sys.stdout``.
 
     encoding
-      Defaults to 'utf-8': the encoding to be used when
+      defaults to 'utf-8': the encoding to be used when
       encoding/decoding Unicode strings.
 
     convert_unicode
-      Defaults to False: true if unicode conversion should be applied
+      defaults to False: true if unicode conversion should be applied
       to all str types.
 
     module
-      Defaults to None: this is a
-      reference to a DBAPI2 module to be used instead of the engine's
-      default module.  For Postgres, the default is psycopg2, or
-      psycopg1 if 2 cannot be found.  For Oracle, its cx_Oracle.  For
-      mysql, MySQLdb.
+      defaults to None: this is a reference to a DB-API 2.0 module to
+      be used instead of the dialect's default module.
 
     strategy
-      allows alternate Engine implementations to take effect.
-      Current implementations include ``plain`` and ``threadlocal``.  
-      The default used by this function is ``plain``.
-
-      ``plain`` provides support for a Connection object which can be used
-      to execute SQL queries with a specific underlying DBAPI connection.
-
-      ``threadlocal`` is similar to ``plain`` except that it adds support
-      for a thread-local connection and transaction context, which
-      allows a group of engine operations to participate using the same
-      underlying connection and transaction without the need for explicitly
-      passing a single Connection.
+      allows alternate Engine implementations to take effect.  Current
+      implementations include ``plain`` and ``threadlocal``.  The
+      default used by this function is ``plain``.
+
+      ``plain`` provides support for a Connection object which can be
+      used to execute SQL queries with a specific underlying DB-API
+      connection.
+
+      ``threadlocal`` is similar to ``plain`` except that it adds
+      support for a thread-local connection and transaction context,
+      which allows a group of engine operations to participate using
+      the same underlying connection and transaction without the need
+      for explicitly passing a single Connection.
     """
 
     strategy = kwargs.pop('strategy', default_strategy)
@@ -155,17 +160,19 @@ def create_engine(*args, **kwargs):
 
 def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs):
     """Create a new Engine instance using a configuration dictionary.
-    
-    the dictionary is typically produced from a config file where keys are prefixed,
-    such as sqlalchemy.url, sqlalchemy.echo, etc.  The 'prefix' argument indicates 
-    the prefix to be searched for.
-    
-    A select set of keyword arguments will be "coerced" to their expected type based on 
-    string values.  in a future release, this functionality will be expanded to include 
-    dialect-specific arguments.
+
+    The dictionary is typically produced from a config file where keys
+    are prefixed, such as sqlalchemy.url, sqlalchemy.echo, etc.  The
+    'prefix' argument indicates the prefix to be searched for.
+
+    A select set of keyword arguments will be "coerced" to their
+    expected type based on string values.  in a future release, this
+    functionality will be expanded to include dialect-specific
+    arguments.
     """
 
-    opts = dict([(key[len(prefix):], configuration[key]) for key in configuration if key.startswith(prefix)])
+    opts = dict([(key[len(prefix):], configuration[key])
+                 for key in configuration if key.startswith(prefix)])
     for opt, type_ in (
         ('convert_unicode', bool),
         ('pool_timeout', int),
index 553c8df845c28a8646959b585ec3d32127f3f9b2..298264362cb9cf8c9a96ab2bed532e614dc1db58 100644 (file)
@@ -4,9 +4,13 @@
 # This module is part of SQLAlchemy and is released under
 # the MIT License: http://www.opensource.org/licenses/mit-license.php
 
-"""defines the basic components used to interface DBAPI modules with
-higher-level statement-construction, connection-management, 
-execution and result contexts."""
+
+"""Basic components for SQL execution and interfacing with DB-API..
+
+Defines the basic components used to interface DB-API modules with
+higher-level statement-construction, connection-management, execution
+and result contexts.
+"""
 
 from sqlalchemy import exceptions, schema, util, types, logging
 from sqlalchemy.sql import expression, visitors
@@ -14,105 +18,124 @@ import StringIO, sys
 
 
 class Dialect(object):
-    """Define the behavior of a specific database/DBAPI.
+    """Define the behavior of a specific database and DB-API combination.
 
-    Any aspect of metadata definition, SQL query generation, execution,
-    result-set handling, or anything else which varies between
-    databases is defined under the general category of the Dialect.
-    The Dialect acts as a factory for other database-specific object
-    implementations including ExecutionContext, Compiled,
-    DefaultGenerator, and TypeEngine.
+    Any aspect of metadata definition, SQL query generation,
+    execution, result-set handling, or anything else which varies
+    between databases is defined under the general category of the
+    Dialect.  The Dialect acts as a factory for other
+    database-specific object implementations including
+    ExecutionContext, Compiled, DefaultGenerator, and TypeEngine.
 
     All Dialects implement the following attributes:
 
-      positional
-        True if the paramstyle for this Dialect is positional
+    positional
+      True if the paramstyle for this Dialect is positional.
 
-      paramstyle
-        The paramstyle to be used (some DBAPIs support multiple paramstyles)
+    paramstyle
+      the paramstyle to be used (some DB-APIs support multiple
+      paramstyles).
 
-      convert_unicode
-        True if unicode conversion should be applied to all str types
+    convert_unicode
+      True if Unicode conversion should be applied to all ``str``
+      types.
 
-      encoding
-        type of encoding to use for unicode, usually defaults to 'utf-8'
+    encoding
+      type of encoding to use for unicode, usually defaults to
+      'utf-8'.
 
-      schemagenerator
-        a [sqlalchemy.schema#SchemaVisitor] class which generates schemas.
+    schemagenerator
+      a [sqlalchemy.schema#SchemaVisitor] class which generates
+      schemas.
 
-      schemadropper
-        a [sqlalchemy.schema#SchemaVisitor] class which drops schemas.
+    schemadropper
+      a [sqlalchemy.schema#SchemaVisitor] class which drops schemas.
 
-      defaultrunner
-        a [sqlalchemy.schema#SchemaVisitor] class which executes defaults.
+    defaultrunner
+      a [sqlalchemy.schema#SchemaVisitor] class which executes
+      defaults.
 
-      statement_compiler
-        a [sqlalchemy.engine.base#Compiled] class used to compile SQL statements
+    statement_compiler
+      a [sqlalchemy.engine.base#Compiled] class used to compile SQL
+      statements
 
-      preparer
-        a [sqlalchemy.sql.compiler#IdentifierPreparer] class used to quote
-        identifiers.
+    preparer
+      a [sqlalchemy.sql.compiler#IdentifierPreparer] class used to
+      quote identifiers.
     """
 
     def create_connect_args(self, url):
-        """Build DBAPI compatible connection arguments.
+        """Build DB-API compatible connection arguments.
 
-        Given a [sqlalchemy.engine.url#URL] object, returns a
-        tuple consisting of a `*args`/`**kwargs` suitable to send directly
-        to the dbapi's connect function. 
+        Given a [sqlalchemy.engine.url#URL] object, returns a tuple
+        consisting of a `*args`/`**kwargs` suitable to send directly
+        to the dbapi's connect function.
         """
 
         raise NotImplementedError()
 
     def dbapi_type_map(self):
-        """return a mapping of DBAPI type objects present in this Dialect's DBAPI
-        mapped to TypeEngine implementations used by the dialect. 
-        
-        This is used to apply types to result sets based on the DBAPI types
-        present in cursor.description; it only takes effect for result sets against
-        textual statements where no explicit typemap was present.  Constructed SQL statements
-        always have type information explicitly embedded.
+        """Returns a DB-API to sqlalchemy.types mapping.
+
+        A mapping of DB-API type objects present in this Dialect's
+        DB-API implmentation mapped to TypeEngine implementations used
+        by the dialect.
+
+        This is used to apply types to result sets based on the DB-API
+        types present in cursor.description; it only takes effect for
+        result sets against textual statements where no explicit
+        typemap was present.  Constructed SQL statements always have
+        type information explicitly embedded.
         """
 
         raise NotImplementedError()
 
     def type_descriptor(self, typeobj):
-        """Transform the given [sqlalchemy.types#TypeEngine] instance from generic to database-specific.
+        """Transform a generic type to a database-specific type.
+
+        Transforms the given [sqlalchemy.types#TypeEngine] instance
+        from generic to database-specific.
 
-        Subclasses will usually use the [sqlalchemy.types#adapt_type()] method in the types module
-        to make this job easy.
+        Subclasses will usually use the
+        [sqlalchemy.types#adapt_type()] method in the types module to
+        make this job easy.
         """
 
         raise NotImplementedError()
 
     def oid_column_name(self, column):
-        """Return the oid column name for this dialect, or ``None`` if the dialect can't/won't support OID/ROWID.
+        """Return the oid column name for this Dialect
 
-        The [sqlalchemy.schema#Column] instance which represents OID for the query being
-        compiled is passed, so that the dialect can inspect the column
-        and its parent selectable to determine if OID/ROWID is not
-        selected for a particular selectable (i.e. oracle doesnt
-        support ROWID for UNION, GROUP BY, DISTINCT, etc.)
+        May return ``None`` if the dialect can't o won't support
+        OID/ROWID features.
+
+        The [sqlalchemy.schema#Column] instance which represents OID
+        for the query being compiled is passed, so that the dialect
+        can inspect the column and its parent selectable to determine
+        if OID/ROWID is not selected for a particular selectable
+        (i.e. Oracle doesnt support ROWID for UNION, GROUP BY,
+        DISTINCT, etc.)
         """
 
         raise NotImplementedError()
 
     def supports_alter(self):
-        """return ``True`` if the database supports ``ALTER TABLE``."""
+        """Return ``True`` if the database supports ``ALTER TABLE``."""
         raise NotImplementedError()
 
     def max_identifier_length(self):
         """Return the maximum length of identifier names.
-        
-        Return ``None`` if no limit."""
-        
+
+        Returns ``None`` if no limit.
+        """
+
         return None
 
     def supports_unicode_statements(self):
-        """indicate whether the DBAPI can receive SQL statements as Python unicode strings"""
-        
+        """Indicate whether the DB-API can receive SQL statements as Python unicode strings"""
+
         raise NotImplementedError()
-        
+
     def supports_sane_rowcount(self):
         """Indicate whether the dialect properly implements rowcount for ``UPDATE`` and ``DELETE`` statements.
 
@@ -131,9 +154,11 @@ class Dialect(object):
     def reflecttable(self, connection, table, include_columns=None):
         """Load table description from the database.
 
-        Given a [sqlalchemy.engine#Connection] and a [sqlalchemy.schema#Table] object, reflect its
-        columns and properties from the database.  If include_columns (a list or set) is specified, limit the autoload
-        to the given column names.
+        Given a [sqlalchemy.engine#Connection] and a
+        [sqlalchemy.schema#Table] object, reflect its columns and
+        properties from the database.  If include_columns (a list or
+        set) is specified, limit the autoload to the given column
+        names.
         """
 
         raise NotImplementedError()
@@ -141,9 +166,10 @@ class Dialect(object):
     def has_table(self, connection, table_name, schema=None):
         """Check the existence of a particular table in the database.
 
-        Given a [sqlalchemy.engine#Connection] object and a string `table_name`, return True
-        if the given table (possibly within the specified `schema`)
-        exists in the database, False otherwise.
+        Given a [sqlalchemy.engine#Connection] object and a string
+        `table_name`, return True if the given table (possibly within
+        the specified `schema`) exists in the database, False
+        otherwise.
         """
 
         raise NotImplementedError()
@@ -151,9 +177,9 @@ class Dialect(object):
     def has_sequence(self, connection, sequence_name):
         """Check the existence of a particular sequence in the database.
 
-        Given a [sqlalchemy.engine#Connection] object and a string `sequence_name`, return
-        True if the given sequence exists in the database, False
-        otherwise.
+        Given a [sqlalchemy.engine#Connection] object and a string
+        `sequence_name`, return True if the given sequence exists in
+        the database, False otherwise.
         """
 
         raise NotImplementedError()
@@ -165,29 +191,31 @@ class Dialect(object):
 
     def create_execution_context(self, connection, compiled=None, compiled_parameters=None, statement=None, parameters=None):
         """Return a new [sqlalchemy.engine#ExecutionContext] object."""
-        
+
         raise NotImplementedError()
 
     def do_begin(self, connection):
-        """Provide an implementation of *connection.begin()*, given a DBAPI connection."""
+        """Provide an implementation of *connection.begin()*, given a DB-API connection."""
 
         raise NotImplementedError()
 
     def do_rollback(self, connection):
-        """Provide an implementation of *connection.rollback()*, given a DBAPI connection."""
+        """Provide an implementation of *connection.rollback()*, given a DB-API connection."""
 
         raise NotImplementedError()
 
     def create_xid(self):
-        """create a two-phase transaction ID.
+        """Create a two-phase transaction ID.
 
-        this id will be passed to do_begin_twophase(), do_rollback_twophase(),
-        do_commit_twophase().  its format is unspecified."""
+        This id will be passed to do_begin_twophase(),
+        do_rollback_twophase(), do_commit_twophase().  Its format is
+        unspecified.
+        """
 
         raise NotImplementedError()
 
     def do_commit(self, connection):
-        """Provide an implementation of *connection.commit()*, given a DBAPI connection."""
+        """Provide an implementation of *connection.commit()*, given a DB-API connection."""
 
         raise NotImplementedError()
 
@@ -242,8 +270,8 @@ class Dialect(object):
         raise NotImplementedError()
 
     def is_disconnect(self, e):
-        """Return True if the given DBAPI error indicates an invalid connection"""
-        
+        """Return True if the given DB-API error indicates an invalid connection"""
+
         raise NotImplementedError()
 
 
@@ -251,107 +279,106 @@ class ExecutionContext(object):
     """A messenger object for a Dialect that corresponds to a single execution.
 
     ExecutionContext should have these datamembers:
-    
-        connection
-            Connection object which can be freely used by default value generators
-            to execute SQL.  This Connection should reference the same underlying
-            connection/transactional resources of root_connection.
-            
-        root_connection
-            Connection object which is the source of this ExecutionContext.  This
-            Connection may have close_with_result=True set, in which case it can
-            only be used once.
 
-        dialect
-            dialect which created this ExecutionContext.
-            
-        cursor
-            DBAPI cursor procured from the connection
-            
-        compiled
-            if passed to constructor, sqlalchemy.engine.base.Compiled object being executed
-        
-        statement
-            string version of the statement to be executed.  Is either
-            passed to the constructor, or must be created from the 
-            sql.Compiled object by the time pre_exec() has completed.
-            
-        parameters
-            bind parameters passed to the execute() method.  for
-            compiled statements, this is a dictionary or list 
-            of dictionaries.  for textual statements, it should
-            be in a format suitable for the dialect's paramstyle
-            (i.e. dict or list of dicts for non positional,
-            list or list of lists/tuples for positional).
-            
-        isinsert
-          True if the statement is an INSERT
-            
-        isupdate
-          True if the statement is an UPDATE
-    
+    connection
+      Connection object which can be freely used by default value
+      generators to execute SQL.  This Connection should reference the
+      same underlying connection/transactional resources of
+      root_connection.
+
+    root_connection
+      Connection object which is the source of this ExecutionContext.  This
+      Connection may have close_with_result=True set, in which case it can
+      only be used once.
+
+   dialect
+      dialect which created this ExecutionContext.
+
+    cursor
+      DB-API cursor procured from the connection,
+
+    compiled
+      if passed to constructor, sqlalchemy.engine.base.Compiled object
+      being executed,
+
+    statement
+      string version of the statement to be executed.  Is either
+      passed to the constructor, or must be created from the
+      sql.Compiled object by the time pre_exec() has completed.
+
+    parameters
+      bind parameters passed to the execute() method.  For compiled
+      statements, this is a dictionary or list of dictionaries.  For
+      textual statements, it should be in a format suitable for the
+      dialect's paramstyle (i.e. dict or list of dicts for non
+      positional, list or list of lists/tuples for positional).
+
+    isinsert
+      True if the statement is an INSERT.
+
+    isupdate
+      True if the statement is an UPDATE.
+
     The Dialect should provide an ExecutionContext via the
     create_execution_context() method.  The `pre_exec` and `post_exec`
     methods will be called for compiled statements.
-    
     """
 
     def create_cursor(self):
         """Return a new cursor generated from this ExecutionContext's connection.
-        
-        Some dialects may wish to change the behavior of connection.cursor(),
-        such as postgres which may return a PG "server side" cursor.
+
+        Some dialects may wish to change the behavior of
+        connection.cursor(), such as postgres which may return a PG
+        "server side" cursor.
         """
 
         raise NotImplementedError()
 
     def pre_execution(self):
         """Called before an execution of a compiled statement.
-        
-        If a compiled statement was passed to this
-        ExecutionContext, the `statement` and `parameters` datamembers
-        must be initialized after this statement is complete.
+
+        If a compiled statement was passed to this ExecutionContext,
+        the `statement` and `parameters` datamembers must be
+        initialized after this statement is complete.
         """
 
         raise NotImplementedError()
 
     def post_execution(self):
         """Called after the execution of a compiled statement.
-        
+
         If a compiled statement was passed to this ExecutionContext,
-        the `last_insert_ids`, `last_inserted_params`, etc. 
-        datamembers should be available after this method
-        completes.
+        the `last_insert_ids`, `last_inserted_params`, etc.
+        datamembers should be available after this method completes.
         """
 
         raise NotImplementedError()
-    
+
     def result(self):
-        """return a result object corresponding to this ExecutionContext.
-        
-        Returns a ResultProxy."""
-        
+        """Return a result object corresponding to this ExecutionContext.
+
+        Returns a ResultProxy.
+        """
+
         raise NotImplementedError()
-        
+
     def get_rowcount(self):
         """Return the count of rows updated/deleted for an UPDATE/DELETE statement."""
 
         raise NotImplementedError()
 
     def should_autocommit(self):
-        """return True if this context's statement should be 'committed' automatically in a non-transactional context"""
+        """Return True if this context's statement should be 'committed' automatically in a non-transactional context"""
 
         raise NotImplementedError()
-        
+
     def last_inserted_ids(self):
         """Return the list of the primary key values for the last insert statement executed.
 
         This does not apply to straight textual clauses; only to
-        ``sql.Insert`` objects compiled against a ``schema.Table`` object.
-        The order of
-        items in the list is the same as that of the Table's
-        'primary_key' attribute.
-
+        ``sql.Insert`` objects compiled against a ``schema.Table``
+        object.  The order of items in the list is the same as that of
+        the Table's 'primary_key' attribute.
         """
 
         raise NotImplementedError()
@@ -498,7 +525,7 @@ class Connectable(object):
     dialect = util.NotImplProperty("Dialect which this Connectable is associated with.")
 
 class Connection(Connectable):
-    """Represent a single DBAPI connection returned from the underlying connection pool.
+    """Provides high-level functionality for a wrapped DB-API connection.
 
     Provides execution support for string-based SQL statements as well
     as ClauseElement, Compiled and DefaultGenerator objects.  Provides
@@ -507,7 +534,15 @@ class Connection(Connectable):
     The Connection object is **not** threadsafe.
     """
 
-    def __init__(self, engine, connection=None, close_with_result=False, _branch=False):
+    def __init__(self, engine, connection=None, close_with_result=False,
+                 _branch=False):
+        """Construct a new Connection.
+
+        Connection objects are typically constructed by an
+        [sqlalchemy.engine#Engine], see the ``connect()`` and
+        ``contextual_connect()`` methods of Engine.
+        """
+
         self.__engine = engine
         self.__connection = connection or engine.raw_connection()
         self.__transaction = None
@@ -525,82 +560,130 @@ class Connection(Connectable):
         """return a new Connection which references this Connection's 
         engine and connection; but does not have close_with_result enabled,
         and also whose close() method does nothing.
-        
+
         This is used to execute "sub" statements within a single execution,
         usually an INSERT statement.
         """
-        
+
         return Connection(self.__engine, self.__connection, _branch=True)
-        
+
     engine = property(lambda s:s.__engine, doc="The Engine with which this Connection is associated.")
     dialect = property(lambda s:s.__engine.dialect, doc="Dialect used by this Connection.")
-    connection = property(_get_connection, doc="The underlying DBAPI connection managed by this Connection.")
+    connection = property(_get_connection, doc="The underlying DB-API connection managed by this Connection.")
     should_close_with_result = property(lambda s:s.__close_with_result, doc="Indicates if this Connection should be closed when a corresponding ResultProxy is closed; this is essentially an auto-release mode.")
     properties = property(lambda s: s._get_connection().properties,
-                          doc="A set of per-DBAPI connection properties.")
+                          doc="A collection of per-DB-API connection instance properties.")
 
     def connect(self):
-        """connect() is implemented to return self so that an incoming Engine or Connection object can be treated similarly."""
+        """Returns self.
+
+        This ``Connectable`` interface method returns self, allowing
+        Connections to be used interchangably with Engines in most
+        situations that require a bind.
+        """
+
         return self
 
     def contextual_connect(self, **kwargs):
-        """contextual_connect() is implemented to return self so that an incoming Engine or Connection object can be treated similarly."""
+        """Returns self.
+
+        This ``Connectable`` interface method returns self, allowing
+        Connections to be used interchangably with Engines in most
+        situations that require a bind.
+        """
+
         return self
 
     def invalidate(self):
-        """invalidate the underying DBAPI connection and immediately close this Connection.
-        
-        The underlying DBAPI connection is literally closed (if possible), and is discarded.
-        Its source connection pool will typically create a new connection to replace it, once
-        requested.
+        """Invalidate and close the Connection.
+
+        The underlying DB-API connection is literally closed (if
+        possible), and is discarded.  Its source connection pool will
+        typically lazilly create a new connection to replace it.
         """
-        
+
         self.__connection.invalidate()
         self.__connection = None
 
     def detach(self):
-        """detach the underlying DBAPI connection from its connection pool.
-        
-        This Connection instance will remain useable.  When closed, the 
-        DBAPI connection will be literally closed and not returned to its pool.
-        The pool will typically create a new connection to replace it, once requested.
-        
-        This method can be used to insulate the rest of an application from a modified
-        state on a connection (such as a transaction isolation level or similar).
+        """Detach the underlying DB-API connection from its connection pool.
+
+        This Connection instance will remain useable.  When closed,
+        the DB-API connection will be literally closed and not
+        returned to its pool.  The pool will typically lazily create a
+        new connection to replace the detached connection.
+
+        This method can be used to insulate the rest of an application
+        from a modified state on a connection (such as a transaction
+        isolation level or similar).  Also see
+        [sqlalchemy.interfaces#PoolListener] for a mechanism to modify
+        connection state when connections leave and return to their
+        connection pool.
         """
-        
+
         self.__connection.detach()
-        
-    def begin(self, nested=False):
+
+    def begin(self):
+        """Begin a transaction and return a Transaction handle.
+
+        Repeated calls to ``begin`` on the same Connection will create
+        a lightweight, emulated nested transaction.  Only the
+        outermost transaction may ``commit``.  Calls to ``commit`` on
+        inner transactions are ignored.  Any transaction in the
+        hierarchy may ``rollback``, however.
+        """
+
         if self.__transaction is None:
             self.__transaction = RootTransaction(self)
-        elif nested:
-            self.__transaction = NestedTransaction(self, self.__transaction)
         else:
             return Transaction(self, self.__transaction)
         return self.__transaction
 
     def begin_nested(self):
-        return self.begin(nested=True)
-    
+        """Begin a nested transaction and return a Transaction handle.
+
+        Nested transactions require SAVEPOINT support in the
+        underlying database.  Any transaction in the hierarchy may
+        ``commit`` and ``rollback``, however the outermost transaction
+        still controls the overall ``commit`` or ``rollback`` of the
+        transaction of a whole.
+        """
+
+        if self.__transaction is None:
+            self.__transaction = RootTransaction(self)
+        else:
+            self.__transaction = NestedTransaction(self, self.__transaction)
+        return self.__transaction
+
     def begin_twophase(self, xid=None):
+        """Begin a two-phase or XA transaction and return a Transaction handle.
+
+        xid
+          the two phase transaction id.  If not supplied, a random id
+          will be generated.
+        """
+
         if self.__transaction is not None:
-            raise exceptions.InvalidRequestError("Cannot start a two phase transaction when a transaction is already started.")
+            raise exceptions.InvalidRequestError(
+                "Cannot start a two phase transaction when a transaction "
+                "is already in progress.")
         if xid is None:
             xid = self.__engine.dialect.create_xid();
         self.__transaction = TwoPhaseTransaction(self, xid)
         return self.__transaction
-        
+
     def recover_twophase(self):
         return self.__engine.dialect.do_recover_twophase(self)
-    
+
     def rollback_prepared(self, xid, recover=False):
         self.__engine.dialect.do_rollback_twophase(self, xid, recover=recover)
-    
+
     def commit_prepared(self, xid, recover=False):
         self.__engine.dialect.do_commit_twophase(self, xid, recover=recover)
 
     def in_transaction(self):
+        """Return True if a transaction is in progress."""
+
         return self.__transaction is not None
 
     def _begin_impl(self):
@@ -636,26 +719,26 @@ class Connection(Connectable):
         if self.__connection.is_valid:
             self.__engine.dialect.do_savepoint(self, name)
             return name
-    
+
     def _rollback_to_savepoint_impl(self, name, context):
         if self.__connection.is_valid:
             self.__engine.dialect.do_rollback_to_savepoint(self, name)
         self.__transaction = context
-    
+
     def _release_savepoint_impl(self, name, context):
         if self.__connection.is_valid:
             self.__engine.dialect.do_release_savepoint(self, name)
         self.__transaction = context
-    
+
     def _begin_twophase_impl(self, xid):
         if self.__connection.is_valid:
             self.__engine.dialect.do_begin_twophase(self, xid)
-    
+
     def _prepare_twophase_impl(self, xid):
         if self.__connection.is_valid:
             assert isinstance(self.__transaction, TwoPhaseTransaction)
             self.__engine.dialect.do_prepare_twophase(self, xid)
-    
+
     def _rollback_twophase_impl(self, xid, is_prepared):
         if self.__connection.is_valid:
             assert isinstance(self.__transaction, TwoPhaseTransaction)
@@ -669,17 +752,26 @@ class Connection(Connectable):
         self.__transaction = None
 
     def _autocommit(self, context):
-        """When no Transaction is present, this is called after executions to provide "autocommit" behavior."""
-        # TODO: have the dialect determine if autocommit can be set on the connection directly without this
-        # extra step
+        """Possibly issue a commit.
+
+        When no Transaction is present, this is called after statement
+        execution to provide "autocommit" behavior.  Dialects may
+        inspect the statement to determine if a commit is actually
+        required.
+        """
+
+        # TODO: have the dialect determine if autocommit can be set on
+        # the connection directly without this extra step
         if not self.in_transaction() and context.should_autocommit():
             self._commit_impl()
 
     def _autorollback(self):
         if not self.in_transaction():
             self._rollback_impl()
-    
+
     def close(self):
+        """Close this Connection."""
+
         try:
             c = self.__connection
         except AttributeError:
@@ -690,12 +782,16 @@ class Connection(Connectable):
         del self.__connection
 
     def scalar(self, object, *multiparams, **params):
+        """Executes and returns the first column of the first row."""
+
         return self.execute(object, *multiparams, **params).scalar()
 
     def statement_compiler(self, statement, parameters, **kwargs):
         return self.dialect.statement_compiler(self.dialect, statement, parameters, bind=self, **kwargs)
 
     def execute(self, object, *multiparams, **params):
+        """Executes and returns a ResultProxy."""
+
         for c in type(object).__mro__:
             if c in Connection.executors:
                 return Connection.executors[c](self, object, multiparams, params)
@@ -722,7 +818,7 @@ class Connection(Connectable):
 
     def _execute_function(self, func, multiparams, params):
         return self._execute_clauseelement(func.select(), multiparams, params)
-        
+
     def _execute_clauseelement(self, elem, multiparams=None, params=None):
         executemany = multiparams is not None and len(multiparams) > 0
         if executemany:
@@ -738,15 +834,15 @@ class Connection(Connectable):
 
         params = self.__distill_params(multiparams, params)
         context = self.__create_execution_context(compiled=compiled, parameters=params)
-        
+
         context.pre_execution()
         self.__execute_raw(context)
         context.post_execution()
         return context.result()
-            
+
     def __create_execution_context(self, **kwargs):
         return self.__engine.dialect.create_execution_context(connection=self, **kwargs)
-        
+
     def __execute_raw(self, context):
         if logging.is_info_enabled(self.__engine.logger):
             self.__engine.logger.info(context.statement)
@@ -756,7 +852,7 @@ class Connection(Connectable):
         else:
             self.__execute(context)
         self._autocommit(context)
-        
+
     def __execute(self, context):
         if context.parameters is None:
             if context.dialect.positional:
@@ -834,10 +930,11 @@ class Transaction(object):
 
     def close(self):
         """close this transaction.
-        
-        If this transaction is the base transaction in a begin/commit nesting, 
-        the transaction will rollback().  Otherwise, the method returns.
-        
+
+        If this transaction is the base transaction in a begin/commit
+        nesting, the transaction will rollback().  Otherwise, the
+        method returns.
+
         This is used to cancel a Transaction without affecting the scope of
         an enclosign transaction.
         """
@@ -845,13 +942,13 @@ class Transaction(object):
             return
         if self._parent is self:
             self.rollback()
-        
+
     def rollback(self):
         if not self._parent._is_active:
             return
         self._is_active = False
         self._do_rollback()
-    
+
     def _do_rollback(self):
         self._parent.rollback()
 
@@ -860,7 +957,7 @@ class Transaction(object):
             raise exceptions.InvalidRequestError("This transaction is inactive")
         self._is_active = False
         self._do_commit()
-    
+
     def _do_commit(self):
         pass
 
@@ -1084,7 +1181,7 @@ class Engine(Connectable):
         return self.run_callable(lambda c: self.dialect.has_table(c, table_name, schema=schema))
 
     def raw_connection(self):
-        """Return a DBAPI connection."""
+        """Return a DB-API connection."""
 
         return self.pool.connect()
 
@@ -1094,7 +1191,7 @@ class Engine(Connectable):
         self.logger.info(msg)
 
 class ResultProxy(object):
-    """Wraps a DBAPI cursor object to provide easier access to row columns.
+    """Wraps a DB-API cursor object to provide easier access to row columns.
 
     Individual columns may be accessed by their integer position,
     case-insensitive column name, or by ``schema.Column``
@@ -1119,7 +1216,7 @@ class ResultProxy(object):
         def process(value):
             raise exceptions.InvalidRequestError("Ambiguous column name '%s' in result set! try 'use_labels' option on select statement." % colname)
         return process
-            
+
     def __init__(self, context):
         """ResultProxy objects are constructed via the execute() method on SQLEngine."""
         self.context = context
@@ -1134,9 +1231,9 @@ class ResultProxy(object):
         else:
             self._rowcount = context.get_rowcount()
             self.close()
-            
+
     connection = property(lambda self:self.context.root_connection)
-    
+
     def _get_rowcount(self):
         if self._rowcount is not None:
             return self._rowcount
@@ -1145,7 +1242,7 @@ class ResultProxy(object):
     rowcount = property(_get_rowcount)
     lastrowid = property(lambda s:s.cursor.lastrowid)
     out_parameters = property(lambda s:s.context.out_parameters)
-    
+
     def _init_metadata(self):
         if hasattr(self, '_ResultProxy__props'):
             return
@@ -1201,13 +1298,13 @@ class ResultProxy(object):
 
             return rec
         return util.PopulateDict(lookup_key)
-        
+
     def close(self):
-        """Close this ResultProxy, and the underlying DBAPI cursor corresponding to the execution.
+        """Close this ResultProxy, and the underlying DB-API cursor corresponding to the execution.
 
         If this ResultProxy was generated from an implicit execution,
         the underlying Connection will also be closed (returns the
-        underlying DBAPI connection to the connection pool.)
+        underlying DB-API connection to the connection pool.)
 
         This method is also called automatically when all result rows
         are exhausted.
@@ -1217,9 +1314,9 @@ class ResultProxy(object):
             self.cursor.close()
             if self.connection.should_close_with_result:
                 self.connection.close()
-    
+
     keys = property(lambda s:s.__keys)
-    
+
     def _has_key(self, row, key):
         try:
             self._key_cache[key]
@@ -1267,7 +1364,6 @@ class ResultProxy(object):
 
         return self.context.lastrow_has_defaults()
 
-        
     def supports_sane_rowcount(self):
         """Return ``supports_sane_rowcount()`` from the underlying ExecutionContext.
 
@@ -1282,7 +1378,7 @@ class ResultProxy(object):
             return rec[1](row[rec[2]])
         else:
             return row[rec[2]]
-    
+
     def _fetchone_impl(self):
         return self.cursor.fetchone()
     def _fetchmany_impl(self, size=None):
@@ -1292,16 +1388,16 @@ class ResultProxy(object):
 
     def _row_processor(self):
         return RowProxy
-        
+
     def fetchall(self):
-        """Fetch all rows, just like DBAPI ``cursor.fetchall()``."""
+        """Fetch all rows, just like DB-API ``cursor.fetchall()``."""
 
         l = [self._process_row(self, row) for row in self._fetchall_impl()]
         self.close()
         return l
 
     def fetchmany(self, size=None):
-        """Fetch many rows, just like DBAPI ``cursor.fetchmany(size=cursor.arraysize)``."""
+        """Fetch many rows, just like DB-API ``cursor.fetchmany(size=cursor.arraysize)``."""
 
         l = [self._process_row(self, row) for row in self._fetchmany_impl(size)]
         if len(l) == 0:
@@ -1309,7 +1405,7 @@ class ResultProxy(object):
         return l
 
     def fetchone(self):
-        """Fetch one row, just like DBAPI ``cursor.fetchone()``."""
+        """Fetch one row, just like DB-API ``cursor.fetchone()``."""
         row = self._fetchone_impl()
         if row is not None:
             return self._process_row(self, row)
@@ -1329,20 +1425,23 @@ class ResultProxy(object):
             self.close()
 
 class BufferedRowResultProxy(ResultProxy):
-    """``ResultProxy`` that buffers the contents of a selection of rows before 
-    ``fetchone()`` is called.  This is to allow the results of 
-    ``cursor.description`` to be available immediately, when interfacing
-    with a DBAPI that requires rows to be consumed before this information is
-    available (currently psycopg2, when used with server-side cursors).
-    
-    The pre-fetching behavior fetches only one row initially, and then grows
-    its buffer size by a fixed amount with each successive need for additional 
-    rows up to a size of 100.
+    """A ResultProxy with row buffering behavior.
+
+    ``ResultProxy`` that buffers the contents of a selection of rows
+    before ``fetchone()`` is called.  This is to allow the results of
+    ``cursor.description`` to be available immediately, when
+    interfacing with a DB-API that requires rows to be consumed before
+    this information is available (currently psycopg2, when used with
+    server-side cursors).
+
+    The pre-fetching behavior fetches only one row initially, and then
+    grows its buffer size by a fixed amount with each successive need
+    for additional rows up to a size of 100.
     """
     def _init_metadata(self):
         self.__buffer_rows()
         super(BufferedRowResultProxy, self)._init_metadata()
-    
+
     # this is a "growth chart" for the buffering of rows.
     # each successive __buffer_rows call will use the next
     # value in the list for the buffer size until the max
@@ -1354,13 +1453,13 @@ class BufferedRowResultProxy(ResultProxy):
         20 : 50,
         50 : 100
     }
-    
+
     def __buffer_rows(self):
         size = getattr(self, '_bufsize', 1)
         self.__rowbuffer = self.cursor.fetchmany(size)
         #self.context.engine.logger.debug("Buffered %d rows" % size)
         self._bufsize = self.size_growth.get(size, size)
-    
+
     def _fetchone_impl(self):
         if self.closed:
             return None
@@ -1378,19 +1477,22 @@ class BufferedRowResultProxy(ResultProxy):
                 break
             result.append(row)
         return result
-        
+
     def _fetchall_impl(self):
         return self.__rowbuffer + list(self.cursor.fetchall())
 
 class BufferedColumnResultProxy(ResultProxy):
-    """``ResultProxy`` that loads all columns into memory each time fetchone() is
-    called.  If fetchmany() or fetchall() are called, the full grid of results
-    is fetched.  This is to operate with databases where result rows contain "live"
-    results that fall out of scope unless explicitly fetched.  Currently this includes
-    just cx_Oracle LOB objects, but this behavior is known to exist in other DBAPIs as 
-    well (Pygresql, currently unsupported).
-
+    """A ResultProxy with column buffering behavior.
+
+    ``ResultProxy`` that loads all columns into memory each time
+    fetchone() is called.  If fetchmany() or fetchall() are called,
+    the full grid of results is fetched.  This is to operate with
+    databases where result rows contain "live" results that fall out
+    of scope unless explicitly fetched.  Currently this includes just
+    cx_Oracle LOB objects, but this behavior is known to exist in
+    other DB-APIs as well (Pygresql, currently unsupported).
     """
+
     def _get_col(self, row, key):
         rec = self._key_cache[key]
         return row[rec[2]]
@@ -1443,7 +1545,7 @@ class RowProxy(object):
 
     def __contains__(self, key):
         return self.__parent._has_key(self.__row, key)
-        
+
     def __iter__(self):
         for i in range(0, len(self.__row)):
             yield self.__parent._get_col(self.__row, i)
@@ -1531,7 +1633,7 @@ class DefaultRunner(schema.SchemaVisitor):
         self.context = context
         self.connection = self.context._connection._branch()
     dialect = property(lambda self:self.context.dialect)
-    
+
     def get_column_default(self, column):
         if column.default is not None:
             return self.traverse_single(column.default)
index 17986286d011bfea104e1afbd513556506308972..ec8d8d5a7effe5d5620c318e5f1d5120e4e7aa0d 100644 (file)
@@ -4,17 +4,20 @@
 # This module is part of SQLAlchemy and is released under
 # the MIT License: http://www.opensource.org/licenses/mit-license.php
 
-"""Provide default implementations of per-dialect sqlalchemy.engine classes"""
+"""Default implementations of per-dialect sqlalchemy.engine classes."""
+
 
 from sqlalchemy import schema, exceptions, util
 import re, random
 from sqlalchemy.engine import base
 from sqlalchemy.sql import compiler, expression
 
+
 AUTOCOMMIT_REGEXP = re.compile(r'\s*(?:UPDATE|INSERT|CREATE|DELETE|DROP|ALTER)',
                                re.I | re.UNICODE)
 SELECT_REGEXP = re.compile(r'\s*SELECT', re.I | re.UNICODE)
 
+
 class DefaultDialect(base.Dialect):
     """Default implementation of Dialect"""
 
@@ -34,7 +37,7 @@ class DefaultDialect(base.Dialect):
         self.identifier_preparer = self.preparer(self)
     
     def dbapi_type_map(self):
-        # most DBAPIs have problems with this (such as, psycocpg2 types 
+        # most DB-APIs have problems with this (such as, psycocpg2 types 
         # are unhashable).  So far Oracle can return it.
         
         return {}
@@ -53,14 +56,12 @@ class DefaultDialect(base.Dialect):
             typeobj = typeobj()
         return typeobj
 
-
     def supports_unicode_statements(self):
-        """indicate whether the DBAPI can receive SQL statements as Python unicode strings"""
+        """True if DB-API can receive SQL statements as Python Unicode."""
         return False
 
     def max_identifier_length(self):
-        # TODO: probably raise this and fill out
-        # db modules better
+        # TODO: probably raise this and fill out db modules better
         return 9999
 
     def supports_alter(self):
@@ -84,7 +85,6 @@ class DefaultDialect(base.Dialect):
         autocommit on/off, etc.
         """
 
-        #print "ENGINE ROLLBACK ON ", connection.connection
         connection.rollback()
 
     def do_commit(self, connection):
@@ -92,14 +92,13 @@ class DefaultDialect(base.Dialect):
         autocommit on/off, etc.
         """
 
-        #print "ENGINE COMMIT ON ", connection.connection
         connection.commit()
     
     def create_xid(self):
-        """create a two-phase transaction ID.
+        """Create a random two-phase transaction ID.
         
-        this id will be passed to do_begin_twophase(), do_rollback_twophase(),
-        do_commit_twophase().  its format is unspecified."""
+        This id will be passed to do_begin_twophase(), do_rollback_twophase(),
+        do_commit_twophase().  Its format is unspecified."""
         
         return "_sa_%032x" % random.randint(0,2**128)
         
@@ -118,7 +117,6 @@ class DefaultDialect(base.Dialect):
     def do_execute(self, cursor, statement, parameters, **kwargs):
         cursor.execute(statement, parameters)
 
-
     def is_disconnect(self, e):
         return False
         
@@ -128,7 +126,6 @@ class DefaultDialect(base.Dialect):
 
     paramstyle = property(lambda s:s._paramstyle, _set_paramstyle)
 
-
     def _figure_paramstyle(self, paramstyle=None, default='named'):
         if paramstyle is not None:
             self._paramstyle = paramstyle
@@ -156,6 +153,7 @@ class DefaultDialect(base.Dialect):
         return self._ischema
     ischema = property(_get_ischema, doc="""returns an ISchema object for this engine, which allows access to information_schema tables (if supported)""")
 
+
 class DefaultExecutionContext(base.ExecutionContext):
     def __init__(self, dialect, connection, compiled=None, statement=None, parameters=None):
         self.dialect = dialect
@@ -218,9 +216,9 @@ class DefaultExecutionContext(base.ExecutionContext):
 
     def __convert_compiled_params(self, parameters):
         encode = not self.dialect.supports_unicode_statements()
-        # the bind params are a CompiledParams object.  but all the DBAPI's hate
-        # that object (or similar).  so convert it to a clean
-        # dictionary/list/tuple of dictionary/tuple of list
+        # the bind params are a CompiledParams object.  but all the
+        # DB-API's hate that object (or similar).  so convert it to a
+        # clean dictionary/list/tuple of dictionary/tuple of list
         if parameters is not None:
             if self.executemany:
                 processors = parameters[0].get_processors()
@@ -295,7 +293,7 @@ class DefaultExecutionContext(base.ExecutionContext):
         
     def set_input_sizes(self):
         """Given a cursor and ClauseParameters, call the appropriate
-        style of ``setinputsizes()`` on the cursor, using DBAPI types
+        style of ``setinputsizes()`` on the cursor, using DB-API types
         from the bind parameter's ``TypeEngine`` objects.
         """
 
index 168a9c4abcbe5477d0324bb4b6ab59481f763719..a0a6445fd05c51bef50e2ecfd1720399f0b1ee66 100644 (file)
@@ -1,4 +1,4 @@
-"""Define different strategies for creating new instances of sql.Engine.
+"""Strategies for creating new instances of Engine types.
 
 By default there are two, one which is the "thread-local" strategy,
 one which is the "plain" strategy.
@@ -15,9 +15,10 @@ from sqlalchemy import pool as poollib
 strategies = {}
 
 class EngineStrategy(object):
-    """Define a function that receives input arguments and produces an
-    instance of sql.Engine, typically an instance
-    sqlalchemy.engine.base.Engine or a subclass.
+    """An adaptor that processes input arguements and produces an Engine.
+
+    Provides a ``create`` method that receives input arguments and
+    produces an instance of base.Engine or a subclass.
     """
 
     def __init__(self, name):
@@ -30,11 +31,13 @@ class EngineStrategy(object):
         strategies[self.name] = self
 
     def create(self, *args, **kwargs):
-        """Given arguments, returns a new sql.Engine instance."""
+        """Given arguments, returns a new Engine instance."""
 
         raise NotImplementedError()
 
 class DefaultEngineStrategy(EngineStrategy):
+    """Base class for built-in stratgies."""
+
     def create(self, name_or_url, **kwargs):
         # create url.URL object
         u = url.make_url(name_or_url)
@@ -54,9 +57,9 @@ class DefaultEngineStrategy(EngineStrategy):
                 if k in kwargs:
                     dbapi_args[k] = kwargs.pop(k)
             dbapi = dialect_cls.dbapi(**dbapi_args)
-        
+
         dialect_args['dbapi'] = dbapi
-        
+
         # create dialect
         dialect = dialect_cls(**dialect_args)
 
@@ -78,9 +81,13 @@ class DefaultEngineStrategy(EngineStrategy):
                          getattr(dialect_cls, 'poolclass', poollib.QueuePool))
             pool_args = {}
 
-            # consume pool arguments from kwargs, translating a few of the arguments
+            # consume pool arguments from kwargs, translating a few of
+            # the arguments
+            translate = {'echo': 'echo_pool',
+                         'timeout': 'pool_timeout',
+                         'recycle': 'pool_recycle'}
             for k in util.get_cls_kwargs(poolclass):
-                tk = {'echo':'echo_pool', 'timeout':'pool_timeout', 'recycle':'pool_recycle'}.get(k, k)
+                tk = translate.get(k, k)
                 if tk in kwargs:
                     pool_args[k] = kwargs.pop(tk)
             pool_args['use_threadlocal'] = self.pool_threadlocal()
@@ -100,8 +107,14 @@ class DefaultEngineStrategy(EngineStrategy):
 
         # all kwargs should be consumed
         if kwargs:
-            raise TypeError("Invalid argument(s) %s sent to create_engine(), using configuration %s/%s/%s.  Please check that the keyword arguments are appropriate for this combination of components." % (','.join(["'%s'" % k for k in kwargs]), dialect.__class__.__name__, pool.__class__.__name__, engineclass.__name__))
-
+            raise TypeError(
+                "Invalid argument(s) %s sent to create_engine(), "
+                "using configuration %s/%s/%s.  Please check that the "
+                "keyword arguments are appropriate for this combination "
+                "of components." % (','.join(["'%s'" % k for k in kwargs]),
+                                    dialect.__class__.__name__,
+                                    pool.__class__.__name__,
+                                    engineclass.__name__))
         return engineclass(pool, dialect, u, **engine_args)
 
     def pool_threadlocal(self):
@@ -111,6 +124,8 @@ class DefaultEngineStrategy(EngineStrategy):
         raise NotImplementedError()
 
 class PlainEngineStrategy(DefaultEngineStrategy):
+    """Strategy for configuring a regular Engine."""
+
     def __init__(self):
         DefaultEngineStrategy.__init__(self, 'plain')
 
@@ -123,6 +138,8 @@ class PlainEngineStrategy(DefaultEngineStrategy):
 PlainEngineStrategy()
 
 class ThreadLocalEngineStrategy(DefaultEngineStrategy):
+    """Strategy for configuring an Engine with thredlocal behavior."""
+
     def __init__(self):
         DefaultEngineStrategy.__init__(self, 'threadlocal')
 
@@ -136,11 +153,15 @@ ThreadLocalEngineStrategy()
 
 
 class MockEngineStrategy(EngineStrategy):
-    """Produces a single Connection object which dispatches statement executions
-    to a passed-in function"""
+    """Strategy for configuring an Engine-like object with mocked execution.
+
+    Produces a single mock Connectable object which dispatches
+    statement execution to a passed-in function.
+    """
+
     def __init__(self):
         EngineStrategy.__init__(self, 'mock')
-        
+
     def create(self, name_or_url, executor, **kwargs):
         # create url.URL object
         u = url.make_url(name_or_url)
@@ -165,12 +186,13 @@ class MockEngineStrategy(EngineStrategy):
 
         engine = property(lambda s: s)
         dialect = property(lambda s:s._dialect)
-        
+
         def contextual_connect(self, **kwargs):
             return self
 
         def compiler(self, statement, parameters, **kwargs):
-            return self._dialect.compiler(statement, parameters, engine=self, **kwargs)
+            return self._dialect.compiler(
+                statement, parameters, engine=self, **kwargs)
 
         def create(self, entity, **kwargs):
             kwargs['checkfirst'] = False
index 982be3f0529f884498dadd51f797797f0bb82a7a..e9843ea2e318aeb377b46003be2c7e4c71fdfada 100644 (file)
@@ -1,11 +1,10 @@
 from sqlalchemy import util
 from sqlalchemy.engine import base
 
-"""Provide a thread-local transactional wrapper around the root Engine class.
+"""Provides a thread-local transactional wrapper around the root Engine class.
 
-Multiple calls to engine.connect() will return the same connection for
-the same thread. also provides begin/commit methods on the engine
-itself which correspond to a thread-local transaction.
+Provides begin/commit methods on the engine itself which correspond to
+a thread-local transaction.
 """
 
 class TLSession(object):
@@ -32,10 +31,10 @@ class TLSession(object):
         if self.__tcount == 1:
             self.__trans._trans.rollback()
             self.reset()
-            
+
     def in_transaction(self):
         return self.__tcount > 0
-    
+
     def prepare(self):
         if self.__tcount == 1:
             try:
@@ -44,9 +43,11 @@ class TLSession(object):
                 self.reset()
 
     def begin_twophase(self, xid=None):
-        raise NotImplementedError("Two phase transactions not yet implemented for 'threadlocal' strategy")
-    
-    def _dont_begin_twophase(self, xid=None):    
+        raise NotImplementedError(
+            "Two phase transactions not yet implemented for 'threadlocal' "
+            "strategy")
+
+    def _dont_begin_twophase(self, xid=None):
         if self.__tcount == 0:
             self.__transaction = self.get_connection()
             self.__trans = self.__transaction._begin_twophase(xid=xid)
@@ -79,9 +80,11 @@ class TLSession(object):
     def is_begun(self):
         return self.__tcount > 0
 
+
 class TLConnection(base.Connection):
     def __init__(self, session, close_with_result):
-        base.Connection.__init__(self, session.engine, close_with_result=close_with_result)
+        base.Connection.__init__(self, session.engine,
+                                 close_with_result=close_with_result)
         self.__session = session
         self.__opencount = 1
 
@@ -92,11 +95,13 @@ class TLConnection(base.Connection):
         return self
 
     def _begin(self, **kwargs):
-        return TLTransaction(super(TLConnection, self).begin(**kwargs), self.__session)
-    
+        return TLTransaction(
+            super(TLConnection, self).begin(**kwargs), self.__session)
+
     def _begin_twophase(self, xid=None):
-        return TLTransaction(super(TLConnection, self).begin_twophase(xid=xid), self.__session)
-        
+        return TLTransaction(
+            super(TLConnection, self).begin_twophase(xid=xid), self.__session)
+
     def in_transaction(self):
         return self.session.in_transaction()
 
@@ -116,6 +121,7 @@ class TLConnection(base.Connection):
         self.__opencount = 0
         base.Connection.close(self)
 
+
 class TLTransaction(base.Transaction):
     def __init__(self, trans, session):
         self._trans = trans
@@ -129,7 +135,7 @@ class TLTransaction(base.Transaction):
 
     def prepare(self):
         self._session.prepare()
-        
+
     def commit(self):
         self._session.commit()
 
@@ -143,22 +149,19 @@ class TLTransaction(base.Transaction):
 class TLEngine(base.Engine):
     """An Engine that includes support for thread-local managed transactions.
 
-    This engine is better suited to be used with threadlocal Pool
-    object.
+    The TLEngine relies upon its Pool having "threadlocal" behavior,
+    so that once a connection is checked out for the current thread,
+    you get that same connection repeatedly.
     """
 
     def __init__(self, *args, **kwargs):
-        """The TLEngine relies upon the Pool having
-        "threadlocal" behavior, so that once a connection is checked out
-        for the current thread, you get that same connection
-        repeatedly.
-        """
+        """Construct a new TLEngine."""
 
         super(TLEngine, self).__init__(*args, **kwargs)
         self.context = util.ThreadLocal()
 
     def raw_connection(self):
-        """Return a DBAPI connection."""
+        """Return a DB-API connection."""
 
         return self.pool.connect()
 
@@ -166,7 +169,7 @@ class TLEngine(base.Engine):
         """Return a Connection that is not thread-locally scoped.
 
         This is the equivalent to calling ``connect()`` on a
-        ComposedSQLEngine.
+        base.Engine.
         """
 
         return base.Connection(self, self.pool.unique_connection())
@@ -176,7 +179,7 @@ class TLEngine(base.Engine):
             self.context.session = TLSession(self)
         return self.context.session
 
-    session = property(_session, doc="returns the current thread's TLSession")
+    session = property(_session, doc="Returns the current thread's TLSession")
 
     def contextual_connect(self, **kwargs):
         """Return a TLConnection which is thread-locally scoped."""
@@ -192,3 +195,5 @@ class TLEngine(base.Engine):
     def rollback(self):
         self.session.rollback()
 
+    def __repr__(self):
+        return 'TLEngine(%s)' % str(self.url)
index 31546bae8f4308980df2d4667b1519a214991af2..1f6f9eff4cd840d0661da0061218eef800e33d57 100644 (file)
@@ -1,4 +1,4 @@
-"""Provide the URL object as well as the make_url parsing function."""
+"""Provides URL facilities for specifying database connections."""
 
 import re, cgi, sys, urllib
 from sqlalchemy import exceptions
@@ -7,15 +7,16 @@ from sqlalchemy import exceptions
 class URL(object):
     """Represent the components of a URL used to connect to a database.
 
-    This object is suitable to be passed directly to a ``create_engine()``
-    call.  The fields of the URL are parsed from a string by the
-    ``module-level make_url()`` function.  the string format of the URL is
-    an RFC-1738-style string.
+    This object is suitable to be passed directly to a
+    ``create_engine()`` call.  The fields of the URL are parsed from a
+    string by the ``module-level make_url()`` function.  the string
+    format of the URL is an RFC-1738-style string.
 
     Attributes on URL include:
 
     drivername
-      The name of the database backend.  this name will correspond to a module in sqlalchemy/databases
+      the name of the database backend.  This name will correspond to
+      a module in sqlalchemy/databases or a third party plug-in.
 
     username
       The user name for the connection.
@@ -33,7 +34,8 @@ class URL(object):
       The database.
 
     query
-      A dictionary containing key/value pairs representing the URL's query string.
+      A dictionary containing key/value pairs representing the URL's
+      query string.
     """
 
     def __init__(self, drivername, username=None, password=None, host=None, port=None, database=None, query=None):
@@ -100,7 +102,7 @@ class URL(object):
         raise ImportError('unknown database %r' % self.drivername) 
   
     def translate_connect_args(self, names):
-        """Translate this URL's attributes into a dictionary of connection arguments.
+        """Translate attributes into a dictionary of connection arguments.
 
         Given a list of argument names corresponding to the URL
         attributes (`host`, `database`, `username`, `password`,
@@ -121,7 +123,7 @@ class URL(object):
 def make_url(name_or_url):
     """Given a string or unicode instance, produce a new URL instance.
 
-    The given string is parsed according to the rfc1738 spec.  If an
+    The given string is parsed according to the RFC 1738 spec.  If an
     existing URL object is passed, just returns the object.
     """