From 905632c70da9252bed652ab8fbd03160abbc041e Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Tue, 15 Nov 2011 00:36:56 -0500 Subject: [PATCH] docs docs docs docs --- alembic/config.py | 14 +++++-- alembic/context.py | 96 ++++++++++++++++++++++++++++++++++++++++------ docs/build/api.rst | 16 ++++++++ docs/build/ops.rst | 11 ++++++ 4 files changed, 122 insertions(+), 15 deletions(-) diff --git a/alembic/config.py b/alembic/config.py index c5389f80..5409b836 100644 --- a/alembic/config.py +++ b/alembic/config.py @@ -7,9 +7,17 @@ import os class Config(object): """Represent an Alembic configuration. - You can get at one of these by specifying the name of - an .ini file:: - + Within an ``env.py`` script, this is available + via the :attr:`alembic.context.config` attribute:: + + from alembic import context + + some_param = context.config.get_main_option("my option") + + When invoking Alembic programatically, a new + :class:`.Config` can be created simply by passing + the name of an .ini file to the constructor:: + from alembic.config import Config alembic_cfg = Config("/path/to/yourapp/alembic.ini") diff --git a/alembic/context.py b/alembic/context.py index adcb9e06..857c6a91 100644 --- a/alembic/context.py +++ b/alembic/context.py @@ -18,11 +18,11 @@ class Context(object): """Maintains state throughout the migration running process. Mediates the relationship between an ``env.py`` environment script, - a :class:`.ScriptDirectory` instance, and a :class:`.DDLImpl` instance. + a :class:`.ScriptDirectory` instance, and a :class:`.DefaultImpl` instance. - The :class:`.Context` is available via the :func:`.get_context` function, - though usually one would call the various module level functions - described here. + The :class:`.Context` is available directly via the :func:`.get_context` function, + though usually it is referenced behind the scenes by the various module level functions + within the :mod:`alembic.context` module. """ def __init__(self, dialect, script, connection, fn, @@ -121,16 +121,34 @@ class Context(object): @property def bind(self): - """Return a bind suitable for passing to the create() - or create_all() methods of MetaData, Table. + """Return the current "bind". + + In online mode, this is an instance of + :class:`sqlalchemy.engine.base.Connection`, and is suitable + for ad-hoc execution of any kind of usage described + in :ref:`sqlexpression_toplevel` as well as + for usage with the :meth:`sqlalchemy.schema.Table.create` + and :meth:`sqlalchemy.schema.MetaData.create_all` methods + of :class:`.Table`, :class:`.MetaData`. Note that when "standard output" mode is enabled, this bind will be a "mock" connection handler that cannot - return results and is only appropriate for DDL. + return results and is only appropriate for a very limited + subset of commands. """ return self.connection +config = None +"""The current :class:`.Config` object. + +This is the gateway to the ``alembic.ini`` or other +.ini file in use for the current command. + +This function does not require that the :class:`.Context` +has been configured. + +""" _context_opts = {} _context = None @@ -159,12 +177,20 @@ def requires_connection(): Currently, this is ``True`` or ``False`` depending on the the ``--sql`` flag passed. + + This function does not require that the :class:`.Context` + has been configured. """ return not _context_opts.get('as_sql', False) def get_head_revision(): - """Return the hex identifier of the 'head' revision.""" + """Return the hex identifier of the 'head' revision. + + This function does not require that the :class:`.Context` + has been configured. + + """ return _script._as_rev_number("head") def get_starting_revision_argument(): @@ -175,6 +201,9 @@ def get_starting_revision_argument(): Returns ``None`` if no value is available or was configured. + This function does not require that the :class:`.Context` + has been configured. + """ if _context is not None: return _script._as_rev_number(get_context()._start_from_rev) @@ -185,7 +214,7 @@ def get_starting_revision_argument(): def get_revision_argument(): """Get the 'destination' revision argument. - + This is typically the argument passed to the ``upgrade`` or ``downgrade`` command, but can be overridden via the ``destination_rev`` argument @@ -196,16 +225,22 @@ def get_revision_argument(): version number is returned; if specified as ``base``, ``None`` is returned. + This function does not require that the :class:`.Context` + has been configured. + """ return _script._as_rev_number(_context_opts['destination_rev']) def get_tag_argument(): """Return the value passed for the ``--tag`` argument, if any. - + The ``--tag`` argument is not used directly by Alembic, but is available for custom ``env.py`` configurations that wish to use it; particularly for offline generation scripts that wish to generate tagged filenames. + + This function does not require that the :class:`.Context` + has been configured. """ return _context_opts.get('tag', None) @@ -293,7 +328,7 @@ def run_migrations(**kw): """Run migrations as determined by the current command line configuration as well as versioning information present (or not) in the current database connection (if one is present). - + The function accepts optional ``**kw`` arguments. If these are passed, they are sent directly to the ``upgrade()`` and ``downgrade()`` functions within each target revision file. By modifying the @@ -302,6 +337,9 @@ def run_migrations(**kw): contextual information, usually information to identify a particular database in use, can be passed from a custom ``env.py`` script to the migration functions. + + This function requires that a :class:`.Context` has first been + made available via :func:`.configure`. """ get_context().run_migrations(**kw) @@ -310,7 +348,38 @@ def execute(sql): """Execute the given SQL using the current change context. In a SQL script context, the statement is emitted directly to the - output stream. + output stream. There is *no* return result, however, as this + function is oriented towards generating a change script + that can run in "offline" mode. For full interaction + with a connected database, use the "bind" available + from the context:: + + connection = get_context().bind + + Also note that any parameterized statement here *will not work* + in offline mode - any kind of UPDATE or DELETE needs to render + inline expressions. Due to these limitations, + :func:`.execute` is overall not spectacularly useful for migration + scripts that wish to run in offline mode. Consider using the Alembic + directives, or if the environment is only meant to run in + "online" mode, use the ``get_context().bind``. + + :param sql: Any legal SQLAlchemy expression, including: + + * a string + * a :func:`sqlalchemy.sql.expression.text` construct, with the caveat that + bound parameters won't work correctly in offline mode. + * a :func:`sqlalchemy.sql.expression.insert` construct. If working + in offline mode, consider using :func:`alembic.op.bulk_insert` + instead to support parameterization. + * a :func:`sqlalchemy.sql.expression.update`, :func:`sqlalchemy.sql.expression.insert`, + or :func:`sqlalchemy.sql.expression.delete` construct, with the caveat + that bound parameters won't work correctly in offline mode. + * Pretty much anything that's "executable" as described + in :ref:`sqlexpression_toplevel`. + + This function requires that a :class:`.Context` has first been + made available via :func:`.configure`. """ get_context().execute(sql) @@ -318,6 +387,9 @@ def execute(sql): def get_context(): """Return the current :class:`.Context` object. + If :func:`.configure` has not been called yet, raises + an exception. + Generally, env.py scripts should access the module-level functions in :mod:`alebmic.context` to get at this object's functionality. diff --git a/docs/build/api.rst b/docs/build/api.rst index cff5826c..8c7f6505 100644 --- a/docs/build/api.rst +++ b/docs/build/api.rst @@ -11,6 +11,14 @@ env.py Directives The :mod:`alembic.context` module contains API features that are generally used within ``env.py`` files. +The central object in use is the :class:`.Context` object. This object is +made present when the ``env.py`` script calls upon the :func:`.configure` +method for the first time. Before this function is called, there's not +yet any database connection or dialect-specific state set up, and those +functions which require this state will raise an exception when used, +until :func:`.configure` is called successfully. + + .. autofunction:: sqlalchemy.engine.engine_from_config .. currentmodule:: alembic.context @@ -25,6 +33,14 @@ Alembic commands are all represented by functions in the :mod:`alembic.command` package. They all accept the same style of usage, being sent the :class:`~.alembic.config.Config` object as the first argument. +Commands can be run programmatically, by first constructing a :class:`.Config` +object, as in:: + + from alembic.config import Config + from alembic import command + alembic_cfg = Config("/path/to/yourapp/alembic.ini") + command.upgrade(alembic_cfg, "head") + .. currentmodule:: alembic.command .. automodule:: alembic.command diff --git a/docs/build/ops.rst b/docs/build/ops.rst index 27781a94..92338a5b 100644 --- a/docs/build/ops.rst +++ b/docs/build/ops.rst @@ -6,5 +6,16 @@ Operation Reference This file provides documentation on Alembic migration directives. +The directives here are used within user-defined migration files, +within the ``upgrade()`` and ``downgrade()`` functions, as well as +any functions further invoked by those. + +The functions here all require that a :class:`.Context` has been +configured within the ``env.py`` script. Under normal circumstances +this is always the case, as the migration scripts are invoked via +the :func:`.context.run_migrations` function which ultimately +is derived from the :class:`.Context` object. + + .. automodule:: alembic.op :members: -- 2.47.2