summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2011-01-02 14:23:42 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2011-01-02 14:23:42 -0500
commit350aed3fdb9f1e73e69655e53f44ca6a91c196da (patch)
tree3d2a128667b5f6ca6d0b4e1f4865fc98aac6b60b /examples
parent71f92436bdc86f30e2c21d8f5244733601e8c39e (diff)
downloadsqlalchemy-350aed3fdb9f1e73e69655e53f44ca6a91c196da.tar.gz
- whitespace removal bonanza
Diffstat (limited to 'examples')
-rw-r--r--examples/adjacency_list/adjacency_list.py18
-rw-r--r--examples/association/basic_association.py4
-rw-r--r--examples/beaker_caching/__init__.py10
-rw-r--r--examples/beaker_caching/advanced.py12
-rw-r--r--examples/beaker_caching/caching_query.py72
-rw-r--r--examples/beaker_caching/environment.py4
-rw-r--r--examples/beaker_caching/fixture_data.py8
-rw-r--r--examples/beaker_caching/local_session_caching.py30
-rw-r--r--examples/beaker_caching/model.py22
-rw-r--r--examples/custom_attributes/custom_management.py2
-rw-r--r--examples/custom_attributes/listen_for_events.py16
-rw-r--r--examples/dynamic_dict/dynamic_dict.py12
-rw-r--r--examples/elementtree/__init__.py6
-rw-r--r--examples/elementtree/optimized_al.py18
-rw-r--r--examples/elementtree/pickle.py6
-rw-r--r--examples/graphs/directed_graph.py14
-rw-r--r--examples/inheritance/concrete.py4
-rw-r--r--examples/inheritance/polymorph.py6
-rw-r--r--examples/large_collection/large_collection.py18
-rw-r--r--examples/nested_sets/nested_sets.py14
-rw-r--r--examples/poly_assoc/poly_assoc_generic.py4
-rw-r--r--examples/postgis/__init__.py8
-rw-r--r--examples/postgis/postgis.py90
-rw-r--r--examples/sharding/attribute_shard.py28
-rw-r--r--examples/versioning/__init__.py6
-rw-r--r--examples/versioning/history_meta.py42
-rw-r--r--examples/versioning/test_versioning.py100
-rw-r--r--examples/vertical/__init__.py2
28 files changed, 288 insertions, 288 deletions
diff --git a/examples/adjacency_list/adjacency_list.py b/examples/adjacency_list/adjacency_list.py
index 624239869..bac43f097 100644
--- a/examples/adjacency_list/adjacency_list.py
+++ b/examples/adjacency_list/adjacency_list.py
@@ -1,9 +1,9 @@
from sqlalchemy import MetaData, Table, Column, Sequence, ForeignKey,\
Integer, String, create_engine
-
+
from sqlalchemy.orm import sessionmaker, mapper, relationship, backref,\
joinedload_all
-
+
from sqlalchemy.orm.collections import attribute_mapped_collection
metadata = MetaData()
@@ -18,38 +18,38 @@ class TreeNode(object):
def __init__(self, name, parent=None):
self.name = name
self.parent = parent
-
+
def append(self, nodename):
self.children[nodename] = TreeNode(nodename, parent=self)
-
+
def __repr__(self):
return "TreeNode(name=%r, id=%r, parent_id=%r)" % (
self.name,
self.id,
self.parent_id
)
-
+
def dump_tree(node, indent=0):
-
+
return " " * indent + repr(node) + \
"\n" + \
"".join([
dump_tree(c, indent +1)
for c in node.children.values()]
)
-
+
mapper(TreeNode, tree_table, properties={
'children': relationship(TreeNode,
# cascade deletions
cascade="all",
-
+
# many to one + adjacency list - remote_side
# is required to reference the 'remote'
# column in the join condition.
backref=backref("parent", remote_side=tree_table.c.id),
-
+
# children will be represented as a dictionary
# on the "name" attribute.
collection_class=attribute_mapped_collection('name'),
diff --git a/examples/association/basic_association.py b/examples/association/basic_association.py
index d3d764167..19b304f9a 100644
--- a/examples/association/basic_association.py
+++ b/examples/association/basic_association.py
@@ -60,7 +60,7 @@ class OrderItem(object):
def __init__(self, item, price=None):
self.item = item
self.price = price or item.price
-
+
mapper(Order, orders, properties={
'order_items': relationship(OrderItem, cascade="all, delete-orphan",
backref='order')
@@ -82,7 +82,7 @@ session.commit()
# function to return items from the DB
def item(name):
return session.query(Item).filter_by(description=name).one()
-
+
# create an order
order = Order('john smith')
diff --git a/examples/beaker_caching/__init__.py b/examples/beaker_caching/__init__.py
index d7e97efea..cc9f71d8b 100644
--- a/examples/beaker_caching/__init__.py
+++ b/examples/beaker_caching/__init__.py
@@ -16,17 +16,17 @@ In this demo, the following techniques are illustrated:
deep within an object graph when lazy loads occur.
E.g.::
-
+
# query for Person objects, specifying cache
q = Session.query(Person).options(FromCache("default", "all_people"))
-
+
# specify that each Person's "addresses" collection comes from
# cache too
q = q.options(RelationshipCache("default", "by_person", Person.addresses))
-
+
# query
print q.all()
-
+
To run, both SQLAlchemy and Beaker (1.4 or greater) must be
installed or on the current PYTHONPATH. The demo will create a local
directory for datafiles, insert initial data, and run. Running the
@@ -53,7 +53,7 @@ Listing of files:
bootstrap fixture data if necessary.
caching_query.py - Represent functions and classes
- which allow the usage of Beaker caching with SQLAlchemy.
+ which allow the usage of Beaker caching with SQLAlchemy.
Introduces a query option called FromCache.
model.py - The datamodel, which represents Person that has multiple
diff --git a/examples/beaker_caching/advanced.py b/examples/beaker_caching/advanced.py
index 113060033..c16e02f33 100644
--- a/examples/beaker_caching/advanced.py
+++ b/examples/beaker_caching/advanced.py
@@ -13,13 +13,13 @@ from sqlalchemy.orm import joinedload
def load_name_range(start, end, invalidate=False):
"""Load Person objects on a range of names.
-
+
start/end are integers, range is then
"person <start>" - "person <end>".
-
+
The cache option we set up is called "name_range", indicating
a range of names for the Person class.
-
+
The `Person.addresses` collections are also cached. Its basically
another level of tuning here, as that particular cache option
can be transparently replaced with joinedload(Person.addresses).
@@ -36,17 +36,17 @@ def load_name_range(start, end, invalidate=False):
# have the "addresses" collection cached separately
# each lazyload of Person.addresses loads from cache.
q = q.options(RelationshipCache("default", "by_person", Person.addresses))
-
+
# alternatively, eagerly load the "addresses" collection, so that they'd
# be cached together. This issues a bigger SQL statement and caches
# a single, larger value in the cache per person rather than two
# separate ones.
#q = q.options(joinedload(Person.addresses))
-
+
# if requested, invalidate the cache on current criterion.
if invalidate:
q.invalidate()
-
+
return q.all()
print "two through twelve, possibly from cache:\n"
diff --git a/examples/beaker_caching/caching_query.py b/examples/beaker_caching/caching_query.py
index d9ec1576e..4af812500 100644
--- a/examples/beaker_caching/caching_query.py
+++ b/examples/beaker_caching/caching_query.py
@@ -16,7 +16,7 @@ The three new concepts introduced here are:
The rest of what's here are standard SQLAlchemy and
Beaker constructs.
-
+
"""
from sqlalchemy.orm.interfaces import MapperOption
from sqlalchemy.orm.query import Query
@@ -25,10 +25,10 @@ from sqlalchemy.sql import visitors
class CachingQuery(Query):
"""A Query subclass which optionally loads full results from a Beaker
cache region.
-
+
The CachingQuery stores additional state that allows it to consult
a Beaker cache before accessing the database:
-
+
* A "region", which is a cache region argument passed to a
Beaker CacheManager, specifies a particular cache configuration
(including backend implementation, expiration times, etc.)
@@ -36,13 +36,13 @@ class CachingQuery(Query):
group of keys within the cache. A query that filters on a name
might use the name "by_name", a query that filters on a date range
to a joined table might use the name "related_date_range".
-
+
When the above state is present, a Beaker cache is retrieved.
-
+
The "namespace" name is first concatenated with
a string composed of the individual entities and columns the Query
requests, i.e. such as ``Query(User.id, User.name)``.
-
+
The Beaker cache is then loaded from the cache manager based
on the region and composed namespace. The key within the cache
itself is then constructed against the bind parameters specified
@@ -51,17 +51,17 @@ class CachingQuery(Query):
The FromCache and RelationshipCache mapper options below represent
the "public" method of configuring this state upon the CachingQuery.
-
+
"""
-
+
def __init__(self, manager, *args, **kw):
self.cache_manager = manager
Query.__init__(self, *args, **kw)
-
+
def __iter__(self):
"""override __iter__ to pull results from Beaker
if particular attributes have been configured.
-
+
Note that this approach does *not* detach the loaded objects from
the current session. If the cache backend is an in-process cache
(like "memory") and lives beyond the scope of the current session's
@@ -69,7 +69,7 @@ class CachingQuery(Query):
modified to first expunge() each loaded item from the current
session before returning the list of items, so that the items
in the cache are not the same ones in the current Session.
-
+
"""
if hasattr(self, '_cache_parameters'):
return self.get_value(createfunc=lambda: list(Query.__iter__(self)))
@@ -99,13 +99,13 @@ class CachingQuery(Query):
"""Set the value in the cache for this query."""
cache, cache_key = _get_cache_parameters(self)
- cache.put(cache_key, value)
+ cache.put(cache_key, value)
def query_callable(manager):
def query(*arg, **kw):
return CachingQuery(manager, *arg, **kw)
return query
-
+
def _get_cache_parameters(query):
"""For a query with cache_region and cache_namespace configured,
return the correspoinding Cache instance and cache key, based
@@ -116,16 +116,16 @@ def _get_cache_parameters(query):
raise ValueError("This Query does not have caching parameters configured.")
region, namespace, cache_key = query._cache_parameters
-
+
namespace = _namespace_from_query(namespace, query)
-
+
if cache_key is None:
# cache key - the value arguments from this query's parameters.
args = _params_from_query(query)
cache_key = " ".join([str(x) for x in args])
-
+
assert cache_key is not None, "Cache key was None !"
-
+
# get cache
cache = query.cache_manager.get_cache_region(namespace, region)
@@ -146,7 +146,7 @@ def _namespace_from_query(namespace, query):
return namespace
def _set_cache_parameters(query, region, namespace, cache_key):
-
+
if hasattr(query, '_cache_parameters'):
region, namespace, cache_key = query._cache_parameters
raise ValueError("This query is already configured "
@@ -154,7 +154,7 @@ def _set_cache_parameters(query, region, namespace, cache_key):
(region, namespace)
)
query._cache_parameters = region, namespace, cache_key
-
+
class FromCache(MapperOption):
"""Specifies that a Query should load results from a cache."""
@@ -162,14 +162,14 @@ class FromCache(MapperOption):
def __init__(self, region, namespace, cache_key=None):
"""Construct a new FromCache.
-
+
:param region: the cache region. Should be a
region configured in the Beaker CacheManager.
-
+
:param namespace: the cache namespace. Should
be a name uniquely describing the target Query's
lexical structure.
-
+
:param cache_key: optional. A string cache key
that will serve as the key to the query. Use this
if your query has a huge amount of parameters (such
@@ -180,10 +180,10 @@ class FromCache(MapperOption):
self.region = region
self.namespace = namespace
self.cache_key = cache_key
-
+
def process_query(self, query):
"""Process a Query during normal loading operation."""
-
+
_set_cache_parameters(query, self.region, self.namespace, self.cache_key)
class RelationshipCache(MapperOption):
@@ -194,18 +194,18 @@ class RelationshipCache(MapperOption):
def __init__(self, region, namespace, attribute):
"""Construct a new RelationshipCache.
-
+
:param region: the cache region. Should be a
region configured in the Beaker CacheManager.
-
+
:param namespace: the cache namespace. Should
be a name uniquely describing the target Query's
lexical structure.
-
+
:param attribute: A Class.attribute which
indicates a particular class relationship() whose
lazy loader should be pulled from the cache.
-
+
"""
self.region = region
self.namespace = namespace
@@ -234,11 +234,11 @@ class RelationshipCache(MapperOption):
def and_(self, option):
"""Chain another RelationshipCache option to this one.
-
+
While many RelationshipCache objects can be specified on a single
Query separately, chaining them together allows for a more efficient
lookup during load.
-
+
"""
self._relationship_options.update(option._relationship_options)
return self
@@ -246,18 +246,18 @@ class RelationshipCache(MapperOption):
def _params_from_query(query):
"""Pull the bind parameter values from a query.
-
+
This takes into account any scalar attribute bindparam set up.
-
+
E.g. params_from_query(query.filter(Cls.foo==5).filter(Cls.bar==7)))
would return [5, 7].
-
+
"""
v = []
def visit_bindparam(bind):
-
+
if bind.key in query._params:
- value = query._params[bind.key]
+ value = query._params[bind.key]
elif bind.callable:
# lazyloader may dig a callable in here, intended
# to late-evaluate params after autoflush is called.
@@ -265,7 +265,7 @@ def _params_from_query(query):
value = bind.callable()
else:
value = bind.value
-
+
v.append(value)
if query._criterion is not None:
visitors.traverse(query._criterion, {}, {'bindparam':visit_bindparam})
diff --git a/examples/beaker_caching/environment.py b/examples/beaker_caching/environment.py
index ea946606c..740c5977a 100644
--- a/examples/beaker_caching/environment.py
+++ b/examples/beaker_caching/environment.py
@@ -35,7 +35,7 @@ if not os.path.exists(root):
"Press enter to continue.\n" % root
)
os.makedirs(root)
-
+
dbfile = os.path.join(root, "beaker_demo.db")
engine = create_engine('sqlite:///%s' % dbfile, echo=True)
Session.configure(bind=engine)
@@ -50,7 +50,7 @@ cache_manager.regions['default'] ={
'type':'file',
'data_dir':root,
'expire':3600,
-
+
# set start_time to current time
# to re-cache everything
# upon application startup
diff --git a/examples/beaker_caching/fixture_data.py b/examples/beaker_caching/fixture_data.py
index 67af746e3..09f020cea 100644
--- a/examples/beaker_caching/fixture_data.py
+++ b/examples/beaker_caching/fixture_data.py
@@ -19,7 +19,7 @@ def install():
('New York', 'United States', ('10001', '10002', '10003', '10004', '10005', '10006')),
('San Francisco', 'United States', ('94102', '94103', '94104', '94105', '94107', '94108'))
]
-
+
countries = {}
all_post_codes = []
for city, country, postcodes in data:
@@ -27,12 +27,12 @@ def install():
country = countries[country]
except KeyError:
countries[country] = country = Country(country)
-
+
city = City(city, country)
pc = [PostalCode(code, city) for code in postcodes]
Session.add_all(pc)
all_post_codes.extend(pc)
-
+
for i in xrange(1, 51):
person = Person(
"person %.2d" % i,
@@ -44,6 +44,6 @@ def install():
Session.add(person)
Session.commit()
-
+
# start the demo fresh
Session.remove() \ No newline at end of file
diff --git a/examples/beaker_caching/local_session_caching.py b/examples/beaker_caching/local_session_caching.py
index cce2835f1..b63858362 100644
--- a/examples/beaker_caching/local_session_caching.py
+++ b/examples/beaker_caching/local_session_caching.py
@@ -17,7 +17,7 @@ class ScopedSessionNamespace(container.MemoryNamespaceManager):
When used with the query_cache system, the effect is that the objects
in the cache are the same as that within the session - the merge()
- is a formality that doesn't actually create a second instance.
+ is a formality that doesn't actually create a second instance.
This makes it safe to use for updates of data from an identity
perspective (still not ideal for deletes though).
@@ -25,25 +25,25 @@ class ScopedSessionNamespace(container.MemoryNamespaceManager):
is automatically disposed upon session.remove().
"""
-
+
def __init__(self, namespace, scoped_session, **kwargs):
"""__init__ is called by Beaker itself."""
-
+
container.NamespaceManager.__init__(self, namespace)
self.scoped_session = scoped_session
-
+
@classmethod
def create_session_container(cls, beaker_name, scoped_session):
"""Create a new session container for a given scoped_session."""
-
+
def create_namespace(namespace, **kw):
return cls(namespace, scoped_session, **kw)
cache.clsmap[beaker_name] = create_namespace
-
+
@property
def dictionary(self):
"""Return the cache dictionary used by this MemoryNamespaceManager."""
-
+
sess = self.scoped_session()
try:
nscache = sess._beaker_cache
@@ -55,35 +55,35 @@ class ScopedSessionNamespace(container.MemoryNamespaceManager):
if __name__ == '__main__':
from environment import Session, cache_manager
from caching_query import FromCache
-
+
# create a Beaker container type called "ext:local_session".
# it will reference the ScopedSession in meta.
ScopedSessionNamespace.create_session_container("ext:local_session", Session)
-
+
# set up a region based on this new container type.
cache_manager.regions['local_session'] ={'type':'ext:local_session'}
-
+
from model import Person
-
+
# query to load Person by name, with criterion
# of "person 10"
q = Session.query(Person).\
options(FromCache("local_session", "by_name")).\
filter(Person.name=="person 10")
-
+
# load from DB
person10 = q.one()
-
+
# next call, the query is cached.
person10 = q.one()
# clear out the Session. The "_beaker_cache" dictionary
# disappears with it.
Session.remove()
-
+
# query calls from DB again
person10 = q.one()
-
+
# identity is preserved - person10 is the *same* object that's
# ultimately inside the cache. So it is safe to manipulate
# the not-queried-for attributes of objects when using such a
diff --git a/examples/beaker_caching/model.py b/examples/beaker_caching/model.py
index c139d3284..629b263a7 100644
--- a/examples/beaker_caching/model.py
+++ b/examples/beaker_caching/model.py
@@ -18,7 +18,7 @@ class Country(Base):
id = Column(Integer, primary_key=True)
name = Column(String(100), nullable=False)
-
+
def __init__(self, name):
self.name = name
@@ -41,15 +41,15 @@ class PostalCode(Base):
code = Column(String(10), nullable=False)
city_id = Column(Integer, ForeignKey('city.id'), nullable=False)
city = relationship(City)
-
+
@property
def country(self):
return self.city.country
-
+
def __init__(self, code, city):
self.code = code
self.city = city
-
+
class Address(Base):
__tablename__ = 'address'
@@ -58,21 +58,21 @@ class Address(Base):
street = Column(String(200), nullable=False)
postal_code_id = Column(Integer, ForeignKey('postal_code.id'))
postal_code = relationship(PostalCode)
-
+
@property
def city(self):
return self.postal_code.city
-
+
@property
def country(self):
return self.postal_code.country
-
+
def __str__(self):
return "%s\t"\
"%s, %s\t"\
"%s" % (self.street, self.city.name,
self.postal_code.code, self.country.name)
-
+
class Person(Base):
__tablename__ = 'person'
@@ -86,13 +86,13 @@ class Person(Base):
def __str__(self):
return self.name
-
+
def __repr__(self):
return "Person(name=%r)" % self.name
-
+
def format_full(self):
return "\t".join([str(x) for x in [self] + list(self.addresses)])
-
+
# Caching options. A set of three RelationshipCache options
# which can be applied to Query(), causing the "lazy load"
# of these attributes to be loaded from cache.
diff --git a/examples/custom_attributes/custom_management.py b/examples/custom_attributes/custom_management.py
index 2e2689140..644d512cf 100644
--- a/examples/custom_attributes/custom_management.py
+++ b/examples/custom_attributes/custom_management.py
@@ -87,7 +87,7 @@ class MyClass(object):
class MyCollectionAdapter(object):
"""An wholly alternative instrumentation implementation."""
-
+
def __init__(self, key, state, collection):
self.key = key
self.state = state
diff --git a/examples/custom_attributes/listen_for_events.py b/examples/custom_attributes/listen_for_events.py
index 2899f7fb1..80a33c0d8 100644
--- a/examples/custom_attributes/listen_for_events.py
+++ b/examples/custom_attributes/listen_for_events.py
@@ -28,21 +28,21 @@ if __name__ == '__main__':
from sqlalchemy.ext.declarative import declarative_base
class Base(object):
-
+
def receive_change_event(self, verb, key, value, oldvalue):
s = "Value '%s' %s on attribute '%s', " % (value, verb, key)
if oldvalue:
s += "which replaced the value '%s', " % oldvalue
s += "on object %s" % self
print s
-
+
Base = declarative_base(cls=Base)
event.listen(Base, 'attribute_instrument', configure_listener)
class MyMappedClass(Base):
__tablename__ = "mytable"
-
+
id = Column(Integer, primary_key=True)
data = Column(String(50))
related_id = Column(Integer, ForeignKey("related.id"))
@@ -50,7 +50,7 @@ if __name__ == '__main__':
def __str__(self):
return "MyMappedClass(data=%r)" % self.data
-
+
class Related(Base):
__tablename__ = "related"
@@ -59,12 +59,12 @@ if __name__ == '__main__':
def __str__(self):
return "Related(data=%r)" % self.data
-
+
# classes are instrumented. Demonstrate the events !
-
+
m1 = MyMappedClass(data='m1', related=Related(data='r1'))
m1.data = 'm1mod'
m1.related.mapped.append(MyMappedClass(data='m2'))
del m1.data
-
-
+
+
diff --git a/examples/dynamic_dict/dynamic_dict.py b/examples/dynamic_dict/dynamic_dict.py
index 8d15fce0b..725d65619 100644
--- a/examples/dynamic_dict/dynamic_dict.py
+++ b/examples/dynamic_dict/dynamic_dict.py
@@ -4,15 +4,15 @@ class ProxyDict(object):
self.collection_name = collection_name
self.childclass = childclass
self.keyname = keyname
-
+
@property
def collection(self):
return getattr(self.parent, self.collection_name)
-
+
def keys(self):
descriptor = getattr(self.childclass, self.keyname)
return [x[0] for x in self.collection.values(descriptor)]
-
+
def __getitem__(self, key):
x = self.collection.filter_by(**{self.keyname:key}).first()
if x:
@@ -40,11 +40,11 @@ class Parent(Base):
id = Column(Integer, primary_key=True)
name = Column(String(50))
_collection = relationship("Child", lazy="dynamic", cascade="all, delete-orphan")
-
+
@property
def child_map(self):
return ProxyDict(self, '_collection', Child, 'key')
-
+
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
@@ -53,7 +53,7 @@ class Child(Base):
def __repr__(self):
return "Child(key=%r)" % self.key
-
+
Base.metadata.create_all()
sess = sessionmaker()()
diff --git a/examples/elementtree/__init__.py b/examples/elementtree/__init__.py
index 33805c0cb..8d47f4ace 100644
--- a/examples/elementtree/__init__.py
+++ b/examples/elementtree/__init__.py
@@ -21,15 +21,15 @@ In order of complexity:
the load in a non-recursive fashion and is much more efficient.
E.g.::
-
+
# parse an XML file and persist in the database
doc = ElementTree.parse("test.xml")
session.add(Document(file, doc))
session.commit()
-
+
# locate documents with a certain path/attribute structure
for document in find_document('/somefile/header/field2[@attr=foo]'):
# dump the XML
print document
-
+
""" \ No newline at end of file
diff --git a/examples/elementtree/optimized_al.py b/examples/elementtree/optimized_al.py
index d6110a132..102f6c373 100644
--- a/examples/elementtree/optimized_al.py
+++ b/examples/elementtree/optimized_al.py
@@ -18,8 +18,8 @@ e = create_engine('sqlite://', echo=True)
meta = MetaData()
####################### PART II - Table Metadata #############################
-
-# stores a top level record of an XML document.
+
+# stores a top level record of an XML document.
documents = Table('documents', meta,
Column('document_id', Integer, primary_key=True),
Column('filename', String(30), unique=True),
@@ -48,12 +48,12 @@ meta.create_all(e)
########################### PART III - Model #################################
# our document class. contains a string name,
-# and the ElementTree root element.
+# and the ElementTree root element.
class Document(object):
def __init__(self, name, element):
self.filename = name
self.element = element
-
+
def __str__(self):
buf = StringIO.StringIO()
self.element.write(buf)
@@ -101,10 +101,10 @@ class ElementTreeMarshal(object):
def __get__(self, document, owner):
if document is None:
return self
-
+
if hasattr(document, '_element'):
return document._element
-
+
nodes = {}
root = None
for node in document._nodes:
@@ -120,10 +120,10 @@ class ElementTreeMarshal(object):
elem.attrib[attr.name] = attr.value
elem.text = node.text
elem.tail = node.tail
-
+
document._element = ElementTree.ElementTree(root)
return document._element
-
+
def __set__(self, document, element):
def traverse(node):
n = _Node()
@@ -137,7 +137,7 @@ class ElementTreeMarshal(object):
traverse(element.getroot())
document._element = element
-
+
def __delete__(self, document):
del document._element
document._nodes = []
diff --git a/examples/elementtree/pickle.py b/examples/elementtree/pickle.py
index 5e53e6798..28bee4672 100644
--- a/examples/elementtree/pickle.py
+++ b/examples/elementtree/pickle.py
@@ -22,7 +22,7 @@ meta = MetaData()
def are_elements_equal(x, y):
return x == y
-# stores a top level record of an XML document.
+# stores a top level record of an XML document.
# the "element" column will store the ElementTree document as a BLOB.
documents = Table('documents', meta,
Column('document_id', Integer, primary_key=True),
@@ -33,7 +33,7 @@ documents = Table('documents', meta,
meta.create_all(e)
# our document class. contains a string name,
-# and the ElementTree root element.
+# and the ElementTree root element.
class Document(object):
def __init__(self, name, element):
self.filename = name
@@ -47,7 +47,7 @@ mapper(Document, documents)
# get ElementTree document
filename = os.path.join(os.path.dirname(__file__), "test.xml")
doc = ElementTree.parse(filename)
-
+
# save to DB
session = Session(e)
session.add(Document("test.xml", doc))
diff --git a/examples/graphs/directed_graph.py b/examples/graphs/directed_graph.py
index 6052c68bc..3ba602f00 100644
--- a/examples/graphs/directed_graph.py
+++ b/examples/graphs/directed_graph.py
@@ -9,20 +9,20 @@ Base = declarative_base()
class Node(Base):
__tablename__ = 'node'
-
+
node_id = Column(Integer, primary_key=True)
def __init__(self, id):
self.node_id = id
-
+
def add_neighbors(self, *nodes):
for node in nodes:
Edge(self, node)
return self
-
+
def higher_neighbors(self):
return [x.higher_node for x in self.lower_edges]
-
+
def lower_neighbors(self):
return [x.lower_node for x in self.higher_edges]
@@ -32,7 +32,7 @@ class Edge(Base):
lower_id = Column(Integer,
ForeignKey('node.node_id'),
primary_key=True)
-
+
higher_id = Column(Integer,
ForeignKey('node.node_id'),
primary_key=True)
@@ -43,7 +43,7 @@ class Edge(Base):
higher_node = relationship(Node,
primaryjoin=higher_id==Node.node_id,
backref='higher_edges')
-
+
# here we have lower.node_id <= higher.node_id
def __init__(self, n1, n2):
if n1.node_id < n2.node_id:
@@ -62,7 +62,7 @@ session = sessionmaker(engine)()
# n1 -> n2 -> n5
# -> n7
# -> n3 -> n6
-
+
n1 = Node(1)
n2 = Node(2)
n3 = Node(3)
diff --git a/examples/inheritance/concrete.py b/examples/inheritance/concrete.py
index eb832a55d..84fc79cd5 100644
--- a/examples/inheritance/concrete.py
+++ b/examples/inheritance/concrete.py
@@ -25,7 +25,7 @@ class Employee(object):
self.name = name
def __repr__(self):
return self.__class__.__name__ + " " + self.name
-
+
class Manager(Employee):
def __init__(self, name, manager_data):
self.name = name
@@ -33,7 +33,7 @@ class Manager(Employee):
def __repr__(self):
return self.__class__.__name__ + " " + \
self.name + " " + self.manager_data
-
+
class Engineer(Employee):
def __init__(self, name, engineer_info):
self.name = name
diff --git a/examples/inheritance/polymorph.py b/examples/inheritance/polymorph.py
index 87c2de10e..316671bed 100644
--- a/examples/inheritance/polymorph.py
+++ b/examples/inheritance/polymorph.py
@@ -20,7 +20,7 @@ people = Table('people', metadata,
Column('company_id', Integer, ForeignKey('companies.company_id')),
Column('name', String(50)),
Column('type', String(30)))
-
+
engineers = Table('engineers', metadata,
Column('person_id', Integer, ForeignKey('people.person_id'),
primary_key=True),
@@ -28,14 +28,14 @@ engineers = Table('engineers', metadata,
Column('engineer_name', String(50)),
Column('primary_language', String(50)),
)
-
+
managers = Table('managers', metadata,
Column('person_id', Integer, ForeignKey('people.person_id'),
primary_key=True),
Column('status', String(30)),
Column('manager_name', String(50))
)
-
+
# create our classes. The Engineer and Manager classes extend from Person.
class Person(object):
def __init__(self, **kwargs):
diff --git a/examples/large_collection/large_collection.py b/examples/large_collection/large_collection.py
index b8ade43ba..a251861d6 100644
--- a/examples/large_collection/large_collection.py
+++ b/examples/large_collection/large_collection.py
@@ -10,18 +10,18 @@ org_table = Table('organizations', meta,
Column('org_id', Integer, primary_key=True),
Column('org_name', String(50), nullable=False, key='name'),
mysql_engine='InnoDB')
-
+
member_table = Table('members', meta,
Column('member_id', Integer, primary_key=True),
Column('member_name', String(50), nullable=False, key='name'),
Column('org_id', Integer, ForeignKey('organizations.org_id', ondelete="CASCADE")),
mysql_engine='InnoDB')
-
-
+
+
class Organization(object):
def __init__(self, name):
self.name = name
-
+
class Member(object):
def __init__(self, name):
self.name = name
@@ -31,11 +31,11 @@ mapper(Organization, org_table, properties = {
# Organization.members will be a Query object - no loading
# of the entire collection occurs unless requested
lazy="dynamic",
-
+
# Member objects "belong" to their parent, are deleted when
# removed from the collection
cascade="all, delete-orphan",
-
+
# "delete, delete-orphan" cascade does not load in objects on delete,
# allows ON DELETE CASCADE to handle it.
# this only works with a database that supports ON DELETE CASCADE -
@@ -49,7 +49,7 @@ mapper(Member, member_table)
if __name__ == '__main__':
engine = create_engine("mysql://scott:tiger@localhost/test", echo=True)
meta.create_all(engine)
-
+
# expire_on_commit=False means the session contents
# will not get invalidated after commit.
sess = sessionmaker(engine, expire_on_commit=False)()
@@ -86,9 +86,9 @@ if __name__ == '__main__':
sess.delete(org)
print "-------------------------\nflush three - delete org, delete members in one statement\n"
sess.commit()
-
+
print "-------------------------\nno Member rows should remain:\n"
print sess.query(Member).count()
-
+
print "------------------------\ndone. dropping tables."
meta.drop_all(engine) \ No newline at end of file
diff --git a/examples/nested_sets/nested_sets.py b/examples/nested_sets/nested_sets.py
index fbb481759..55d734d4e 100644
--- a/examples/nested_sets/nested_sets.py
+++ b/examples/nested_sets/nested_sets.py
@@ -22,7 +22,7 @@ class NestedSetExtension(MapperExtension):
right_most_sibling = connection.scalar(
select([personnel.c.rgt]).where(personnel.c.emp==instance.parent.emp)
)
-
+
connection.execute(
personnel.update(personnel.c.rgt>=right_most_sibling).values(
lft = case(
@@ -41,21 +41,21 @@ class NestedSetExtension(MapperExtension):
# before_update() would be needed to support moving of nodes
# after_delete() would be needed to support removal of nodes.
# [ticket:1172] needs to be implemented for deletion to work as well.
-
+
class Employee(Base):
__tablename__ = 'personnel'
__mapper_args__ = {
'extension':NestedSetExtension(),
'batch':False # allows extension to fire for each instance before going to the next.
}
-
+
parent = None
-
+
emp = Column(String, primary_key=True)
-
+
left = Column("lft", Integer, nullable=False)
right = Column("rgt", Integer, nullable=False)
-
+
def __repr__(self):
return "Employee(%s, %d, %d)" % (self.emp, self.left, self.right)
@@ -100,4 +100,4 @@ for indentation, employee in session.query(func.count(Employee.emp).label('inden
group_by(ealias.emp).\
order_by(ealias.left):
print " " * indentation + str(employee)
-
+
diff --git a/examples/poly_assoc/poly_assoc_generic.py b/examples/poly_assoc/poly_assoc_generic.py
index aaa182df0..b674e1eb8 100644
--- a/examples/poly_assoc/poly_assoc_generic.py
+++ b/examples/poly_assoc/poly_assoc_generic.py
@@ -53,12 +53,12 @@ def association(cls, table):
setattr(self, attr_name, GenericAssoc(table.name))
getattr(self, attr_name).targets = [value]
setattr(cls, name, property(get, set))
-
+
@property
def member(self):
return getattr(self.association,
'_backref_%s' % self.association.type)
-
+
setattr(cls, 'member', member)
mapper(GenericAssoc, association_table, properties={
diff --git a/examples/postgis/__init__.py b/examples/postgis/__init__.py
index 1a351f7ae..3eb4ed3bc 100644
--- a/examples/postgis/__init__.py
+++ b/examples/postgis/__init__.py
@@ -7,20 +7,20 @@ The example illustrates:
* a DDL extension which allows CREATE/DROP to work in
conjunction with AddGeometryColumn/DropGeometryColumn
-
+
* a Geometry type, as well as a few subtypes, which
convert result row values to a GIS-aware object,
and also integrates with the DDL extension.
* a GIS-aware object which stores a raw geometry value
and provides a factory for functions such as AsText().
-
+
* an ORM comparator which can override standard column
methods on mapped objects to produce GIS operators.
-
+
* an attribute event listener that intercepts strings
and converts to GeomFromText().
-
+
* a standalone operator example.
The implementation is limited to only public, well known
diff --git a/examples/postgis/postgis.py b/examples/postgis/postgis.py
index d3f728293..68f5ecae9 100644
--- a/examples/postgis/postgis.py
+++ b/examples/postgis/postgis.py
@@ -24,18 +24,18 @@ class GisElement(object):
class PersistentGisElement(GisElement):
"""Represents a Geometry value as loaded from the database."""
-
+
def __init__(self, desc):
self.desc = desc
class TextualGisElement(GisElement, expression.Function):
"""Represents a Geometry value as expressed within application code; i.e. in wkt format.
-
+
Extends expression.Function so that the value is interpreted as
GeomFromText(value) in a SQL expression context.
-
+
"""
-
+
def __init__(self, desc, srid=-1):
assert isinstance(desc, basestring)
self.desc = desc
@@ -46,17 +46,17 @@ class TextualGisElement(GisElement, expression.Function):
class Geometry(TypeEngine):
"""Base PostGIS Geometry column type.
-
+
Converts bind/result values to/from a PersistentGisElement.
-
+
"""
-
+
name = 'GEOMETRY'
-
+
def __init__(self, dimension=None, srid=-1):
self.dimension = dimension
self.srid = srid
-
+
def bind_processor(self, dialect):
def process(value):
if value is not None:
@@ -64,7 +64,7 @@ class Geometry(TypeEngine):
else:
return value
return process
-
+
def result_processor(self, dialect, coltype):
def process(value):
if value is not None:
@@ -78,10 +78,10 @@ class Geometry(TypeEngine):
class Point(Geometry):
name = 'POINT'
-
+
class Curve(Geometry):
name = 'CURVE'
-
+
class LineString(Curve):
name = 'LINESTRING'
@@ -93,36 +93,36 @@ class LineString(Curve):
class GISDDL(object):
"""A DDL extension which integrates SQLAlchemy table create/drop
methods with PostGis' AddGeometryColumn/DropGeometryColumn functions.
-
+
Usage::
-
+
sometable = Table('sometable', metadata, ...)
-
+
GISDDL(sometable)
sometable.create()
-
+
"""
-
+
def __init__(self, table):
for event in ('before-create', 'after-create', 'before-drop', 'after-drop'):
table.ddl_listeners[event].append(self)
self._stack = []
-
+
def __call__(self, event, table, bind):
if event in ('before-create', 'before-drop'):
regular_cols = [c for c in table.c if not isinstance(c.type, Geometry)]
gis_cols = set(table.c).difference(regular_cols)
self._stack.append(table.c)
table._columns = expression.ColumnCollection(*regular_cols)
-
+
if event == 'before-drop':
for c in gis_cols:
bind.execute(select([func.DropGeometryColumn('public', table.name, c.name)], autocommit=True))
-
+
elif event == 'after-create':
table._columns = self._stack.pop()
-
+
for c in table.c:
if isinstance(c.type, Geometry):
bind.execute(select([func.AddGeometryColumn(table.name, c.name, c.type.srid, c.type.name, c.type.dimension)], autocommit=True))
@@ -133,7 +133,7 @@ class GISDDL(object):
def _to_postgis(value):
"""Interpret a value as a GIS-compatible construct."""
-
+
if hasattr(value, '__clause_element__'):
return value.__clause_element__()
elif isinstance(value, (expression.ClauseElement, GisElement)):
@@ -149,18 +149,18 @@ def _to_postgis(value):
class GisAttribute(AttributeExtension):
"""Intercepts 'set' events on a mapped instance attribute and
converts the incoming value to a GIS expression.
-
+
"""
-
+
def set(self, state, value, oldvalue, initiator):
return _to_postgis(value)
-
+
class GisComparator(ColumnProperty.ColumnComparator):
"""Intercepts standard Column operators on mapped class attributes
and overrides their behavior.
-
+
"""
-
+
# override the __eq__() operator
def __eq__(self, other):
return self.__clause_element__().op('~=')(_to_postgis(other))
@@ -168,19 +168,19 @@ class GisComparator(ColumnProperty.ColumnComparator):
# add a custom operator
def intersects(self, other):
return self.__clause_element__().op('&&')(_to_postgis(other))
-
+
# any number of GIS operators can be overridden/added here
# using the techniques above.
-
+
def GISColumn(*args, **kw):
"""Define a declarative column property with GIS behavior.
-
+
This just produces orm.column_property() with the appropriate
extension and comparator_factory arguments. The given arguments
are passed through to Column. The declarative module extracts
the Column for inclusion in the mapped table.
-
+
"""
return column_property(
Column(*args, **kw),
@@ -201,21 +201,21 @@ if __name__ == '__main__':
class Road(Base):
__tablename__ = 'roads'
-
+
road_id = Column(Integer, primary_key=True)
road_name = Column(String)
road_geom = GISColumn(Geometry(2))
-
+
# enable the DDL extension, which allows CREATE/DROP operations
# to work correctly. This is not needed if working with externally
- # defined tables.
+ # defined tables.
GISDDL(Road.__table__)
metadata.drop_all()
metadata.create_all()
session = sessionmaker(bind=engine)()
-
+
# Add objects. We can use strings...
session.add_all([
Road(road_name='Jeff Rd', road_geom='LINESTRING(191232 243118,191108 243242)'),
@@ -224,30 +224,30 @@ if __name__ == '__main__':
Road(road_name='Graeme Ave', road_geom='LINESTRING(189412 252431,189631 259122)'),
Road(road_name='Phil Tce', road_geom='LINESTRING(190131 224148,190871 228134)'),
])
-
+
# or use an explicit TextualGisElement (similar to saying func.GeomFromText())
r = Road(road_name='Dave Cres', road_geom=TextualGisElement('LINESTRING(198231 263418,198213 268322)', -1))
session.add(r)
-
+
# pre flush, the TextualGisElement represents the string we sent.
assert str(r.road_geom) == 'LINESTRING(198231 263418,198213 268322)'
assert session.scalar(r.road_geom.wkt) == 'LINESTRING(198231 263418,198213 268322)'
-
+
session.commit()
# after flush and/or commit, all the TextualGisElements become PersistentGisElements.
assert str(r.road_geom) == "01020000000200000000000000B832084100000000E813104100000000283208410000000088601041"
-
+
r1 = session.query(Road).filter(Road.road_name=='Graeme Ave').one()
-
+
# illustrate the overridden __eq__() operator.
-
+
# strings come in as TextualGisElements
r2 = session.query(Road).filter(Road.road_geom == 'LINESTRING(189412 252431,189631 259122)').one()
-
+
# PersistentGisElements work directly
r3 = session.query(Road).filter(Road.road_geom == r1.road_geom).one()
-
+
assert r1 is r2 is r3
# illustrate the "intersects" operator
@@ -256,7 +256,7 @@ if __name__ == '__main__':
# illustrate usage of the "wkt" accessor. this requires a DB
# execution to call the AsText() function so we keep this explicit.
assert session.scalar(r1.road_geom.wkt) == 'LINESTRING(189412 252431,189631 259122)'
-
+
session.rollback()
-
+
metadata.drop_all()
diff --git a/examples/sharding/attribute_shard.py b/examples/sharding/attribute_shard.py
index 6b4813dd3..9f1157c32 100644
--- a/examples/sharding/attribute_shard.py
+++ b/examples/sharding/attribute_shard.py
@@ -74,12 +74,12 @@ weather_reports = Table("weather_reports", meta,
for db in (db1, db2, db3, db4):
meta.drop_all(db)
meta.create_all(db)
-
+
# establish initial "id" in db1
db1.execute(ids.insert(), nextid=1)
-# step 5. define sharding functions.
+# step 5. define sharding functions.
# we'll use a straight mapping of a particular set of "country"
# attributes to shard id.
@@ -92,12 +92,12 @@ shard_lookup = {
def shard_chooser(mapper, instance, clause=None):
"""shard chooser.
-
+
looks at the given instance and returns a shard id
note that we need to define conditions for
the WeatherLocation class, as well as our secondary Report class which will
point back to its WeatherLocation via its 'location' attribute.
-
+
"""
if isinstance(instance, WeatherLocation):
return shard_lookup[instance.continent]
@@ -105,24 +105,24 @@ def shard_chooser(mapper, instance, clause=None):
return shard_chooser(mapper, instance.location)
def id_chooser(query, ident):
- """id chooser.
-
+ """id chooser.
+
given a primary key, returns a list of shards
to search. here, we don't have any particular information from a
pk so we just return all shard ids. often, youd want to do some
kind of round-robin strategy here so that requests are evenly
distributed among DBs.
-
+
"""
return ['north_america', 'asia', 'europe', 'south_america']
def query_chooser(query):
"""query chooser.
-
+
this also returns a list of shard ids, which can
just be all of them. but here we'll search into the Query in order
to try to narrow down the list of shards to query.
-
+
"""
ids = []
@@ -140,7 +140,7 @@ def query_chooser(query):
ids.append(shard_lookup[value])
elif operator == operators.in_op:
ids.extend(shard_lookup[v] for v in value)
-
+
if len(ids) == 0:
return ['north_america', 'asia', 'europe', 'south_america']
else:
@@ -148,12 +148,12 @@ def query_chooser(query):
def _get_query_comparisons(query):
"""Search an orm.Query object for binary expressions.
-
+
Returns expressions which match a Column against one or more
literal values as a list of tuples of the form
(column, operator, values). "values" is a single value
or tuple of values depending on the operator.
-
+
"""
binds = {}
clauses = set()
@@ -216,7 +216,7 @@ create_session.configure(
query_chooser=query_chooser
)
-# step 6. mapped classes.
+# step 6. mapped classes.
class WeatherLocation(object):
def __init__(self, continent, city):
self.continent = continent
@@ -231,7 +231,7 @@ mapper(WeatherLocation, weather_locations, properties={
'reports':relationship(Report, backref='location')
})
-mapper(Report, weather_reports)
+mapper(Report, weather_reports)
# save and load objects!
diff --git a/examples/versioning/__init__.py b/examples/versioning/__init__.py
index f2f8832cf..72edcca53 100644
--- a/examples/versioning/__init__.py
+++ b/examples/versioning/__init__.py
@@ -19,13 +19,13 @@ A fragment of example usage, using declarative::
class SomeClass(Base):
__tablename__ = 'sometable'
-
+
id = Column(Integer, primary_key=True)
name = Column(String(50))
-
+
def __eq__(self, other):
assert type(other) is SomeClass and other.id == self.id
-
+
sess = Session()
sc = SomeClass(name='sc1')
sess.add(sc)
diff --git a/examples/versioning/history_meta.py b/examples/versioning/history_meta.py
index fa95733e2..2983a33e2 100644
--- a/examples/versioning/history_meta.py
+++ b/examples/versioning/history_meta.py
@@ -19,10 +19,10 @@ def _history_mapper(local_mapper):
# of the info is always loaded (currently sets it on all attributes)
for prop in local_mapper.iterate_properties:
getattr(local_mapper.class_, prop.key).impl.active_history = True
-
+
super_mapper = local_mapper.inherits
super_history_mapper = getattr(cls, '__history_mapper__', None)
-
+
polymorphic_on = None
super_fks = []
if not super_mapper or local_mapper.local_table is not super_mapper.local_table:
@@ -30,7 +30,7 @@ def _history_mapper(local_mapper):
for column in local_mapper.local_table.c:
if column.name == 'version':
continue
-
+
col = column.copy()
col.unique = False
@@ -38,16 +38,16 @@ def _history_mapper(local_mapper):
super_fks.append((col.key, list(super_history_mapper.base_mapper.local_table.primary_key)[0]))
cols.append(col)
-
+
if column is local_mapper.polymorphic_on:
polymorphic_on = col
-
+
if super_mapper:
super_fks.append(('version', super_history_mapper.base_mapper.local_table.c.version))
cols.append(Column('version', Integer, primary_key=True))
else:
cols.append(Column('version', Integer, primary_key=True))
-
+
if super_fks:
cols.append(ForeignKeyConstraint(*zip(*super_fks)))
@@ -62,13 +62,13 @@ def _history_mapper(local_mapper):
col = column.copy()
super_history_mapper.local_table.append_column(col)
table = None
-
+
if super_history_mapper:
bases = (super_history_mapper.class_,)
else:
bases = local_mapper.base_mapper.class_.__bases__
versioned_cls = type.__new__(type, "%sHistory" % cls.__name__, bases, {})
-
+
m = mapper(
versioned_cls,
table,
@@ -77,11 +77,11 @@ def _history_mapper(local_mapper):
polymorphic_identity=local_mapper.polymorphic_identity
)
cls.__history_mapper__ = m
-
+
if not super_history_mapper:
cls.version = Column('version', Integer, default=1, nullable=False)
-
-
+
+
class VersionedMeta(DeclarativeMeta):
def __init__(cls, classname, bases, dict_):
DeclarativeMeta.__init__(cls, classname, bases, dict_)
@@ -102,21 +102,21 @@ def create_version(obj, session, deleted = False):
obj_mapper = object_mapper(obj)
history_mapper = obj.__history_mapper__
history_cls = history_mapper.class_
-
+
obj_state = attributes.instance_state(obj)
-
+
attr = {}
obj_changed = False
-
+
for om, hm in zip(obj_mapper.iterate_to_root(), history_mapper.iterate_to_root()):
if hm.single:
continue
-
+
for hist_col in hm.local_table.c:
if hist_col.key == 'version':
continue
-
+
obj_col = om.local_table.c[hist_col.key]
# get the value of the
@@ -131,7 +131,7 @@ def create_version(obj, session, deleted = False):
# the "unmapped" status of the subclass column on the
# base class is a feature of the declarative module as of sqla 0.5.2.
continue
-
+
# expired object attributes and also deferred cols might not be in the
# dict. force it to load no matter what by using getattr().
if prop.key not in obj_state.dict:
@@ -148,7 +148,7 @@ def create_version(obj, session, deleted = False):
# if the attribute had no value.
attr[hist_col.key] = a[0]
obj_changed = True
-
+
if not obj_changed:
# not changed, but we have relationships. OK
# check those too
@@ -157,8 +157,8 @@ def create_version(obj, session, deleted = False):
attributes.get_history(obj, prop.key).has_changes():
obj_changed = True
break
-
- if not obj_changed and not deleted:
+
+ if not obj_changed and not deleted:
return
attr['version'] = obj.version
@@ -167,7 +167,7 @@ def create_version(obj, session, deleted = False):
setattr(hist, key, value)
session.add(hist)
obj.version += 1
-
+
class VersionedListener(SessionExtension):
def before_flush(self, session, flush_context, instances):
for obj in versioned_objects(session.dirty):
diff --git a/examples/versioning/test_versioning.py b/examples/versioning/test_versioning.py
index c9cb605cd..83d769e1e 100644
--- a/examples/versioning/test_versioning.py
+++ b/examples/versioning/test_versioning.py
@@ -8,7 +8,7 @@ from test.lib.entities import ComparableEntity
def setup():
global engine
engine = create_engine('sqlite://', echo=True)
-
+
class TestVersioning(TestBase):
def setup(self):
global Base, Session, Versioned
@@ -17,34 +17,34 @@ class TestVersioning(TestBase):
__metaclass__ = VersionedMeta
_decl_class_registry = Base._decl_class_registry
Session = sessionmaker(extension=VersionedListener())
-
+
def teardown(self):
clear_mappers()
Base.metadata.drop_all()
-
+
def create_tables(self):
Base.metadata.create_all()
-
+
def test_plain(self):
class SomeClass(Versioned, Base, ComparableEntity):
__tablename__ = 'sometable'
-
+
id = Column(Integer, primary_key=True)
name = Column(String(50))
-
+
self.create_tables()
sess = Session()
sc = SomeClass(name='sc1')
sess.add(sc)
sess.commit()
-
+
sc.name = 'sc1modified'
sess.commit()
-
+
assert sc.version == 2
-
+
SomeClassHistory = SomeClass.__history_mapper__.class_
-
+
eq_(
sess.query(SomeClassHistory).filter(SomeClassHistory.version == 1).all(),
[SomeClassHistory(version=1, name='sc1')]
@@ -61,7 +61,7 @@ class TestVersioning(TestBase):
)
assert sc.version == 3
-
+
sess.commit()
sc.name = 'temp'
@@ -76,7 +76,7 @@ class TestVersioning(TestBase):
SomeClassHistory(version=2, name='sc1modified')
]
)
-
+
sess.delete(sc)
sess.commit()
@@ -92,41 +92,41 @@ class TestVersioning(TestBase):
def test_from_null(self):
class SomeClass(Versioned, Base, ComparableEntity):
__tablename__ = 'sometable'
-
+
id = Column(Integer, primary_key=True)
name = Column(String(50))
-
+
self.create_tables()
sess = Session()
sc = SomeClass()
sess.add(sc)
sess.commit()
-
+
sc.name = 'sc1'
sess.commit()
-
+
assert sc.version == 2
def test_deferred(self):
"""test versioning of unloaded, deferred columns."""
-
+
class SomeClass(Versioned, Base, ComparableEntity):
__tablename__ = 'sometable'
id = Column(Integer, primary_key=True)
name = Column(String(50))
data = deferred(Column(String(25)))
-
+
self.create_tables()
sess = Session()
sc = SomeClass(name='sc1', data='somedata')
sess.add(sc)
sess.commit()
sess.close()
-
+
sc = sess.query(SomeClass).first()
assert 'data' not in sc.__dict__
-
+
sc.name = 'sc1modified'
sess.commit()
@@ -138,8 +138,8 @@ class TestVersioning(TestBase):
sess.query(SomeClassHistory).filter(SomeClassHistory.version == 1).all(),
[SomeClassHistory(version=1, name='sc1', data='somedata')]
)
-
-
+
+
def test_joined_inheritance(self):
class BaseClass(Versioned, Base, ComparableEntity):
__tablename__ = 'basetable'
@@ -147,9 +147,9 @@ class TestVersioning(TestBase):
id = Column(Integer, primary_key=True)
name = Column(String(50))
type = Column(String(20))
-
+
__mapper_args__ = {'polymorphic_on':type, 'polymorphic_identity':'base'}
-
+
class SubClassSeparatePk(BaseClass):
__tablename__ = 'subtable1'
@@ -175,7 +175,7 @@ class TestVersioning(TestBase):
same1 = SubClassSamePk(name='same1', subdata2='same1subdata')
sess.add_all([sep1, base1, same1])
sess.commit()
-
+
base1.name = 'base1mod'
same1.subdata2 = 'same1subdatamod'
sep1.name ='sep1mod'
@@ -189,10 +189,10 @@ class TestVersioning(TestBase):
[
SubClassSeparatePkHistory(id=1, name=u'sep1', type=u'sep', version=1),
BaseClassHistory(id=2, name=u'base1', type=u'base', version=1),
- SubClassSamePkHistory(id=3, name=u'same1', type=u'same', version=1)
+ SubClassSamePkHistory(id=3, name=u'same1', type=u'same', version=1)
]
)
-
+
same1.subdata2 = 'same1subdatamod2'
eq_(
@@ -201,7 +201,7 @@ class TestVersioning(TestBase):
SubClassSeparatePkHistory(id=1, name=u'sep1', type=u'sep', version=1),
BaseClassHistory(id=2, name=u'base1', type=u'base', version=1),
SubClassSamePkHistory(id=3, name=u'same1', type=u'same', version=1),
- SubClassSamePkHistory(id=3, name=u'same1', type=u'same', version=2)
+ SubClassSamePkHistory(id=3, name=u'same1', type=u'same', version=2)
]
)
@@ -213,7 +213,7 @@ class TestVersioning(TestBase):
BaseClassHistory(id=2, name=u'base1', type=u'base', version=1),
BaseClassHistory(id=2, name=u'base1mod', type=u'base', version=2),
SubClassSamePkHistory(id=3, name=u'same1', type=u'same', version=1),
- SubClassSamePkHistory(id=3, name=u'same1', type=u'same', version=2)
+ SubClassSamePkHistory(id=3, name=u'same1', type=u'same', version=2)
]
)
@@ -225,7 +225,7 @@ class TestVersioning(TestBase):
name = Column(String(50))
type = Column(String(50))
__mapper_args__ = {'polymorphic_on':type, 'polymorphic_identity':'base'}
-
+
class SubClass(BaseClass):
subname = Column(String(50))
@@ -236,21 +236,21 @@ class TestVersioning(TestBase):
b1 = BaseClass(name='b1')
sc = SubClass(name='s1', subname='sc1')
-
+
sess.add_all([b1, sc])
-
+
sess.commit()
-
+
b1.name='b1modified'
BaseClassHistory = BaseClass.__history_mapper__.class_
SubClassHistory = SubClass.__history_mapper__.class_
-
+
eq_(
sess.query(BaseClassHistory).order_by(BaseClassHistory.id, BaseClassHistory.version).all(),
[BaseClassHistory(id=1, name=u'b1', type=u'base', version=1)]
)
-
+
sc.name ='s1modified'
b1.name='b1modified2'
@@ -262,48 +262,48 @@ class TestVersioning(TestBase):
SubClassHistory(id=2, name=u's1', type=u'sub', version=1)
]
)
-
+
def test_unique(self):
class SomeClass(Versioned, Base, ComparableEntity):
__tablename__ = 'sometable'
-
+
id = Column(Integer, primary_key=True)
name = Column(String(50), unique=True)
data = Column(String(50))
-
+
self.create_tables()
sess = Session()
sc = SomeClass(name='sc1', data='sc1')
sess.add(sc)
sess.commit()
-
+
sc.data = 'sc1modified'
sess.commit()
-
+
assert sc.version == 2
-
+
sc.data = 'sc1modified2'
sess.commit()
-
+
assert sc.version == 3
def test_relationship(self):
class SomeRelated(Base, ComparableEntity):
__tablename__ = 'somerelated'
-
+
id = Column(Integer, primary_key=True)
class SomeClass(Versioned, Base, ComparableEntity):
__tablename__ = 'sometable'
-
+
id = Column(Integer, primary_key=True)
name = Column(String(50))
related_id = Column(Integer, ForeignKey('somerelated.id'))
related = relationship("SomeRelated")
-
+
SomeClassHistory = SomeClass.__history_mapper__.class_
-
+
self.create_tables()
sess = Session()
sc = SomeClass(name='sc1')
@@ -311,13 +311,13 @@ class TestVersioning(TestBase):
sess.commit()
assert sc.version == 1
-
+
sr1 = SomeRelated()
sc.related = sr1
sess.commit()
-
+
assert sc.version == 2
-
+
eq_(
sess.query(SomeClassHistory).filter(SomeClassHistory.version == 1).all(),
[SomeClassHistory(version=1, name='sc1', related_id=None)]
@@ -334,4 +334,4 @@ class TestVersioning(TestBase):
)
assert sc.version == 3
-
+
diff --git a/examples/vertical/__init__.py b/examples/vertical/__init__.py
index 61ba2228b..b4ce291f2 100644
--- a/examples/vertical/__init__.py
+++ b/examples/vertical/__init__.py
@@ -1,7 +1,7 @@
"""
Illustrates "vertical table" mappings.
-A "vertical table" refers to a technique where individual attributes of an object are stored as distinct rows in a table.
+A "vertical table" refers to a technique where individual attributes of an object are stored as distinct rows in a table.
The "vertical table" technique is used to persist objects which can have a varied set of attributes, at the expense of simple query control and brevity. It is commonly found in content/document management systems in order to represent user-created structures flexibly.
Two variants on the approach are given. In the second, each row references a "datatype" which contains information about the type of information stored in the attribute, such as integer, string, or date.