I've released the first alpha version of SAContext, a class that
bundles your SQLAlchemy engines, metadatas, and SessionContext into
one convenient object like pylons.database.sesson_context only much
better.

    http://sluggo.scrapping.cc/python/sacontext/
    http://cheeseshop.python.org/pypi/SAContext/0.1.0

The API has been hammered out between me and Michael Bayer,
SQLAlchemy's author, to provide flexibility for single-engine and
multi-engine applications while sticking to his usage recommendations
(which session_context does NOT do).

I've added tickets to get this incorporated into Pylons:
    http://pylonshq.com/project/pylonshq/ticket/261
and SQLAlchemy:
    http://www.sqlalchemy.org/trac/ticket/617
This will take some testing and integration work. however.

The SAContext class can be used in any SQLAlchemy application, and
requires an explicit URI and engine args.  The test suite passes so
this can be used as-is.
PylonsSAContext is a subclass that optionally parses the specs from
the Pylons configuration, with full support for various engine args
and multiple databases.  The parsing method passes the test suite but
the whole thing has not been used in a Pylons application yet.  I'll
be testing it over the next week.  I'm releasing it now in case
anybody wants to test it or make API suggestions.

Basic usage from the docstring:

            # Connect to an engine.  The URI is mandatory but should be a
            # keyword arg.
            sac = SAContext(uri="sqlite://")    # A SQLite memory database.

            # Or pass additional engine options.
            sac = SAContext(uri="mysql://...", engine_options={"echo": True})

            # The metadata for this engine has automatically been created.
            users = Table("Users", sac.metadata, Column(...))

            # Or reflect the columns from an existing database table.
            users = Table("Users", sac.metadata, autoload=True)

            # ORM operations are managed by a hidden SessionContext that
            # automatically exposes a thread-specific session.
            sac.session.flush()

            # 'sac.query' is a shortcut for 'sac.session.query'.
            # (Use .list() instead of .all() in SQLALchemy < 0.3.9.)
            records = sac.query(User).filter_by(...).all()

            # Mappers can use the SessionContext extension this way.
            # Note: the extension is optional, not required.
            mapper(User, users, extension=sac.ext)

            # You can connect to multiple databases.
            sac.add_engine(key="logs", uri="mysql://...")

            # Each engine has its own bound metadata.
            access_log = Table("Access", sac.get_metadata("logs"), ...)

            # To access a non-default engine, do this.
            sac.get_engine("logs").echo = True

PylonsSAContext works the same but its constructor and .add_engine are
a bit more flexible:

            # Look up the URI in the config under 'sqlalchemy.default.dburi',
            # with engine options such as "sqlalchemy.default.echo = true" and
            # "sqlalchemy.default.pool_recycle = 3600".  These are automatically
            # converted to int/bool according to the SQLAlchemy manual.
            sac = PylonsSAContext()

            # Connect to a second database under 'squalchemy.database2.dburi'.
             sac.add_engine("database2")

             # Connect to a third database called "logs" but under the
config key
             # 'sqlalchemy.engine3.dburi'.  If there's no 'echo_pool'
option, default to
             # True.  Always set 'pool_recycle' to 3600 even if the config says
             # otherwise.  Also pass in a pool class, which can't be
specified in the
             # config file since it's not a scalar (string/int/bool).
             sac.add_engine("logs", config_key="engine3",
                 engine_options={"pool_recycle": 3600, "poolclass":
MyPoolClass},
                 engine_defaults={"echo_pool": True})

              # Connect to a fourth engine that's not in the config file.
              sac.add_engine("fourth", uri="mssql://...", engine_args={...})

              # Or don't use the config file at all.  (What are you smoking?)
              sac = PylonsSAContext(uri="sqlite:////tmp/crack.sqlite")

By default SAContext uses a "bound metadata" strategy which means
every engine is paired with a bound MetaData.  The session is not
aware of engines; it just executes queries and the metadatas find the
engines.

But if you pass a BoundSessionStrategy instance as SAContext(...,
strategy=my_strategy), it will bind the engines to the session
instead.  That's what pylons.database.session_context sorta does.
Most applications don't need this but it's useful in a few cases.  I
don't understand what those cases are but Michael mumbled something
about distributed databases, transactions spanning multiple databases,
etc.    So if you need it, it's there.

-- 
Mike Orr <[EMAIL PROTECTED]>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"pylons-discuss" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/pylons-discuss?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to