]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- add a new sphinx extension "viewsource". takes advantage of part of the viewcode...
authorMike Bayer <mike_mp@zzzcomputing.com>
Sun, 10 Nov 2013 00:42:01 +0000 (19:42 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 10 Nov 2013 00:42:01 +0000 (19:42 -0500)
to allow ad-hoc display of the source of any file, as well as a "directory listing" structure.
- reorganize examples/ to take advantage of new extension.  in particular, keep moving all
the descriptive text for files etc. into module docstrings, taking more advantage of
self-documentation.

36 files changed:
doc/build/builder/viewsource.py [new file with mode: 0644]
doc/build/conf.py
doc/build/orm/examples.rst
examples/adjacency_list/__init__.py
examples/association/__init__.py
examples/association/basic_association.py
examples/association/dict_of_sets_with_default.py
examples/association/proxied_association.py
examples/custom_attributes/__init__.py
examples/dogpile_caching/__init__.py
examples/dogpile_caching/caching_query.py
examples/dogpile_caching/local_session_caching.py
examples/dogpile_caching/model.py
examples/dogpile_caching/relationship_caching.py [moved from examples/dogpile_caching/relation_caching.py with 90% similarity]
examples/dynamic_dict/__init__.py
examples/elementtree/__init__.py
examples/elementtree/adjacency_list.py
examples/elementtree/optimized_al.py
examples/generic_associations/__init__.py
examples/generic_associations/discriminator_on_association.py
examples/generic_associations/generic_fk.py
examples/generic_associations/table_per_association.py
examples/generic_associations/table_per_related.py
examples/graphs/__init__.py
examples/inheritance/__init__.py
examples/inheritance/concrete.py
examples/inheritance/joined.py
examples/inheritance/single.py
examples/large_collection/__init__.py
examples/nested_sets/__init__.py
examples/postgis/__init__.py
examples/sharding/__init__.py
examples/versioning/__init__.py
examples/versioning/history_meta.py
examples/versioning/test_versioning.py
examples/vertical/__init__.py

diff --git a/doc/build/builder/viewsource.py b/doc/build/builder/viewsource.py
new file mode 100644 (file)
index 0000000..3999085
--- /dev/null
@@ -0,0 +1,201 @@
+from docutils import nodes
+from sphinx.ext.viewcode import collect_pages
+from sphinx.pycode import ModuleAnalyzer
+import imp
+from sphinx import addnodes
+import re
+from sphinx.util.compat import Directive
+import os
+from docutils.statemachine import StringList
+from sphinx.environment import NoUri
+
+def view_source(name, rawtext, text, lineno, inliner,
+                      options={}, content=[]):
+
+    env = inliner.document.settings.env
+
+    node = _view_source_node(env, text, None)
+    return [node], []
+
+def _view_source_node(env, text, state):
+    # pretend we're using viewcode fully,
+    # install the context it looks for
+    if not hasattr(env, '_viewcode_modules'):
+        env._viewcode_modules = {}
+
+    modname = text
+    text = modname.split(".")[-1] + ".py"
+
+    # imitate sphinx .<modname> syntax
+    if modname.startswith("."):
+        # see if the modname needs to be corrected in terms
+        # of current module context
+        base_module = env.temp_data.get('autodoc:module')
+        if base_module is None:
+            base_module = env.temp_data.get('py:module')
+
+        if base_module:
+            modname = base_module + modname
+
+    urito = env.app.builder.get_relative_uri
+
+    # we're showing code examples which may have dependencies
+    # which we really don't want to have required so load the
+    # module by file, not import (though we are importing)
+    # the top level module here...
+    pathname = None
+    for token in modname.split("."):
+        file_, pathname, desc = imp.find_module(token, [pathname] if pathname else None)
+        if file_:
+            file_.close()
+
+    # unlike viewcode which silently traps exceptions,
+    # I want this to totally barf if the file can't be loaded.
+    # a failed build better than a complete build missing
+    # key content
+    analyzer = ModuleAnalyzer.for_file(pathname, modname)
+    # copied from viewcode
+    analyzer.find_tags()
+    if not isinstance(analyzer.code, unicode):
+        code = analyzer.code.decode(analyzer.encoding)
+    else:
+        code = analyzer.code
+
+    if state is not None:
+        docstring = _find_mod_docstring(analyzer)
+        if docstring:
+            # get rid of "foo.py" at the top
+            docstring = re.sub(r"^[a-zA-Z_0-9]+\.py", "", docstring)
+
+            # strip
+            docstring = docstring.strip()
+
+            # yank only first paragraph
+            docstring = docstring.split("\n\n")[0].strip()
+    else:
+        docstring = None
+
+    entry = code, analyzer.tags, {}
+    env._viewcode_modules[modname] = entry
+    pagename = '_modules/' + modname.replace('.', '/')
+
+    try:
+        refuri = urito(env.docname, pagename)
+    except NoUri:
+        # if we're in the latex builder etc., this seems
+        # to be what we get
+        refuri = None
+
+
+    if docstring:
+        # embed the ref with the doc text so that it isn't
+        # a separate paragraph
+        if refuri:
+            docstring = "`%s <%s>`_ - %s" % (text, refuri, docstring)
+        else:
+            docstring = "``%s`` - %s" % (text, docstring)
+        para = nodes.paragraph('', '')
+        state.nested_parse(StringList([docstring]), 0, para)
+        return_node = para
+    else:
+        if refuri:
+            refnode = nodes.reference('', '',
+                    nodes.Text(text, text),
+                    refuri=urito(env.docname, pagename)
+                )
+        else:
+            refnode = nodes.Text(text, text)
+
+        if state:
+            return_node = nodes.paragraph('', '', refnode)
+        else:
+            return_node = refnode
+
+    return return_node
+
+from sphinx.pycode.pgen2 import token
+
+def _find_mod_docstring(analyzer):
+    """attempt to locate the module-level docstring.
+
+    Note that sphinx autodoc just uses ``__doc__``.  But we don't want
+    to import the module, so we need to parse for it.
+
+    """
+    analyzer.tokenize()
+    for type_, parsed_line, start_pos, end_pos, raw_line in analyzer.tokens:
+        if type_ == token.COMMENT:
+            continue
+        elif type_ == token.STRING:
+            return eval(parsed_line)
+        else:
+            return None
+
+def _parse_content(content):
+    d = {}
+    d['text'] = []
+    idx = 0
+    for line in content:
+        idx += 1
+        m = re.match(r' *\:(.+?)\:(?: +(.+))?', line)
+        if m:
+            attrname, value = m.group(1, 2)
+            d[attrname] = value or ''
+        else:
+            break
+    d["text"] = content[idx:]
+    return d
+
+def _comma_list(text):
+    return re.split(r"\s*,\s*", text.strip())
+
+class AutoSourceDirective(Directive):
+    has_content = True
+
+    def run(self):
+        content = _parse_content(self.content)
+
+
+        env = self.state.document.settings.env
+        self.docname = env.docname
+
+        sourcefile = self.state.document.current_source.split(":")[0]
+        dir_ = os.path.dirname(sourcefile)
+        files = [
+            f for f in os.listdir(dir_) if f.endswith(".py")
+            and f != "__init__.py"
+        ]
+
+        if "files" in content:
+            # ordered listing of files to include
+            files = [fname for fname in _comma_list(content["files"])
+                        if fname in set(files)]
+
+        node = nodes.paragraph('', '',
+                        nodes.Text("Listing of files:", "Listing of files:")
+                )
+
+        bullets = nodes.bullet_list()
+        for fname in files:
+            modname, ext = os.path.splitext(fname)
+            # relative lookup
+            modname = "." + modname
+
+            link = _view_source_node(env, modname, self.state)
+
+            list_node = nodes.list_item('',
+                link
+            )
+            bullets += list_node
+
+        node += bullets
+
+        return [node]
+
+def setup(app):
+    app.add_role('viewsource', view_source)
+
+    app.add_directive('autosource', AutoSourceDirective)
+
+    # from sphinx.ext.viewcode
+    app.connect('html-collect-pages', collect_pages)
index e08b0184811b270d0968a4b08e2f35a52ba4fd50..efc9e217f44ae03d717d1cbc5f122cbbdbfc3e67 100644 (file)
@@ -18,7 +18,7 @@ import os
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.
 sys.path.insert(0, os.path.abspath('../../lib'))
-sys.path.insert(0, os.path.abspath('../../examples'))
+sys.path.insert(0, os.path.abspath('../..')) # examples
 sys.path.insert(0, os.path.abspath('.'))
 
 import sqlalchemy
@@ -38,6 +38,7 @@ extensions = [
                 'builder.dialect_info',
                 'builder.mako',
                 'builder.sqlformatter',
+                'builder.viewsource',
             ]
 
 # Add any paths that contain templates here, relative to this directory.
index e0c87dadf771237681fc2e4c1bd650dfde6a4baf..60d075a3693263670b8cdc3c5aae0227bbcd438e 100644 (file)
@@ -12,23 +12,20 @@ each of which are listed below.
 Additional SQLAlchemy examples, some user contributed, are available on the
 wiki at `<http://www.sqlalchemy.org/trac/wiki/UsageRecipes>`_.
 
+
 .. _examples_adjacencylist:
 
 Adjacency List
 --------------
 
-Location: /examples/adjacency_list/
-
-.. automodule:: adjacency_list
+.. automodule:: examples.adjacency_list
 
 .. _examples_associations:
 
 Associations
 ------------
 
-Location: /examples/association/
-
-.. automodule:: association
+.. automodule:: examples.association
 
 
 .. _examples_instrumentation:
@@ -36,105 +33,74 @@ Location: /examples/association/
 Attribute Instrumentation
 -------------------------
 
-Location: /examples/custom_attributes/
-
-.. automodule:: custom_attributes
+.. automodule:: examples.custom_attributes
 
 .. _examples_caching:
 
 Dogpile Caching
 ---------------
 
-Location: /examples/dogpile_caching/
-
-.. automodule:: dogpile_caching
+.. automodule:: examples.dogpile_caching
 
 Directed Graphs
 ---------------
 
-Location: /examples/graphs/
-
-.. automodule:: graphs
+.. automodule:: examples.graphs
 
 Dynamic Relations as Dictionaries
 ----------------------------------
 
-Location: /examples/dynamic_dict/
-
-.. automodule:: dynamic_dict
+.. automodule:: examples.dynamic_dict
 
 .. _examples_generic_associations:
 
 Generic Associations
 --------------------
 
-Location: /examples/generic_associations
-
-.. automodule:: generic_associations
+.. automodule:: examples.generic_associations
 
 .. _examples_sharding:
 
 Horizontal Sharding
 -------------------
 
-Location: /examples/sharding
-
-.. automodule:: sharding
+.. automodule:: examples.sharding
 
 Inheritance Mappings
 --------------------
 
-Location: /examples/inheritance/
-
-.. automodule:: inheritance
+.. automodule:: examples.inheritance
 
 Large Collections
 -----------------
 
-Location: /examples/large_collection/
-
-.. automodule:: large_collection
+.. automodule:: examples.large_collection
 
 Nested Sets
 -----------
 
-Location: /examples/nested_sets/
-
-.. automodule:: nested_sets
-
-Polymorphic Associations
-------------------------
-
-See :ref:`examples_generic_associations` for a modern version of polymorphic associations.
+.. automodule:: examples.nested_sets
 
 .. _examples_postgis:
 
 PostGIS Integration
 -------------------
 
-Location: /examples/postgis
-
-.. automodule:: postgis
+.. automodule:: examples.postgis
 
 Versioned Objects
 -----------------
 
-Location: /examples/versioning
-
-.. automodule:: versioning
+.. automodule:: examples.versioning
 
 Vertical Attribute Mapping
 --------------------------
 
-Location: /examples/vertical
-
-.. automodule:: vertical
+.. automodule:: examples.vertical
 
 .. _examples_xmlpersistence:
 
 XML Persistence
 ---------------
 
-Location: /examples/elementtree/
-
-.. automodule:: elementtree
+.. automodule:: examples.elementtree
index 44f27090bf90df269e042c9aa81ca6c7c5414caf..5d80363e4a14ed6f54c8ad14b6cc46548f9cb0f5 100644 (file)
@@ -12,5 +12,7 @@ E.g.::
 
     dump_tree(node)
 
+.. autosource::
+
 """
 
index df736f4fbd262fc68827c08a83fcae795bedef83..4cd64c22f8b3edc1986c401e5e88dde2c496b246 100644 (file)
@@ -1,20 +1,8 @@
 """
-
 Examples illustrating the usage of the "association object" pattern,
 where an intermediary class mediates the relationship between two
 classes that are associated in a many-to-many pattern.
 
-This directory includes the following examples:
-
-* basic_association.py - illustrate a many-to-many relationship between an
-  "Order" and a collection of "Item" objects, associating a purchase price
-  with each via an association object called "OrderItem"
-* proxied_association.py - same example as basic_association, adding in
-  usage of :mod:`sqlalchemy.ext.associationproxy` to make explicit references
-  to "OrderItem" optional.
-* dict_of_sets_with_default.py - an advanced association proxy example which
-  illustrates nesting of association proxies to produce multi-level Python
-  collections, in this case a dictionary with string keys and sets of integers
-  as values, which conceal the underlying mapped classes.
+.. autosource::
 
 """
\ No newline at end of file
index a175b1b8974c5224d8d788d0f726fabb2ee5cddc..8a8a54ad1c121f1473056b40f596a5d23085cebf 100644 (file)
@@ -1,4 +1,8 @@
-"""A basic example of using the association object pattern.
+"""basic_association.py
+
+illustrate a many-to-many relationship between an
+"Order" and a collection of "Item" objects, associating a purchase price
+with each via an association object called "OrderItem"
 
 The association object pattern is a form of many-to-many which
 associates additional data with each association between parent/child.
index f541727e75fc9f783b2192ddfe45ddfb24dbc8ef..fc4aebfca52fd3e7a15202c8e5c15642a4d27d76 100644 (file)
@@ -1,4 +1,9 @@
-"""Illustrate a 'dict of sets of integers' model.
+"""dict_of_sets_with_default.py
+
+an advanced association proxy example which
+illustrates nesting of association proxies to produce multi-level Python
+collections, in this case a dictionary with string keys and sets of integers
+as values, which conceal the underlying mapped classes.
 
 This is a three table model which represents a parent table referencing a
 dictionary of string keys and sets as values, where each set stores a
index 4cf1c51be79ed940b4a04a86e7b90da3d4a64ab1..7cb4c933821f50bbf3b0cf757028ca14f43b9e6c 100644 (file)
@@ -1,5 +1,9 @@
-"""An extension to the basic_association.py example, which illustrates
-the usage of sqlalchemy.ext.associationproxy.
+"""proxied_association.py
+
+same example as basic_association, adding in
+usage of :mod:`sqlalchemy.ext.associationproxy` to make explicit references
+to ``OrderItem`` optional.
+
 
 """
 
index b28e97d957e41df1887933e39f8501484ee99da4..2072c051f3b1199e1c7834add78b30645c07b430 100644 (file)
@@ -2,18 +2,6 @@
 Two examples illustrating modifications to SQLAlchemy's attribute management
 system.
 
-``listen_for_events.py`` illustrates the usage of
-:class:`~sqlalchemy.orm.interfaces.AttributeExtension` to intercept attribute
-events.  It additionally illustrates a way to automatically attach these
-listeners to all class attributes using a
-:class:`.InstrumentationManager`.
-
-``custom_management.py`` illustrates much deeper usage of
-:class:`.InstrumentationManager` as well as
-collection adaptation, to completely change the underlying method used to
-store state on an object.   This example was developed to illustrate
-techniques which would be used by other third party object instrumentation
-systems to interact with SQLAlchemy's event system and is only intended for
-very intricate framework integrations.
+.. autosource::
 
 """
\ No newline at end of file
index 00c386bda9c2b07f18bb090a1570c1969cf638d1..2d986584b578f78980a5227e32c1093234c52868 100644 (file)
@@ -50,35 +50,9 @@ The demo scripts themselves, in order of complexity, are run as follows::
 
    python examples/dogpile_caching/local_session_caching.py
 
-
-Listing of files:
-
-    environment.py - Establish the Session, a dictionary
-    of "regions", a sample cache region against a .dbm
-    file, data / cache file paths, and configurations,
-    bootstrap fixture data if necessary.
-
-    caching_query.py - Represent functions and classes
-    which allow the usage of Dogpile caching with SQLAlchemy.
-    Introduces a query option called FromCache.
-
-    model.py - The datamodel, which represents Person that has multiple
-    Address objects, each with PostalCode, City, Country
-
-    fixture_data.py - creates demo PostalCode, Address, Person objects
-    in the database.
-
-    helloworld.py - the basic idea.
-
-    relationship_caching.py - Illustrates how to add cache options on
-    relationship endpoints, so that lazyloads load from cache.
-
-    advanced.py - Further examples of how to use FromCache.  Combines
-    techniques from the first two scripts.
-
-    local_session_caching.py - Grok everything so far ?   This example
-    creates a new dogpile.cache backend that will persist data in a dictionary
-    which is local to the current session.   remove() the session
-    and the cache is gone.
+.. autosource::
+    :files: environment.py, caching_query.py, model.py, fixture_data.py, \
+          helloworld.py, relationship_caching.py, advanced.py, \
+          local_session_caching.py
 
 """
index 7fe84bede071123ede49c9d1089a74bdc0c5aa10..9ac0d431ab5370b12bcbecd8550456106d39c751 100644 (file)
@@ -1,7 +1,8 @@
 """caching_query.py
 
-Represent persistence structures which allow the usage of
-dogpile.cache caching with SQLAlchemy.
+Represent functions and classes
+which allow the usage of Dogpile caching with SQLAlchemy.
+Introduces a query option called FromCache.
 
 The three new concepts introduced here are:
 
index cf0083d2e755dac2edb3989bc406d287f293fbce..e6c712b4af47c0c31372b19cc92be5ab8cd10e82 100644 (file)
@@ -1,5 +1,10 @@
 """local_session_caching.py
 
+Grok everything so far ?   This example
+creates a new dogpile.cache backend that will persist data in a dictionary
+which is local to the current session.   remove() the session
+and the cache is gone.
+
 Create a new Dogpile cache backend that will store
 cached data local to the current Session.
 
index 622d31e6ac17256a022db6a694564934ad7e7a57..75c0ad28a8c03b57d10bcc623e44554c2b20b10e 100644 (file)
@@ -1,6 +1,7 @@
-"""Model.   We are modeling Person objects with a collection
-of Address objects.  Each Address has a PostalCode, which
-in turn references a City and then a Country:
+"""model.py
+
+The datamodel, which represents Person that has multiple
+Address objects, each with PostalCode, City, Country.
 
 Person --(1..n)--> Address
 Address --(has a)--> PostalCode
similarity index 90%
rename from examples/dogpile_caching/relation_caching.py
rename to examples/dogpile_caching/relationship_caching.py
index d40752e4839a9b664eb1f559d23725487d11afc3..320ced48a80611ac9084b6e9aeaaabdaaa925af5 100644 (file)
@@ -1,5 +1,8 @@
 """relationship_caching.py
 
+Illustrates how to add cache options on
+relationship endpoints, so that lazyloads load from cache.
+
 Load a set of Person and Address objects, specifying that
 related PostalCode, City, Country objects should be pulled from long
 term cache.
index 7f7b0691d30017850aadca0a8bb11dbb6c71b568..e592ea20056a73806dbc39edc2cc0e864c065de8 100644 (file)
@@ -3,4 +3,6 @@
 string keys) can operate upon a large collection without loading the
 full collection at once.
 
+.. autosource::
+
 """
\ No newline at end of file
index 6462dd56297c19deb8d154d63b25698199ba1bb3..66e9cfbbe39b6e56e6faecdad39b114e9c1e8c8b 100644 (file)
@@ -7,26 +7,6 @@ native cElementTree as well as lxml, and can be adapted to
 suit any kind of DOM representation system. Querying along
 xpath-like strings is illustrated as well.
 
-In order of complexity:
-
-* ``pickle.py`` - Quick and dirty, serialize the whole DOM into a BLOB
-  column.  While the example   is very brief, it has very limited
-  functionality.
-
-* ``adjacency_list.py`` - Each DOM node is stored in an individual
-  table row, with attributes   represented in a separate table.  The
-  nodes are associated in a hierarchy using an adjacency list
-  structure.  A query function is introduced which can search for nodes
-  along any path with a given   structure of attributes, basically a
-  (very narrow) subset of xpath.
-
-* ``optimized_al.py`` - Uses the same strategy as
-  ``adjacency_list.py``, but associates each   DOM row with its owning
-  document row, so that a full document of DOM nodes can be   loaded
-  using O(1) queries - the construction of the "hierarchy" is performed
-  after the load in a non-recursive fashion and is much more
-  efficient.
-
 E.g.::
 
     # parse an XML file and persist in the database
@@ -39,4 +19,7 @@ E.g.::
         # dump the XML
         print document
 
+.. autosource::
+    :files: pickle.py, adjacency_list.py, optimized_al.py
+
 """
\ No newline at end of file
index a3ad42778bf336ddecb36bf1ea19665af4bbaf12..5e27ba9caeea674ec9559070bf3af94b18b7ef7d 100644 (file)
@@ -1,9 +1,17 @@
-"""illustrates an explicit way to persist an XML document expressed using ElementTree.
+"""Illustrates an explicit way to persist an XML document expressed using ElementTree.
+
+Each DOM node is stored in an individual
+table row, with attributes   represented in a separate table.  The
+nodes are associated in a hierarchy using an adjacency list
+structure.  A query function is introduced which can search for nodes
+along any path with a given   structure of attributes, basically a
+(very narrow) subset of xpath.
 
 This example explicitly marshals/unmarshals the ElementTree document into
 mapped entities which have their own tables.  Compare to pickle.py which
 uses pickle to accomplish the same task.  Note that the usage of both
 styles of persistence are identical, as is the structure of the main Document class.
+
 """
 
 ################################# PART I - Imports/Coniguration ####################################
index 1dbad09434bd5680ffe0d7b9c352ea726e293ddf..e13f5b0eedf8d7cd682a0f0c47ed1168c72cc4f1 100644 (file)
@@ -1,7 +1,9 @@
-"""This script duplicates adjacency_list.py, but optimizes the loading
-of XML nodes to be based on a "flattened" datamodel. Any number of XML documents,
-each of arbitrary complexity, can be loaded in their entirety via a single query
-which joins on only three tables.
+"""Uses the same strategy as
+  ``adjacency_list.py``, but associates each   DOM row with its owning
+  document row, so that a full document of DOM nodes can be loaded
+  using O(1) queries - the construction of the "hierarchy" is performed
+  after the load in a non-recursive fashion and is more
+  efficient.
 
 """
 
index 2121e8b603530a836590e9d2ef29faf1d4457cb5..b6593b4f4652d548e864be1a9aa752d96c5405b3 100644 (file)
@@ -9,19 +9,10 @@ subclassing the ``HasAddresses`` mixin, which ensures that the
 parent class is provided with an ``addresses`` collection
 which contains ``Address`` objects.
 
-The configurations include:
-
-* ``table_per_related.py`` - illustrates a distinct table per related collection.
-* ``table_per_association.py`` - illustrates a shared collection table, using a
-  table per association.
-* ``discriminator_on_association.py`` - shared collection table and shared
-  association table, including a discriminator column.
-* ``generic_fk.py`` - imitates the approach taken by popular frameworks such
-  as Django and Ruby on Rails to create a so-called "generic foreign key".
-
-The ``discriminator_on_association.py`` and ``generic_fk.py`` scripts
+The :viewsource:`.discriminator_on_association` and :viewsource:`.generic_fk` scripts
 are modernized versions of recipes presented in the 2007 blog post
 `Polymorphic Associations with SQLAlchemy <http://techspot.zzzeek.org/2007/05/29/polymorphic-associations-with-sqlalchemy/>`_.
-.
+
+.. autosource::
 
 """
\ No newline at end of file
index 9968810d55d5e5f85d0cf85f50b429978c8054d9..e03cfec0093441d0605e1e8c5b9a39deba0ed0b9 100644 (file)
@@ -1,17 +1,15 @@
 """discriminator_on_related.py
 
-The HasAddresses mixin will provide a relationship
-to the fixed Address table based on a fixed association table.
-
-The association table contains a "discriminator"
-which determines what type of parent object associates to the
-Address row.  SQLAlchemy's single-table-inheritance feature is used
+Illustrates a mixin which provides a generic association
+using a single target table and a single association table,
+referred to by all parent tables.  The association table
+contains a "discriminator" column which determines what type of
+parent object associates to each particular row in the association
+table.
+
+SQLAlchemy's single-table-inheritance feature is used
 to target different association types.
 
-This is a "polymorphic association".   Even though a "discriminator"
-that refers to a particular table is present, the extra association
-table is used so that traditional foreign key constraints may be used.
-
 This configuration attempts to simulate a so-called "generic foreign key"
 as closely as possible without actually foregoing the use of real
 foreign keys.   Unlike table-per-related and table-per-association,
index b92a28f602503351710b1c860363b418323b2380..e228c6ba4ae6c4cc42401900c12750db5464e7e4 100644 (file)
@@ -1,12 +1,11 @@
 """generic_fk.py
 
-This example will emulate key aspects of the system used by popular
-frameworks such as Django, ROR, etc.
-
-It approaches the issue by bypassing standard referential integrity
-practices, and producing a so-called "generic foreign key", which means
-a database column that is not constrained to refer to any particular table.
-In-application logic is used to determine which table is referenced.
+Illustrates a so-called "generic foreign key", in a similar fashion
+to that of popular frameworks such as Django, ROR, etc.  This
+approach bypasses standard referential integrity
+practices, in that the "foreign key" column is not actually
+constrained to refer to any particular table; instead,
+in-application logic is used to determine which table is referenced.
 
 This approach is not in line with SQLAlchemy's usual style, as foregoing
 foreign key integrity means that the tables can easily contain invalid
index 4cdc3549416a14dc411785afcec1900305374aec..4993492a464a29184ac8bb93f82e7047270a2770 100644 (file)
@@ -1,8 +1,9 @@
 """table_per_association.py
 
-The HasAddresses mixin will provide a new "address_association" table for
-each parent class.   The "address" table will be shared
-for all parents.
+Illustrates a mixin which provides a generic association
+via a individually generated association tables for each parent class.
+The associated objects themselves are persisted in a single table
+shared among all parents.
 
 This configuration has the advantage that all Address
 rows are in one table, so that the definition of "Address"
index 8823cd3888762a68beede9217c138b9874bbe3f1..aff6e40ce6d2653ffb934f2f144bb39793aa244c 100644 (file)
@@ -1,7 +1,8 @@
 """table_per_related.py
 
-The HasAddresses mixin will provide a new "address" table for
-each parent class, as well as a distinct "Address" subclass.
+Illustrates a generic association which persists association
+objects within individual tables, each one generated to persist
+those objects on behalf of a particular parent class.
 
 This configuration has the advantage that each type of parent
 maintains its "Address" rows separately, so that collection
index 629808abe91ffede9e5354bc74da686701357f99..57d41453b008795ad689f7040507767500490bc6 100644 (file)
@@ -8,4 +8,6 @@ and querying for lower- and upper- neighbors are illustrated::
     n2.add_neighbor(n5)
     print n2.higher_neighbors()
 
+.. autosource::
+
 """
\ No newline at end of file
index 09519a679b3c811874c41e9befb37592ce19339d..eb3e843ca3dbc3c68d6ee2a8014db49ff90c1d5b 100644 (file)
@@ -1,4 +1,6 @@
 """Working examples of single-table, joined-table, and concrete-table
 inheritance as described in :ref:`datamapping_inheritance`.
 
+.. autosource::
+
 """
\ No newline at end of file
index b05afa5ea7a78a31b894c1e08516e81d002ed50b..f9bdc81b4f3714b643a9aa345aa6023d2d8eab23 100644 (file)
@@ -1,3 +1,5 @@
+"""Concrete (table-per-class) inheritance example."""
+
 from sqlalchemy import create_engine, MetaData, Table, Column, Integer, \
     String
 from sqlalchemy.orm import mapper, sessionmaker, polymorphic_union
index 8283ef05d99469320aebc18010ce20324d05bd08..6e0205e04e5e3dc306cf02e6ede58206d5e0fc63 100644 (file)
@@ -1,4 +1,4 @@
-"""this example illustrates a polymorphic load of two classes"""
+"""Joined-table (table-per-subclass) inheritance example."""
 
 from sqlalchemy import Table, Column, Integer, String, \
     ForeignKey, create_engine, inspect, or_
index b445f74a6fc0a1b45f1cf9ab65d8073228232dbb..22a6fe027d350f4ff22938eff2c460e0d60d9710 100644 (file)
@@ -1,3 +1,5 @@
+"""Single-table inheritance example."""
+
 from sqlalchemy import MetaData, Table, Column, Integer, String, \
     ForeignKey, create_engine
 from sqlalchemy.orm import mapper, relationship, sessionmaker
index 4098cd53a4d9bcb2254c9ba674e362a4fbfb3d90..432d9196f2661cf1f3ba97a211baa1edb82324cf 100644 (file)
@@ -9,4 +9,6 @@ objects is very large, including:
   ``passive_deletes=True`` to greatly improve the performance of
   related collection deletion.
 
+.. autosource::
+
 """
index 1a97b9aef34ca77ebbbcca32fa96d40ebe986835..3e73bb13e921e9fd6cdcde7e068e29067940547c 100644 (file)
@@ -1,4 +1,6 @@
 """ Illustrates a rudimentary way to implement the "nested sets"
 pattern for hierarchical data using the SQLAlchemy ORM.
 
+.. autosource::
+
 """
\ No newline at end of file
index cec5ad48a322962ca4d4e9b8338a19b11b54d65b..250d9ce876ea58bfa6bdc843cec5f51183179e8e 100644 (file)
@@ -33,5 +33,7 @@ E.g.::
 
     print session.query(Road).filter(Road.road_geom.intersects(r1.road_geom)).all()
 
+.. autosource::
+
 """
 
index dacc815f9b7b6cd447eb8e1dba5bead68152919b..59d26a2175b3acda97ea30ac9bdec61ee812440e 100644 (file)
@@ -27,4 +27,6 @@ is a simple method of assigning objects to different tables (and potentially
 database nodes) in an explicit way - described on the wiki at
 `EntityName <http://www.sqlalchemy.org/trac/wiki/UsageRecipes/EntityName>`_.
 
+.. autosource::
+
 """
index 4621fae3b38544fdc195c6360c5595b470a110a6..a2a6a1813c04b45aa8aef6c4fb9705db0025de6a 100644 (file)
@@ -57,4 +57,6 @@ can be applied::
 
     SomeHistoryClass = SomeClass.__history_mapper__.class_
 
+.. autosource::
+
 """
\ No newline at end of file
index 5b0f1920fc1ecd5d7f96963a6196b8285a501c0b..8cb52343434800c7749eb34a4d54d83ce2da5f4d 100644 (file)
@@ -1,3 +1,5 @@
+"""Versioned mixin class and other utilities."""
+
 from sqlalchemy.ext.declarative import declared_attr
 from sqlalchemy.orm import mapper, class_mapper, attributes, object_mapper
 from sqlalchemy.orm.exc import UnmappedClassError, UnmappedColumnError
index ca70c9ac017b4ca9691f2db739bac4cb0f6f6c1b..906280555238c6f5faf4a2fc4b46e29c299352d5 100644 (file)
@@ -1,3 +1,5 @@
+"""Unit tests illustrating usage of the ``history_meta.py`` module functions."""
+
 from unittest import TestCase
 from sqlalchemy.ext.declarative import declarative_base
 from .history_meta import Versioned, versioned_session
index 6073da91c99f2d479e8ad1afd7c6b0cdcec12cc2..0b69f32ea5c01ba3d9f2abcce0912f4d2dcae927 100644 (file)
@@ -29,5 +29,6 @@ Example::
                 AnimalFact.value == True))))
     print 'weasel-like animals', q.all()
 
+.. autosource::
 
 """
\ No newline at end of file