]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
marathon doc updating session including a rewrite of unicode paragraphs
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 5 Dec 2011 04:08:35 +0000 (23:08 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 5 Dec 2011 04:08:35 +0000 (23:08 -0500)
17 files changed:
doc/build/core/engines.rst
doc/build/core/pooling.rst
doc/build/core/schema.rst
doc/build/core/types.rst
doc/build/orm/collections.rst
doc/build/orm/loading.rst
lib/sqlalchemy/dialects/drizzle/mysqldb.py
lib/sqlalchemy/dialects/mysql/mysqldb.py
lib/sqlalchemy/dialects/mysql/oursql.py
lib/sqlalchemy/dialects/oracle/cx_oracle.py
lib/sqlalchemy/dialects/sqlite/pysqlite.py
lib/sqlalchemy/engine/__init__.py
lib/sqlalchemy/events.py
lib/sqlalchemy/exc.py
lib/sqlalchemy/orm/__init__.py
lib/sqlalchemy/orm/collections.py
lib/sqlalchemy/types.py

index 353571526cdb6cf9ec8d77d66b33a720018df7cc..bfcf92bad6fd79330dbe4b9c52928e86cc3df9c1 100644 (file)
@@ -234,6 +234,8 @@ application, rather than creating a new one for each connection.
 .. autoclass:: sqlalchemy.engine.url.URL
     :members:
 
+.. _custom_dbapi_args:
+
 Custom DBAPI connect() arguments
 =================================
 
index 000311a7756da0f043f6df736c6cece67ac9b911..2906a6fea3650a090d85ade3402319c27bacf749 100644 (file)
@@ -5,10 +5,13 @@ Connection Pooling
 
 .. module:: sqlalchemy.pool
 
-The establishment of a
-database connection is typically a somewhat expensive operation, and
-applications need a way to get at database connections repeatedly
-with minimal overhead.  Particularly for
+A connection pool is a standard technique used to maintain
+long running connections in memory for efficient re-use, 
+as well as to provide
+management for the total number of connections an application
+might use simultaneously.
+
+Particularly for
 server-side web applications, a connection pool is the standard way to
 maintain a "pool" of active database connections in memory which are
 reused across requests.
@@ -21,10 +24,10 @@ plain DBAPI approach.
 Connection Pool Configuration
 -----------------------------
 
-The :class:`~sqlalchemy.engine.Engine` returned by the
+The :class:`~.engine.base.Engine` returned by the
 :func:`~sqlalchemy.create_engine` function in most cases has a :class:`.QueuePool`
 integrated, pre-configured with reasonable pooling defaults.  If
-you're reading this section to simply enable pooling- congratulations!
+you're reading this section only to learn how to enable pooling - congratulations!
 You're already done.
 
 The most common :class:`.QueuePool` tuning parameters can be passed
@@ -91,9 +94,9 @@ the same name::
     engine = create_engine('postgresql+psycopg2://', creator=getconn)
 
 For most "initialize on connection" routines, it's more convenient
-to use a :class:`.PoolListener`, so that the usual URL argument to
+to use the :class:`.PoolEvents` event hooks, so that the usual URL argument to
 :func:`.create_engine` is still usable.  ``creator`` is there as
-a total last resort for when a DBAPI has some form of ``connect``
+a last resort for when a DBAPI has some form of ``connect``
 that is not at all supported by SQLAlchemy.
 
 Constructing a Pool
@@ -141,12 +144,12 @@ engines by passing it to the ``pool`` argument of :func:`.create_engine`::
 
     e = create_engine('postgresql://', pool=mypool)
 
-Pool Event Listeners
---------------------
+Pool Events
+-----------
 
 Connection pools support an event interface that allows hooks to execute
 upon first connect, upon each new connection, and upon checkout and 
-checkin of connections.   See :class:`.PoolListener` for details.
+checkin of connections.   See :class:`.PoolEvents` for details.
 
 Dealing with Disconnects
 ------------------------
@@ -239,8 +242,9 @@ can detect an invalid connection before it's used::
             raise exc.DisconnectionError()
         cursor.close()
 
-Above, the :class:`.Pool` object specifically catches :class:`.DisconnectionError` and attempts
-to create a new DBAPI connection, up to three times before giving up.   This recipe will ensure 
+Above, the :class:`.Pool` object specifically catches :class:`~sqlalchemy.exc.DisconnectionError` and attempts
+to create a new DBAPI connection, up to three times, before giving up and then raising
+:class:`~sqlalchemy.exc.InvalidRequestError`, failing the connection.   This recipe will ensure 
 that a new :class:`.Connection` will succeed even if connections
 in the pool have gone stale, provided that the database server is actually running.   The expense
 is that of an additional execution performed per checkout.   When using the ORM :class:`.Session`,
index bc9ab91bacac0eb49dd48f65f6f08eb005830925..708a9e9091dec8e73e27178aa9fd7f5f6b0c5413 100644 (file)
@@ -412,8 +412,8 @@ Reflecting Database Objects
 
 A :class:`~sqlalchemy.schema.Table` object can be instructed to load
 information about itself from the corresponding database schema object already
-existing within the database. This process is called *reflection*. Most simply
-you need only specify the table name, a :class:`~sqlalchemy.schema.MetaData`
+existing within the database. This process is called *reflection*. In the
+most simple case you need only specify the table name, a :class:`~sqlalchemy.schema.MetaData`
 object, and the ``autoload=True`` flag. If the
 :class:`~sqlalchemy.schema.MetaData` is not persistently bound, also add the
 ``autoload_with`` argument::
index b7b4e3488c75a0abd38f256656c6b8ec221bae33..c3fb99f0280d05e0fe289e2e0b13ee3f4e21eb05 100644 (file)
@@ -297,6 +297,8 @@ TypeDecorator Recipes
 ~~~~~~~~~~~~~~~~~~~~~
 A few key :class:`.TypeDecorator` recipes follow.
 
+.. _coerce_to_unicode:
+
 Coercing Encoded Strings to Unicode
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
index 7ca968d2e0bdfcb28d0322ea87f87dcd6b9e890b..6491332f6b48688f7d061833c1525c7fe545051c 100644 (file)
@@ -2,6 +2,7 @@
 
 .. currentmodule:: sqlalchemy.orm
 
+=======================================
 Collection Configuration and Techniques
 =======================================
 
@@ -15,32 +16,33 @@ and techniques.
 .. currentmodule:: sqlalchemy.orm
 
 Working with Large Collections
--------------------------------
+===============================
 
 The default behavior of :func:`.relationship` is to fully load
 the collection of items in, as according to the loading strategy of the
-relationship. Additionally, the Session by default only knows how to delete
+relationship. Additionally, the :class:`.Session` by default only knows how to delete
 objects which are actually present within the session. When a parent instance
-is marked for deletion and flushed, the Session loads its full list of child
+is marked for deletion and flushed, the :class:`.Session` loads its full list of child
 items in so that they may either be deleted as well, or have their foreign key
 value set to null; this is to avoid constraint violations. For large
 collections of child items, there are several strategies to bypass full
 loading of child items both at load time as well as deletion time.
 
+.. _dynamic_relationship:
+
 Dynamic Relationship Loaders
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-----------------------------
 
 A key feature to enable management of a large collection is the so-called "dynamic"
 relationship.  This is an optional form of :func:`~sqlalchemy.orm.relationship` which
 returns a :class:`~sqlalchemy.orm.query.Query` object in place of a collection
 when accessed. :func:`~sqlalchemy.orm.query.Query.filter` criterion may be
-applied as well as limits and offsets, either explicitly or via array slices:
+applied as well as limits and offsets, either explicitly or via array slices::
 
-.. sourcecode:: python+sql
+    class User(Base):
+        __tablename__ = 'user'
 
-    mapper(User, users_table, properties={
-        'posts': relationship(Post, lazy="dynamic")
-    })
+        posts = relationship(Post, lazy="dynamic")
 
     jack = session.query(User).get(id)
 
@@ -66,13 +68,14 @@ automatically each time the collection is about to emit a
 query.
 
 To place a dynamic relationship on a backref, use the :func:`~.orm.backref`
-function in conjunction with ``lazy='dynamic'``:
+function in conjunction with ``lazy='dynamic'``::
 
-.. sourcecode:: python+sql
+    class Post(Base):
+        __table__ = posts_table
 
-    mapper(Post, posts_table, properties={
-        'user': relationship(User, backref=backref('posts', lazy='dynamic'))
-    })
+        user = relationship(User, 
+                    backref=backref('posts', lazy='dynamic')
+                )
 
 Note that eager/lazy loading options cannot be used in conjunction dynamic relationships at this time.
 
@@ -81,15 +84,15 @@ Note that eager/lazy loading options cannot be used in conjunction dynamic relat
 
 
 Setting Noload
-~~~~~~~~~~~~~~~
+---------------
 
-The opposite of the dynamic relationship is simply "noload", specified using ``lazy='noload'``:
+A "noload" relationship never loads from the database, even when 
+accessed.   It is configured using ``lazy='noload'``::
 
-.. sourcecode:: python+sql
+    class MyClass(Base):
+        __tablename__ = 'some_table'
 
-    mapper(MyClass, table, properties={
-        'children': relationship(MyOtherClass, lazy='noload')
-    })
+        children = relationship(MyOtherClass, lazy='noload')
 
 Above, the ``children`` collection is fully writeable, and changes to it will
 be persisted to the database as well as locally available for reading at the
@@ -99,30 +102,26 @@ from the database, the ``children`` collection stays empty.
 .. _passive_deletes:
 
 Using Passive Deletes
-~~~~~~~~~~~~~~~~~~~~~~
+----------------------
 
 Use ``passive_deletes=True`` to disable child object loading on a DELETE
 operation, in conjunction with "ON DELETE (CASCADE|SET NULL)" on your database
 to automatically cascade deletes to child objects. Note that "ON DELETE" is
-not supported on SQLite, and requires ``InnoDB`` tables when using MySQL:
-
-.. sourcecode:: python+sql
-
-        mytable = Table('mytable', meta,
-            Column('id', Integer, primary_key=True),
-            )
+not supported on SQLite, and requires ``InnoDB`` tables when using MySQL::
 
-        myothertable = Table('myothertable', meta,
-            Column('id', Integer, primary_key=True),
-            Column('parent_id', Integer),
-            ForeignKeyConstraint(['parent_id'], ['mytable.id'], ondelete="CASCADE"),
-            )
-
-        mapper(MyOtherClass, myothertable)
+    class MyClass(Base):
+        __tablename__ = 'mytable'
+        id = Column(Integer, primary_key=True)
+        children = relationship("MyOtherClass", 
+                        cascade="all, delete-orphan", 
+                        passive_deletes=True)
 
-        mapper(MyClass, mytable, properties={
-            'children': relationship(MyOtherClass, cascade="all, delete-orphan", passive_deletes=True)
-        })
+    class MyOtherClass(Base):
+        __tablename__ = 'myothertable'
+        id = Column(Integer, primary_key=True)
+        parent_id = Column(Integer, 
+                    ForeignKey('mytable.id', ondelete='CASCADE')
+                        )
 
 When ``passive_deletes`` is applied, the ``children`` relationship will not be
 loaded into memory when an instance of ``MyClass`` is marked for deletion. The
@@ -130,21 +129,23 @@ loaded into memory when an instance of ``MyClass`` is marked for deletion. The
 ``MyOtherClass`` which are currently present in the session; however for
 instances of ``MyOtherClass`` which are not loaded, SQLAlchemy assumes that
 "ON DELETE CASCADE" rules will ensure that those rows are deleted by the
-database and that no foreign key violation will occur.
+database.
 
 .. currentmodule:: sqlalchemy.orm.collections
 .. _custom_collections:
 
 Customizing Collection Access
------------------------------
+=============================
 
 Mapping a one-to-many or many-to-many relationship results in a collection of
 values accessible through an attribute on the parent instance. By default,
 this collection is a ``list``::
 
-    mapper(Parent, properties={
-        'children' : relationship(Child)
-    })
+    class Parent(Base):
+        __tablename__ = 'parent'
+        parent_id = Column(Integer, primary_key=True)
+
+        children = relationship(Child)
 
     parent = Parent()
     parent.children.append(Child())
@@ -153,14 +154,14 @@ this collection is a ``list``::
 Collections are not limited to lists. Sets, mutable sequences and almost any
 other Python object that can act as a container can be used in place of the
 default list, by specifying the ``collection_class`` option on
-:func:`~sqlalchemy.orm.relationship`.
+:func:`~sqlalchemy.orm.relationship`::
 
-.. sourcecode:: python+sql
+    class Parent(Base):
+        __tablename__ = 'parent'
+        parent_id = Column(Integer, primary_key=True)
 
-    # use a set
-    mapper(Parent, properties={
-        'children' : relationship(Child, collection_class=set)
-    })
+        # use a set
+        children = relationship(Child, collection_class=set)
 
     parent = Parent()
     child = Child()
@@ -168,12 +169,12 @@ default list, by specifying the ``collection_class`` option on
     assert child in parent.children
 
 Dictionary Collections
-~~~~~~~~~~~~~~~~~~~~~~~
+-----------------------
 
 A little extra detail is needed when using a dictionary as a collection. 
 This because objects are always loaded from the database as lists, and a key-generation
 strategy must be available to populate the dictionary correctly.  The
-:func:`.orm.collections.attribute_mapped_collection` function is by far the most common way
+:func:`.attribute_mapped_collection` function is by far the most common way
 to achieve a simple dictionary collection.  It produces a dictionary class that will apply a particular attribute
 of the mapped class as a key.   Below we map an ``Item`` class containing
 a dictionary of ``Note`` items keyed to the ``Note.keyword`` attribute::
@@ -210,7 +211,7 @@ a dictionary of ``Note`` items keyed to the ``Note.keyword`` attribute::
     >>> item.notes.items()
     {'a': <__main__.Note object at 0x2eaaf0>}
 
-:func:`.orm.collections.attribute_mapped_collection` will ensure that 
+:func:`.attribute_mapped_collection` will ensure that 
 the ``.keyword`` attribute of each ``Note`` complies with the key in the
 dictionary.   Such as, when assigning to ``Item.notes``, the dictionary
 key we supply must match that of the actual ``Note`` object::
@@ -221,8 +222,8 @@ key we supply must match that of the actual ``Note`` object::
                 'b': Note('b', 'btext')
             }
 
-The attribute which :func:`.orm.collections.attribute_mapped_collection` uses as a key
-does not need to be mapped at all !  Using a regular Python ``@property`` allows virtually
+The attribute which :func:`.attribute_mapped_collection` uses as a key
+does not need to be mapped at all!  Using a regular Python ``@property`` allows virtually
 any detail or combination of details about the object to be used as the key, as 
 below when we establish it as a tuple of ``Note.keyword`` and the first ten letters
 of the ``Note.text`` field::
@@ -259,8 +260,8 @@ is added to the ``Item.notes`` dictionary and the key is generated for us automa
     >>> item.notes
     {('a', 'atext'): <__main__.Note object at 0x2eaaf0>}
 
-Other built-in dictionary types include :func:`.orm.collections.column_mapped_collection`,
-which is almost like ``attribute_mapped_collection`` except given the :class:`.Column`
+Other built-in dictionary types include :func:`.column_mapped_collection`,
+which is almost like :func:`.attribute_mapped_collection` except given the :class:`.Column`
 object directly::
 
     from sqlalchemy.orm.collections import column_mapped_collection
@@ -272,8 +273,8 @@ object directly::
                     collection_class=column_mapped_collection(Note.__table__.c.keyword), 
                     cascade="all, delete-orphan")
 
-as well as :func:`.orm.collections.mapped_collection` which is passed any callable function.
-Note that it's usually easier to use :func:`.orm.collections.attribute_mapped_collection` along
+as well as :func:`.mapped_collection` which is passed any callable function.
+Note that it's usually easier to use :func:`.attribute_mapped_collection` along
 with a ``@property`` as mentioned earlier::
 
     from sqlalchemy.orm.collections import mapped_collection
@@ -289,18 +290,23 @@ Dictionary mappings are often combined with the "Association Proxy" extension to
 streamlined dictionary views.  See :ref:`proxying_dictionaries` and :ref:`composite_association_proxy` 
 for examples.
 
+.. autofunction:: attribute_mapped_collection
+
+.. autofunction:: column_mapped_collection
+
+.. autofunction:: mapped_collection
 
 Custom Collection Implementations
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+==================================
 
-You can use your own types for collections as well.  In simple cases, simply 
+You can use your own types for collections as well.  In simple cases,  
 inherting from ``list`` or ``set``, adding custom behavior, is all that's needed.
 In other cases, special decorators are needed to tell SQLAlchemy more detail
 about how the collection operates.
 
-.. topic:: Do I need a custom collection implementation ?
+.. topic:: Do I need a custom collection implementation?
 
-   In most cases not at all !   The most common use cases for a "custom" collection
+   In most cases not at all!   The most common use cases for a "custom" collection
    is one that validates or marshals incoming values into a new form, such as
    a string that becomes a class instance, or one which goes a
    step beyond and represents the data internally in some fashion, presenting
@@ -332,7 +338,7 @@ operations can fire *events* which indicate some secondary operation must take
 place. Examples of a secondary operation include saving the child item in the
 parent's :class:`~sqlalchemy.orm.session.Session` (i.e. the ``save-update``
 cascade), as well as synchronizing the state of a bi-directional relationship
-(i.e. a ``backref``).
+(i.e. a :func:`.backref`).
 
 The collections package understands the basic interface of lists, sets and
 dicts and will automatically apply instrumentation to those built-in types and
@@ -388,11 +394,11 @@ automatically when present. This set-like class does not provide the expected
 decorator.
 
 Annotating Custom Collections via Decorators
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+--------------------------------------------
 
 Decorators can be used to tag the individual methods the ORM needs to manage
 collections. Use them when your class doesn't quite meet the regular interface
-for its container type, or you simply would like to use a different method to
+for its container type, or when you otherwise would like to use a different method to
 get the job done.
 
 .. sourcecode:: python+sql
@@ -439,12 +445,15 @@ interface marked for SQLAlchemy's use. Append and remove methods will be
 called with a mapped entity as the single argument, and iterator methods are
 called with no arguments and must return an iterator.
 
+.. autoclass:: collection
+    :members:
+
 .. _dictionary_collections:
 
 Custom Dictionary-Based Collections
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+-----------------------------------
 
-The :class:`sqlalchemy.orm.collections.MappedCollection` class can be used as
+The :class:`.MappedCollection` class can be used as
 a base class for your custom types or as a mix-in to quickly add ``dict``
 collection support to other classes. It uses a keying function to delegate to
 ``__setitem__`` and ``__delitem__``:
@@ -496,12 +505,15 @@ must decorate appender and remover methods, however- there are no compatible
 methods in the basic dictionary interface for SQLAlchemy to use by default.
 Iteration will go through ``itervalues()`` unless otherwise decorated.
 
+.. autoclass:: sqlalchemy.orm.collections.MappedCollection
+   :members:
+
 Instrumentation and Custom Types
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+--------------------------------
 
 Many custom types and existing library classes can be used as a entity
 collection type as-is without further ado. However, it is important to note
-that the instrumentation process _will_ modify the type, adding decorators
+that the instrumentation process will modify the type, adding decorators
 around methods automatically.
 
 The decorations are lightweight and no-op outside of relationships, but they
@@ -519,26 +531,21 @@ to restrict the decorations to just your usage in relationships. For example:
 The ORM uses this approach for built-ins, quietly substituting a trivial
 subclass when a ``list``, ``set`` or ``dict`` is used directly.
 
-The collections package provides additional decorators and support for
-authoring custom types. See the :mod:`sqlalchemy.orm.collections` package for
-more information and discussion of advanced usage and Python 2.3-compatible
-decoration options.
+Collection Internals
+=====================
 
-Collections API
-~~~~~~~~~~~~~~~
+Various internal methods.
 
-.. autofunction:: attribute_mapped_collection
-
-.. autoclass:: collection
-    :members:
+.. autofunction:: bulk_replace
 
 .. autofunction:: collection_adapter
 
-.. autofunction:: column_mapped_collection
+.. autoclass:: CollectionAdapter
 
-.. autofunction:: mapped_collection
+.. autoclass:: InstrumentedDict
 
-.. autoclass:: sqlalchemy.orm.collections.MappedCollection
-   :members:
+.. autoclass:: InstrumentedList
 
+.. autoclass:: InstrumentedSet
 
+.. autofunction:: prepare_instrumentation
index 16c17b4bdb8ac7967eb49334aa40eef5b96cc135..9ae60e8a84b9b37dd6a490d76c2a9799a28e7271 100644 (file)
@@ -146,7 +146,7 @@ place joinedloads for both:
 
     session.query(A).options(joinedload('atob'), joinedload('atob.btoc')).all()
 
-or more simply just use :func:`~sqlalchemy.orm.joinedload_all` or
+or more succinctly just use :func:`~sqlalchemy.orm.joinedload_all` or
 :func:`~sqlalchemy.orm.subqueryload_all`:
 
 .. sourcecode:: python+sql
index dcf02609e59de01ceddc53fa4be3a45543a5d4bb..01116fa93f8dc8a6e06416e7da46c35b6056b5aa 100644 (file)
@@ -13,10 +13,11 @@ Connect string format::
 
     drizzle+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>
 
-Character Sets
---------------
+Unicode
+-------
 
-Drizzle is all utf8 all the time.
+Drizzle accommodates Python ``unicode`` objects directly and 
+uses the ``utf8`` encoding in all cases.
 
 Known Issues
 -------------
index 1b0ea85cb9005b269ddc555ec89ca7eddf257804..044b9110a4cd181fcffa55da8f70f41934fba341 100644 (file)
@@ -19,35 +19,38 @@ Connect string format::
 
     mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>
 
-Character Sets
---------------
+Unicode
+-------
 
-Many MySQL server installations default to a ``latin1`` encoding for client
-connections.  All data sent through the connection will be converted into
-``latin1``, even if you have ``utf8`` or another character set on your tables
+MySQLdb will accommodate Python ``unicode`` objects if the
+``use_unicode=1`` parameter, or the ``charset`` parameter,
+is passed as a connection argument.
+
+Without this setting, many MySQL server installations default to 
+a ``latin1`` encoding for client connections, which has the effect
+of all data being converted into ``latin1``, even if you have ``utf8`` 
+or another character set configured on your tables
 and columns.  With versions 4.1 and higher, you can change the connection
 character set either through server configuration or by including the
-``charset`` parameter in the URL used for ``create_engine``.  The ``charset``
-option is passed through to MySQL-Python and has the side-effect of also
-enabling ``use_unicode`` in the driver by default.  For regular encoded
-strings, also pass ``use_unicode=0`` in the connection arguments::
+``charset`` parameter.  The ``charset``
+parameter as received by MySQL-Python also has the side-effect of 
+enabling ``use_unicode=1``::
+
+    # set client encoding to utf8; all strings come back as unicode
+    create_engine('mysql+mysqldb:///mydb?charset=utf8')
 
-  # set client encoding to utf8; all strings come back as unicode
-  create_engine('mysql+mysqldb:///mydb?charset=utf8')
+Manually configuring ``use_unicode=0`` will cause MySQL-python to 
+return encoded strings::
 
-  # set client encoding to utf8; all strings come back as utf8 str
-  create_engine('mysql+mysqldb:///mydb?charset=utf8&use_unicode=0')
+    # set client encoding to utf8; all strings come back as utf8 str
+    create_engine('mysql+mysqldb:///mydb?charset=utf8&use_unicode=0')
 
 Known Issues
 -------------
 
 MySQL-python version 1.2.2 has a serious memory leak related
 to unicode conversion, a feature which is disabled via ``use_unicode=0``.
-Using a more recent version of MySQL-python is recommended. The 
-recommended connection form with SQLAlchemy is::
-  
-    engine = create_engine('mysql://scott:tiger@localhost/test?charset=utf8&use_unicode=0', pool_recycle=3600)
-
+It is strongly advised to use the latest version of MySQL-Python.
 
 """
 
index 2678d9dc92896b76ec5d0770b7fd59586588bc4b..25273a61999c55e3c19e4655cb25f623f078523b 100644 (file)
@@ -17,8 +17,8 @@ Connect string format::
 
     mysql+oursql://<user>:<password>@<host>[:<port>]/<dbname>
 
-Character Sets
---------------
+Unicode
+-------
 
 oursql defaults to using ``utf8`` as the connection charset, but other
 encodings may be used instead. Like the MySQL-Python driver, unicode support
index 29d9e2ab0a1e15e27b486c1f99a4ab3b61f2fad6..078136f70eb270a97258aa46738a80b0c040333a 100644 (file)
@@ -50,6 +50,8 @@ Unicode
 cx_oracle 5 fully supports Python unicode objects.   SQLAlchemy will pass
 all unicode strings directly to cx_oracle, and additionally uses an output
 handler so that all string based result values are returned as unicode as well.
+Generally, the ``NLS_LANG`` environment variable determines the nature
+of the encoding to be used.
 
 Note that this behavior is disabled when Oracle 8 is detected, as it has been 
 observed that issues remain when passing Python unicodes to cx_oracle with Oracle 8.
index c8739f242d41a0e6d71c9061830be4eb9154a46f..ad8d5c6f9f1343d3747f82eb39b427fa1c2cd2fb 100644 (file)
@@ -173,15 +173,14 @@ way.
 Unicode
 -------
 
-In contrast to SQLAlchemy's active handling of date and time types for pysqlite, pysqlite's 
-default behavior regarding Unicode is that all strings are returned as Python unicode objects
-in all cases.  So even if the :class:`~sqlalchemy.types.Unicode` type is 
-*not* used, you will still always receive unicode data back from a result set.  It is 
-**strongly** recommended that you do use the :class:`~sqlalchemy.types.Unicode` type
-to represent strings, since it will raise a warning if a non-unicode Python string is 
-passed from the user application.  Mixing the usage of non-unicode objects with returned unicode objects can
-quickly create confusion, particularly when using the ORM as internal data is not 
-always represented by an actual database result string.
+The pysqlite driver only returns Python ``unicode`` objects in result sets, never
+plain strings, and accommodates ``unicode`` objects within bound parameter
+values in all cases.   Regardless of the SQLAlchemy string type in use, 
+string-based result values will by Python ``unicode`` in Python 2.  
+The :class:`.Unicode` type should still be used to indicate those columns that
+require unicode, however, so that non-``unicode`` values passed inadvertently
+will emit a warning.  Pysqlite will emit an error if a non-``unicode`` string
+is passed containing non-ASCII characters.
 
 """
 
index 0d091bb11fb08be74418f3280f03c0486d706abc..1835d8a074d558eea5a52e7108c002dfa9a97fc0 100644 (file)
@@ -137,31 +137,31 @@ def create_engine(*args, **kwargs):
 
     :ref:`connections_toplevel`
     
-    :param assert_unicode:  Deprecated.  A warning is raised in all cases when a non-Unicode
-        object is passed when SQLAlchemy would coerce into an encoding
-        (note: but **not** when the DBAPI handles unicode objects natively).
-        To suppress or raise this warning to an 
-        error, use the Python warnings filter documented at:
-        http://docs.python.org/library/warnings.html
+    :param assert_unicode:  Deprecated.  This flag
+        sets an engine-wide default value for
+        the ``assert_unicode`` flag on the 
+        :class:`.String` type - see that 
+        type for further details.
 
     :param connect_args: a dictionary of options which will be
         passed directly to the DBAPI's ``connect()`` method as
-        additional keyword arguments.
-
-    :param convert_unicode=False: if set to True, all
-        String/character based types will convert Python Unicode values to raw
-        byte values sent to the DBAPI as bind parameters, and all raw byte values to
-        Python Unicode coming out in result sets. This is an
-        engine-wide method to provide Unicode conversion across the
-        board for those DBAPIs that do not accept Python Unicode objects
-        as input.  For Unicode conversion on a column-by-column level, use
-        the ``Unicode`` column type instead, described in :ref:`types_toplevel`.  Note that
-        many DBAPIs have the ability to return Python Unicode objects in
-        result sets directly - SQLAlchemy will use these modes of operation
-        if possible and will also attempt to detect "Unicode returns" 
-        behavior by the DBAPI upon first connect by the 
-        :class:`.Engine`.  When this is detected, string values in 
-        result sets are passed through without further processing.
+        additional keyword arguments.  See the example
+        at :ref:`custom_dbapi_args`.
+
+    :param convert_unicode=False: if set to True, sets
+        the default behavior of ``convert_unicode`` on the
+        :class:`.String` type to ``True``, regardless
+        of a setting of ``False`` on an individual 
+        :class:`.String` type, thus causing all :class:`.String`
+        -based columns
+        to accommodate Python ``unicode`` objects.  This flag
+        is useful as an engine-wide setting when using a 
+        DBAPI that does not natively support Python
+        ``unicode`` objects and raises an error when
+        one is received (such as pyodbc with FreeTDS).
+        
+        See :class:`.String` for further details on 
+        what this flag indicates.
 
     :param creator: a callable which returns a DBAPI connection.
         This creation function will be passed to the underlying
@@ -184,9 +184,50 @@ def create_engine(*args, **kwargs):
         :ref:`dbengine_logging` for information on how to configure logging
         directly.
 
-    :param encoding='utf-8': the encoding to use for all Unicode
-        translations, both by engine-wide unicode conversion as well as
-        the ``Unicode`` type object.
+    :param encoding: Defaults to ``utf-8``.  This is the string 
+        encoding used by SQLAlchemy for string encode/decode 
+        operations which occur within SQLAlchemy, **outside of 
+        the DBAPI.**  Most modern DBAPIs feature some degree of 
+        direct support for Python ``unicode`` objects,
+        what you see in Python 2 as a string of the form
+        ``u'some string'``.  For those scenarios where the 
+        DBAPI is detected as not supporting a Python ``unicode``
+        object, this encoding is used to determine the 
+        source/destination encoding.  It is **not used**
+        for those cases where the DBAPI handles unicode
+        directly.
+        
+        To properly configure a system to accommodate Python
+        ``unicode`` objects, the DBAPI should be 
+        configured to handle unicode to the greatest
+        degree as is appropriate - see
+        the notes on unicode pertaining to the specific
+        target database in use at :ref:`dialect_toplevel`. 
+        
+        Areas where string encoding may need to be accommodated 
+        outside of the DBAPI include zero or more of: 
+        
+        * the values passed to bound parameters, corresponding to 
+          the :class:`.Unicode` type or the :class:`.String` type
+          when ``convert_unicode`` is ``True``;
+        * the values returned in result set columns corresponding 
+          to the :class:`.Unicode` type or the :class:`.String` 
+          type when ``convert_unicode`` is ``True``;
+        * the string SQL statement passed to the DBAPI's 
+          ``cursor.execute()`` method; 
+        * the string names of the keys in the bound parameter 
+          dictionary passed to the DBAPI's ``cursor.execute()`` 
+          as well as ``cursor.setinputsizes()`` methods;
+        * the string column names retrieved from the DBAPI's 
+          ``cursor.description`` attribute.
+          
+        When using Python 3, the DBAPI is required to support
+        *all* of the above values as Python ``unicode`` objects,
+        which in Python 3 are just known as ``str``.  In Python 2,
+        the DBAPI does not specify unicode behavior at all,
+        so SQLAlchemy must make decisions for each of the above
+        values on a per-DBAPI basis - implementations are
+        completely inconsistent in their behavior.
 
     :param execution_options: Dictionary execution options which will
         be applied to all connections.  See
index eee2a7557f4fd0cb49a7374fa33f2ae562bf9b50..adfbd196647612ba980ae2437bcd5b056ead4bf3 100644 (file)
@@ -312,7 +312,7 @@ class PoolEvents(event.Events):
           The ``_ConnectionFairy`` which manages the connection for the span of
           the current checkout.
 
-        If you raise an ``exc.DisconnectionError``, the current
+        If you raise a :class:`~sqlalchemy.exc.DisconnectionError`, the current
         connection will be disposed and a fresh connection retrieved.
         Processing of all checkout listeners will abort and restart
         using the new connection.
index d375807b2f5286220c0c6360389692378cc070fc..57ddb11ef57f14ad2d05bc47a27114d34350f502 100644 (file)
@@ -63,7 +63,10 @@ class DisconnectionError(SQLAlchemyError):
     """A disconnect is detected on a raw DB-API connection.
 
     This error is raised and consumed internally by a connection pool.  It can
-    be raised by a ``PoolListener`` so that the host pool forces a disconnect.
+    be raised by the :meth:`.PoolEvents.checkout` event 
+    so that the host pool forces a retry; the exception will be caught
+    three times in a row before the pool gives up and raises 
+    :class:`~sqlalchemy.exc.InvalidRequestError` regarding the connection attempt.
 
     """
 
index 4c6d30d324db7114fbc610dcc73d398eb424dfc4..ec4f39fdf86b735e245ad93be82eabcdbeccc1c5 100644 (file)
@@ -427,11 +427,8 @@ def relationship(argument, secondary=None, **kwargs):
       * ``dynamic`` - the attribute will return a pre-configured
         :class:`~sqlalchemy.orm.query.Query` object for all read 
         operations, onto which further filtering operations can be
-        applied before iterating the results.  The dynamic 
-        collection supports a limited set of mutation operations,
-        allowing ``append()`` and ``remove()``.  Changes to the
-        collection will not be visible until flushed 
-        to the database, where it is then refetched upon iteration.
+        applied before iterating the results.  See
+        the section :ref:`dynamic_relationship` for more details.
 
       * True - a synonym for 'select'
 
@@ -627,19 +624,12 @@ def dynamic_loader(argument, **kw):
 
         dynamic_loader(SomeClass)
         
-        # vs.
+        # is the same as
         
         relationship(SomeClass, lazy="dynamic")
 
-    A :func:`relationship` that is "dynamic" features the behavior
-    that read operations return an active :class:`.Query` object which 
-    reads from the database when accessed. Items may be appended to the
-    attribute via ``append()``, or removed via ``remove()``; changes will be
-    persisted to the database during a :meth:`Sesion.flush`. However, no other
-    Python list or collection mutation operations are available.
-
-    All arguments accepted by :func:`relationship` are
-    accepted here, other than ``lazy`` which is fixed at ``dynamic``.
+    See the section :ref:`dynamic_relationship` for more details
+    on dynamic loading.
 
     """
     kw['lazy'] = 'dynamic'
index 7ac70fe5a4fe3ba56cd2d877d12b065a1e7486a3..d605d849bc3a3362aa9a0c7b6a8a08cb6b89d396 100644 (file)
@@ -122,7 +122,7 @@ __instrumentation_mutex = util.threading.Lock()
 def column_mapped_collection(mapping_spec):
     """A dictionary-based collection type with column-based keying.
 
-    Returns a MappedCollection factory with a keying function generated
+    Returns a :class:`.MappedCollection` factory with a keying function generated
     from mapping_spec, which may be a Column or a sequence of Columns.
 
     The key value must be immutable for the lifetime of the object.  You
@@ -153,7 +153,7 @@ def column_mapped_collection(mapping_spec):
 def attribute_mapped_collection(attr_name):
     """A dictionary-based collection type with attribute-based keying.
 
-    Returns a MappedCollection factory with a keying based on the
+    Returns a :class:`.MappedCollection` factory with a keying based on the
     'attr_name' attribute of entities in the collection, where ``attr_name``
     is the string name of the attribute.
 
@@ -169,7 +169,7 @@ def attribute_mapped_collection(attr_name):
 def mapped_collection(keyfunc):
     """A dictionary-based collection type with arbitrary keying.
 
-    Returns a MappedCollection factory with a keying function generated
+    Returns a :class:`.MappedCollection` factory with a keying function generated
     from keyfunc, a callable that takes an entity and returns a key value.
 
     The key value must be immutable for the lifetime of the object.  You
@@ -201,10 +201,6 @@ class collection(object):
         @collection.removes_return()
         def popitem(self): ...
 
-    Decorators can be specified in long-hand for Python 2.3, or with
-    the class-level dict attribute '__instrumentation__'- see the source
-    for details.
-
     """
     # Bundled as a class solely for ease of use: packaging, doc strings,
     # importability.
@@ -474,7 +470,7 @@ class CollectionAdapter(object):
     to the underlying Python collection, and emits add/remove events for
     entities entering or leaving the collection.
 
-    The ORM uses an CollectionAdapter exclusively for interaction with
+    The ORM uses :class:`.CollectionAdapter` exclusively for interaction with
     entity collections.
 
     The usage of getattr()/setattr() is currently to allow injection
@@ -664,14 +660,11 @@ def bulk_replace(values, existing_adapter, new_adapter):
     instances in ``existing_adapter`` not present in ``values`` will have
     remove events fired upon them.
 
-    values
-      An iterable of collection member instances
+    :param values: An iterable of collection member instances
 
-    existing_adapter
-      A CollectionAdapter of instances to be replaced
+    :param existing_adapter: A :class:`.CollectionAdapter` of instances to be replaced
 
-    new_adapter
-      An empty CollectionAdapter to load with ``values``
+    :param new_adapter: An empty :class:`.CollectionAdapter` to load with ``values``
 
 
     """
index 136de147ee843fbcd656bfe3775ef698d94d642c..1ad1280f53a954d31d6cd7ba12453216b93aefb6 100644 (file)
@@ -962,53 +962,55 @@ class String(Concatenable, TypeEngine):
         :param length: optional, a length for the column for use in
           DDL statements.  May be safely omitted if no ``CREATE
           TABLE`` will be issued.  Certain databases may require a
-          *length* for use in DDL, and will raise an exception when
-          the ``CREATE TABLE`` DDL is issued.  Whether the value is
+          ``length`` for use in DDL, and will raise an exception when
+          the ``CREATE TABLE`` DDL is issued if a ``VARCHAR``
+          with no length is included.  Whether the value is
           interpreted as bytes or characters is database specific.
 
-        :param convert_unicode: defaults to False.  If True, the 
-          type will do what is necessary in order to accept 
-          Python Unicode objects as bind parameters, and to return
-          Python Unicode objects in result rows.   This may
-          require SQLAlchemy to explicitly coerce incoming Python 
-          unicodes into an encoding, and from an encoding 
-          back to Unicode, or it may not require any interaction
-          from SQLAlchemy at all, depending on the DBAPI in use.
-
-          When SQLAlchemy performs the encoding/decoding, 
-          the encoding used is configured via
-          :attr:`~sqlalchemy.engine.base.Dialect.encoding`, which
-          defaults to `utf-8`.
-
-          The "convert_unicode" behavior can also be turned on
-          for all String types by setting 
-          :attr:`sqlalchemy.engine.base.Dialect.convert_unicode`
-          on create_engine().
-
-          To instruct SQLAlchemy to perform Unicode encoding/decoding
-          even on a platform that already handles Unicode natively,
-          set convert_unicode='force'.  This will incur significant
-          performance overhead when fetching unicode result columns.
-
-        :param assert_unicode: Deprecated.  A warning is raised in all cases
-          when a non-Unicode object is passed when SQLAlchemy would coerce
-          into an encoding (note: but **not** when the DBAPI handles unicode
-          objects natively). To suppress or raise this warning to an error,
-          use the Python warnings filter documented at:
-          http://docs.python.org/library/warnings.html
+        :param convert_unicode: When set to ``True``, the 
+          :class:`.String` type will assume that
+          input is to be passed as Python ``unicode`` objects,
+          and results returned as Python ``unicode`` objects.
+          If the DBAPI in use does not support Python unicode
+          (which is fewer and fewer these days), SQLAlchemy
+          will encode/decode the value, using the 
+          value of the ``encoding`` parameter passed to 
+          :func:`.create_engine` as the encoding.
+          
+          When using a DBAPI that natively supports Python
+          unicode objects, this flag generally does not 
+          need to be set.  For columns that are explicitly
+          intended to store non-ASCII data, the :class:`.Unicode`
+          or :class:`UnicodeText` 
+          types should be used regardless, which feature
+          the same behavior of ``convert_unicode`` but 
+          also indicate an underlying column type that
+          directly supports unicode, such as ``NVARCHAR``.
+
+          For the extremely rare case that Python ``unicode``
+          is to be encoded/decoded by SQLAlchemy on a backend
+          that does natively support Python ``unicode``,
+          the value ``force`` can be passed here which will
+          cause SQLAlchemy's encode/decode services to be
+          used unconditionally.
+
+        :param assert_unicode: Deprecated.  A warning is emitted 
+          when a non-``unicode`` object is passed to the 
+          :class:`.Unicode` subtype of :class:`.String`, 
+          or the :class:`.UnicodeText` subtype of :class:`.Text`.   
+          See :class:`.Unicode` for information on how to 
+          control this warning.
 
         :param unicode_error: Optional, a method to use to handle Unicode
-          conversion errors. Behaves like the 'errors' keyword argument to
-          the standard library's string.decode() functions.   This flag
-          requires that `convert_unicode` is set to `"force"` - otherwise,
+          conversion errors. Behaves like the ``errors`` keyword argument to
+          the standard library's ``string.decode()`` functions.   This flag
+          requires that ``convert_unicode`` is set to ``force`` - otherwise,
           SQLAlchemy is not guaranteed to handle the task of unicode
           conversion.   Note that this flag adds significant performance
           overhead to row-fetching operations for backends that already
           return unicode objects natively (which most DBAPIs do).  This
-          flag should only be used as an absolute last resort for reading
-          strings from a column with varied or corrupted encodings,
-          which only applies to databases that accept invalid encodings 
-          in the first place (i.e. MySQL.  *not* PG, Sqlite, etc.)
+          flag should only be used as a last resort for reading
+          strings from a column with varied or corrupted encodings.
 
         """
         if unicode_error is not None and convert_unicode != 'force':
@@ -1109,37 +1111,57 @@ class Text(String):
     __visit_name__ = 'text'
 
 class Unicode(String):
-    """A variable length Unicode string.
-
-    The ``Unicode`` type is a :class:`.String` which converts Python
-    ``unicode`` objects (i.e., strings that are defined as
-    ``u'somevalue'``) into encoded bytestrings when passing the value
-    to the database driver, and similarly decodes values from the
-    database back into Python ``unicode`` objects.
-
-    It's roughly equivalent to using a ``String`` object with
-    ``convert_unicode=True``, however
-    the type has other significances in that it implies the usage 
-    of a unicode-capable type being used on the backend, such as NVARCHAR.
-    This may affect what type is emitted when issuing CREATE TABLE
-    and also may effect some DBAPI-specific details, such as type
-    information passed along to ``setinputsizes()``.
-
-    When using the ``Unicode`` type, it is only appropriate to pass
-    Python ``unicode`` objects, and not plain ``str``.  If a
-    bytestring (``str``) is passed, a runtime warning is issued.  If
-    you notice your application raising these warnings but you're not
-    sure where, the Python ``warnings`` filter can be used to turn
-    these warnings into exceptions which will illustrate a stack
-    trace::
+    """A variable length Unicode string type.
+
+    The :class:`.Unicode` type is a :class:`.String` subclass
+    that assumes input and output as Python ``unicode`` data,
+    and in that regard is equivalent to the usage of the
+    ``convert_unicode`` flag with the :class:`.String` type.
+    However, unlike plain :class:`.String`, it also implies an 
+    underlying column type that is explicitly supporting of non-ASCII
+    data, such as ``NVARCHAR`` on Oracle and SQL Server.
+    This can impact the output of ``CREATE TABLE`` statements 
+    and ``CAST`` functions at the dialect level, and can 
+    also affect the handling of bound parameters in some
+    specific DBAPI scenarios.
+    
+    The encoding used by the :class:`.Unicode` type is usually
+    determined by the DBAPI itself; most modern DBAPIs 
+    feature support for Python ``unicode`` objects as bound
+    values and result set values, and the encoding should
+    be configured as detailed in the notes for the target
+    DBAPI in the :ref:`dialect_toplevel` section.
+    
+    For those DBAPIs which do not support, or are not configured
+    to accommodate Python ``unicode`` objects
+    directly, SQLAlchemy does the encoding and decoding
+    outside of the DBAPI.   The encoding in this scenario 
+    is determined by the ``encoding`` flag passed to 
+    :func:`.create_engine`.
+
+    When using the :class:`.Unicode` type, it is only appropriate 
+    to pass Python ``unicode`` objects, and not plain ``str``.
+    If a plain ``str`` is passed under Python 2, a warning
+    is emitted.  If you notice your application emitting these warnings but 
+    you're not sure of the source of them, the Python 
+    ``warnings`` filter, documented at 
+    http://docs.python.org/library/warnings.html, 
+    can be used to turn these warnings into exceptions 
+    which will illustrate a stack trace::
 
       import warnings
       warnings.simplefilter('error')
 
-    Bytestrings sent to and received from the database are encoded
-    using the dialect's
-    :attr:`~sqlalchemy.engine.base.Dialect.encoding`, which defaults
-    to `utf-8`.
+    For an application that wishes to pass plain bytestrings
+    and Python ``unicode`` objects to the ``Unicode`` type
+    equally, the bytestrings must first be decoded into 
+    unicode.  The recipe at :ref:`coerce_to_unicode` illustrates
+    how this is done.
+
+    See also:
+
+        :class:`.UnicodeText` - unlengthed textual counterpart
+        to :class:`.Unicode`.
 
     """
 
@@ -1147,17 +1169,11 @@ class Unicode(String):
 
     def __init__(self, length=None, **kwargs):
         """
-        Create a Unicode-converting String type.
-
-        :param length: optional, a length for the column for use in
-          DDL statements.  May be safely omitted if no ``CREATE
-          TABLE`` will be issued.  Certain databases may require a
-          *length* for use in DDL, and will raise an exception when
-          the ``CREATE TABLE`` DDL is issued.  Whether the value is
-          interpreted as bytes or characters is database specific.
-
-        :param \**kwargs: passed through to the underlying ``String``
-          type.
+        Create a :class:`.Unicode` object.
+        
+        Parameters are the same as that of :class:`.String`,
+        with the exception that ``convert_unicode``
+        defaults to ``True``.
 
         """
         kwargs.setdefault('convert_unicode', True)
@@ -1165,13 +1181,14 @@ class Unicode(String):
         super(Unicode, self).__init__(length=length, **kwargs)
 
 class UnicodeText(Text):
-    """An unbounded-length Unicode string.
+    """An unbounded-length Unicode string type.
 
     See :class:`.Unicode` for details on the unicode
     behavior of this object.
 
-    Like ``Unicode``, usage the ``UnicodeText`` type implies a 
-    unicode-capable type being used on the backend, such as NCLOB.
+    Like :class:`.Unicode`, usage the :class:`.UnicodeText` type implies a 
+    unicode-capable type being used on the backend, such as 
+    ``NCLOB``, ``NTEXT``.
 
     """
 
@@ -1181,12 +1198,9 @@ class UnicodeText(Text):
         """
         Create a Unicode-converting Text type.
 
-        :param length: optional, a length for the column for use in
-          DDL statements.  May be safely omitted if no ``CREATE
-          TABLE`` will be issued.  Certain databases may require a
-          *length* for use in DDL, and will raise an exception when
-          the ``CREATE TABLE`` DDL is issued.  Whether the value is
-          interpreted as bytes or characters is database specific.
+        Parameters are the same as that of :class:`.Text`,
+        with the exception that ``convert_unicode``
+        defaults to ``True``.
 
         """
         kwargs.setdefault('convert_unicode', True)