summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-06-13 15:49:27 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2010-06-13 15:49:27 -0400
commit7378611832a8b58ce040dab3ee0739209c4c8854 (patch)
tree15d7ef3d60c5133a8b2089e4fc7cbbad49a07f08
parent27781263d93e4e35c8c39ed163fa827506cfb193 (diff)
downloadsqlalchemy-7378611832a8b58ce040dab3ee0739209c4c8854.tar.gz
- added documentation for Inspector [ticket:1820]
- fixed "toplevel" regexp to include tokens of the form foo-bar-toplevel (i.e. multiple dashes) - some CSS adjustment so that all API headings are in gray.
-rw-r--r--CHANGES5
-rw-r--r--doc/build/builder/util.py2
-rw-r--r--doc/build/metadata.rst7
-rw-r--r--doc/build/reference/sqlalchemy/index.rst1
-rw-r--r--doc/build/reference/sqlalchemy/inspector.rst36
-rw-r--r--doc/build/static/docs.css4
-rw-r--r--lib/sqlalchemy/__init__.py2
-rw-r--r--lib/sqlalchemy/engine/reflection.py83
8 files changed, 128 insertions, 12 deletions
diff --git a/CHANGES b/CHANGES
index d0be776fe..b7a92783d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -17,7 +17,10 @@ CHANGES
- firebird
- Fixed incorrect signature in do_execute(), error
introduced in 0.6.1. [ticket:1823]
-
+
+- documentation
+ - Added documentation for the Inspector. [ticket:1820]
+
0.6.1
=====
- orm
diff --git a/doc/build/builder/util.py b/doc/build/builder/util.py
index a7c4d6b5a..0ae4de5cd 100644
--- a/doc/build/builder/util.py
+++ b/doc/build/builder/util.py
@@ -4,5 +4,5 @@ def striptags(text):
return re.compile(r'<[^>]*>').sub('', text)
def strip_toplevel_anchors(text):
- return re.compile(r'\.html#\w+-toplevel').sub('.html', text)
+ return re.compile(r'\.html#[-\w]+-toplevel').sub('.html', text)
diff --git a/doc/build/metadata.rst b/doc/build/metadata.rst
index 2ac0ea2a4..6dcd625f9 100644
--- a/doc/build/metadata.rst
+++ b/doc/build/metadata.rst
@@ -231,6 +231,8 @@ Alternatively, the ``bind`` attribute of :class:`~sqlalchemy.schema.MetaData` is
* Your application talks to multiple database engines at different times, which use the *same* set of :class:`Table` objects. It's usually confusing and unnecessary to begin to create "copies" of :class:`Table` objects just so that different engines can be used for different operations. An example is an application that writes data to a "master" database while performing read-only operations from a "read slave". A global :class:`~sqlalchemy.schema.MetaData` object is *not* appropriate for per-request switching like this, although a :class:`~sqlalchemy.schema.ThreadLocalMetaData` object is.
* You are using the ORM :class:`Session` to handle which class/table is bound to which engine, or you are using the :class:`Session` to manage switching between engines. Its a good idea to keep the "binding of tables to engines" in one place - either using :class:`~sqlalchemy.schema.MetaData` only (the :class:`Session` can of course be present, it just has no ``bind`` configured), or using :class:`Session` only (the ``bind`` attribute of :class:`~sqlalchemy.schema.MetaData` is left empty).
+.. _metadata_reflection:
+
Reflecting Tables
-----------------
@@ -303,6 +305,11 @@ The :class:`~sqlalchemy.schema.MetaData` object can also get a listing of tables
for table in reversed(meta.sorted_tables):
someengine.execute(table.delete())
+Fine Grained Reflection with Inspector
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A low level interface which provides a backend-agnostic system of loading lists of schema, table, column, and constraint descriptions from a given database is also available. This is known as the "Inspector" and is described in the API documentation at :ref:`inspector_api_toplevel`.
+
Specifying the Schema Name
---------------------------
diff --git a/doc/build/reference/sqlalchemy/index.rst b/doc/build/reference/sqlalchemy/index.rst
index 2a3362b31..9970a669c 100644
--- a/doc/build/reference/sqlalchemy/index.rst
+++ b/doc/build/reference/sqlalchemy/index.rst
@@ -8,6 +8,7 @@ sqlalchemy
pooling
expressions
schema
+ inspector
types
interfaces
util
diff --git a/doc/build/reference/sqlalchemy/inspector.rst b/doc/build/reference/sqlalchemy/inspector.rst
new file mode 100644
index 000000000..e0ef91460
--- /dev/null
+++ b/doc/build/reference/sqlalchemy/inspector.rst
@@ -0,0 +1,36 @@
+.. _inspector_api_toplevel:
+
+Schema Introspection
+====================
+
+.. module:: sqlalchemy.engine.reflection
+
+SQLAlchemy provides rich schema introspection capabilities. The most common methods for this include the "autoload" argument of :class:`~sqlalchemy.schema.Table`::
+
+ from sqlalchemy import create_engine, MetaData, Table
+ engine = create_engine('...')
+ meta = MetaData()
+ user_table = Table('user', meta, autoload=True, autoload_with=engine)
+
+As well as the :meth:`~sqlalchemy.schema.MetaData.reflect` method of :class:`~sqlalchemy.schema.MetaData`::
+
+ from sqlalchemy import create_engine, MetaData, Table
+ engine = create_engine('...')
+ meta = MetaData()
+ meta.reflect(engine)
+ user_table = meta.tables['user']
+
+Further examples of reflection using :class:`~sqlalchemy.schema.Table` and :class:`~sqlalchemy.schema.MetaData` can be found at :ref:`metadata_reflection`.
+
+There is also a low-level inspection interface available for more specific operations, known as the :class:`Inspector`::
+
+ from sqlalchemy import create_engine
+ from sqlalchemy.engine import reflection
+ engine = create_engine('...')
+ insp = reflection.Inspector.from_engine(engine)
+ print insp.get_table_names()
+
+.. autoclass:: Inspector
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/doc/build/static/docs.css b/doc/build/static/docs.css
index 33fbca527..1df49f8b2 100644
--- a/doc/build/static/docs.css
+++ b/doc/build/static/docs.css
@@ -250,6 +250,9 @@ pre {
}
dl.function > dt,
+dl.attribute > dt,
+dl.classmethod > dt,
+dl.method > dt,
dl.class > dt
{
background-color:#F0F0F0;
@@ -257,6 +260,7 @@ dl.class > dt
padding: 0px 10px;
}
+
dt:target, span.highlight {
background-color:#FBE54E;
}
diff --git a/lib/sqlalchemy/__init__.py b/lib/sqlalchemy/__init__.py
index 4855602f3..df041574b 100644
--- a/lib/sqlalchemy/__init__.py
+++ b/lib/sqlalchemy/__init__.py
@@ -114,6 +114,6 @@ from sqlalchemy.engine import create_engine, engine_from_config
__all__ = sorted(name for name, obj in locals().items()
if not (name.startswith('_') or inspect.ismodule(obj)))
-__version__ = '0.6.1'
+__version__ = '0.6.2'
del inspect, sys
diff --git a/lib/sqlalchemy/engine/reflection.py b/lib/sqlalchemy/engine/reflection.py
index 4a3643a41..a78dac02b 100644
--- a/lib/sqlalchemy/engine/reflection.py
+++ b/lib/sqlalchemy/engine/reflection.py
@@ -45,14 +45,34 @@ def cache(fn, self, con, *args, **kw):
class Inspector(object):
"""Performs database schema inspection.
- The Inspector acts as a proxy to the dialects' reflection methods and
- provides higher level functions for accessing database schema information.
+ The Inspector acts as a proxy to the reflection methods of the
+ :class:`~sqlalchemy.engine.base.Dialect`, providing a
+ consistent interface as well as caching support for previously
+ fetched metadata.
+
+ The preferred method to construct an :class:`Inspector` is via the
+ :meth:`Inspector.from_engine` method. I.e.::
+
+ engine = create_engine('...')
+ insp = Inspector.from_engine(engine)
+
+ Where above, the :class:`~sqlalchemy.engine.base.Dialect` may opt
+ to return an :class:`Inspector` subclass that provides additional
+ methods specific to the dialect's target database.
+
"""
def __init__(self, bind):
- """Initialize the instance.
+ """Initialize a new :class:`Inspector`.
+
+ :param bind: a :class:`~sqlalchemy.engine.base.Connectable`,
+ which is typically an instance of
+ :class:`~sqlalchemy.engine.base.Engine` or
+ :class:`~sqlalchemy.engine.base.Connection`.
+
+ For a dialect-specific instance of :class:`Inspector`, see
+ :meth:`Inspector.from_engine`
- :param bind: a :class:`~sqlalchemy.engine.base.Connectable`
"""
# ensure initialized
@@ -70,13 +90,35 @@ class Inspector(object):
self.info_cache = {}
@classmethod
- def from_engine(cls, engine):
- if hasattr(engine.dialect, 'inspector'):
- return engine.dialect.inspector(engine)
- return Inspector(engine)
+ def from_engine(cls, bind):
+ """Construct a new dialect-specific Inspector object from the given engine or connection.
+
+ :param bind: a :class:`~sqlalchemy.engine.base.Connectable`,
+ which is typically an instance of
+ :class:`~sqlalchemy.engine.base.Engine` or
+ :class:`~sqlalchemy.engine.base.Connection`.
+
+ This method differs from direct a direct constructor call of :class:`Inspector`
+ in that the :class:`~sqlalchemy.engine.base.Dialect` is given a chance to provide
+ a dialect-specific :class:`Inspector` instance, which may provide additional
+ methods.
+
+ See the example at :class:`Inspector`.
+
+ """
+ if hasattr(bind.dialect, 'inspector'):
+ return bind.dialect.inspector(engine)
+ return Inspector(bind)
@property
def default_schema_name(self):
+ """Return the default schema name presented by the dialect
+ for the current engine's database user.
+
+ E.g. this is typically ``public`` for Postgresql and ``dbo``
+ for SQL Server.
+
+ """
return self.dialect.default_schema_name
def get_schema_names(self):
@@ -125,6 +167,11 @@ class Inspector(object):
return tnames
def get_table_options(self, table_name, schema=None, **kw):
+ """Return a dictionary of options specified when the table of the given name was created.
+
+ This currently includes some options that apply to MySQL tables.
+
+ """
if hasattr(self.dialect, 'get_table_options'):
return self.dialect.get_table_options(self.bind, table_name, schema,
info_cache=self.info_cache,
@@ -271,7 +318,25 @@ class Inspector(object):
return indexes
def reflecttable(self, table, include_columns):
-
+ """Given a Table object, load its internal constructs based on introspection.
+
+ This is the underlying method used by most dialects to produce
+ table reflection. Direct usage is like::
+
+ from sqlalchemy import create_engine, MetaData, Table
+ from sqlalchemy.engine import reflection
+
+ engine = create_engine('...')
+ meta = MetaData()
+ user_table = Table('user', meta)
+ insp = Inspector.from_engine(engine)
+ insp.reflecttable(user_table, None)
+
+ :param table: a :class:`~sqlalchemy.schema.Table` instance.
+ :param include_columns: a list of string column names to include
+ in the reflection process. If ``None``, all columns are reflected.
+
+ """
dialect = self.bind.dialect
# MySQL dialect does this. Applicable with other dialects?