summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/adjacency_list/adjacency_list.py67
-rw-r--r--examples/association/basic_association.py65
-rw-r--r--examples/association/dict_of_sets_with_default.py14
-rw-r--r--examples/association/proxied_association.py68
-rw-r--r--examples/custom_attributes/__init__.py2
-rw-r--r--examples/custom_attributes/active_column_defaults.py20
-rw-r--r--examples/custom_attributes/custom_management.py65
-rw-r--r--examples/custom_attributes/listen_for_events.py20
-rw-r--r--examples/dogpile_caching/advanced.py26
-rw-r--r--examples/dogpile_caching/caching_query.py50
-rw-r--r--examples/dogpile_caching/environment.py21
-rw-r--r--examples/dogpile_caching/fixture_data.py25
-rw-r--r--examples/dogpile_caching/helloworld.py43
-rw-r--r--examples/dogpile_caching/local_session_caching.py20
-rw-r--r--examples/dogpile_caching/model.py37
-rw-r--r--examples/dogpile_caching/relationship_caching.py7
-rw-r--r--examples/dynamic_dict/__init__.py2
-rw-r--r--examples/dynamic_dict/dynamic_dict.py34
-rw-r--r--examples/elementtree/__init__.py2
-rw-r--r--examples/elementtree/adjacency_list.py150
-rw-r--r--examples/elementtree/optimized_al.py153
-rw-r--r--examples/elementtree/pickle.py26
-rw-r--r--examples/generic_associations/__init__.py2
-rw-r--r--examples/generic_associations/discriminator_on_association.py100
-rw-r--r--examples/generic_associations/generic_fk.py92
-rw-r--r--examples/generic_associations/table_per_association.py89
-rw-r--r--examples/generic_associations/table_per_related.py84
-rw-r--r--examples/graphs/__init__.py2
-rw-r--r--examples/graphs/directed_graph.py31
-rw-r--r--examples/inheritance/concrete.py142
-rw-r--r--examples/inheritance/joined.py140
-rw-r--r--examples/inheritance/single.py136
-rw-r--r--examples/join_conditions/__init__.py2
-rw-r--r--examples/join_conditions/cast.py36
-rw-r--r--examples/join_conditions/threeway.py60
-rw-r--r--examples/large_collection/large_collection.py112
-rw-r--r--examples/materialized_paths/materialized_paths.py78
-rw-r--r--examples/nested_sets/__init__.py2
-rw-r--r--examples/nested_sets/nested_sets.py108
-rw-r--r--examples/performance/__init__.py67
-rw-r--r--examples/performance/__main__.py3
-rw-r--r--examples/performance/bulk_inserts.py115
-rw-r--r--examples/performance/bulk_updates.py23
-rw-r--r--examples/performance/large_resultsets.py50
-rw-r--r--examples/performance/short_selects.py60
-rw-r--r--examples/performance/single_inserts.py66
-rw-r--r--examples/postgis/__init__.py1
-rw-r--r--examples/postgis/postgis.py186
-rw-r--r--examples/sharding/attribute_shard.py117
-rw-r--r--examples/space_invaders/__init__.py2
-rw-r--r--examples/space_invaders/space_invaders.py278
-rw-r--r--examples/versioned_history/__init__.py2
-rw-r--r--examples/versioned_history/history_meta.py89
-rw-r--r--examples/versioned_history/test_versioning.py421
-rw-r--r--examples/versioned_rows/__init__.py2
-rw-r--r--examples/versioned_rows/versioned_map.py96
-rw-r--r--examples/versioned_rows/versioned_rows.py38
-rw-r--r--examples/versioned_rows/versioned_rows_w_versionid.py61
-rw-r--r--examples/versioned_rows/versioned_update_old_row.py110
-rw-r--r--examples/vertical/__init__.py2
-rw-r--r--examples/vertical/dictlike-polymorphic.py155
-rw-r--r--examples/vertical/dictlike.py100
62 files changed, 2435 insertions, 1742 deletions
diff --git a/examples/adjacency_list/adjacency_list.py b/examples/adjacency_list/adjacency_list.py
index 3c9144323..f1628a632 100644
--- a/examples/adjacency_list/adjacency_list.py
+++ b/examples/adjacency_list/adjacency_list.py
@@ -8,7 +8,7 @@ Base = declarative_base()
class TreeNode(Base):
- __tablename__ = 'tree'
+ __tablename__ = "tree"
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey(id))
name = Column(String(50), nullable=False)
@@ -17,15 +17,13 @@ class TreeNode(Base):
"TreeNode",
# cascade deletions
cascade="all, delete-orphan",
-
# many to one + adjacency list - remote_side
# is required to reference the 'remote'
# column in the join condition.
backref=backref("parent", remote_side=id),
-
# children will be represented as a dictionary
# on the "name" attribute.
- collection_class=attribute_mapped_collection('name'),
+ collection_class=attribute_mapped_collection("name"),
)
def __init__(self, name, parent=None):
@@ -36,20 +34,20 @@ class TreeNode(Base):
return "TreeNode(name=%r, id=%r, parent_id=%r)" % (
self.name,
self.id,
- self.parent_id
+ self.parent_id,
)
def dump(self, _indent=0):
- return " " * _indent + repr(self) + \
- "\n" + \
- "".join([
- c.dump(_indent + 1)
- for c in self.children.values()
- ])
+ return (
+ " " * _indent
+ + repr(self)
+ + "\n"
+ + "".join([c.dump(_indent + 1) for c in self.children.values()])
+ )
-if __name__ == '__main__':
- engine = create_engine('sqlite://', echo=True)
+if __name__ == "__main__":
+ engine = create_engine("sqlite://", echo=True)
def msg(msg, *args):
msg = msg % args
@@ -63,14 +61,14 @@ if __name__ == '__main__':
session = Session(engine)
- node = TreeNode('rootnode')
- TreeNode('node1', parent=node)
- TreeNode('node3', parent=node)
+ node = TreeNode("rootnode")
+ TreeNode("node1", parent=node)
+ TreeNode("node3", parent=node)
- node2 = TreeNode('node2')
- TreeNode('subnode1', parent=node2)
- node.children['node2'] = node2
- TreeNode('subnode2', parent=node.children['node2'])
+ node2 = TreeNode("node2")
+ TreeNode("subnode1", parent=node2)
+ node.children["node2"] = node2
+ TreeNode("subnode2", parent=node.children["node2"])
msg("Created new tree structure:\n%s", node.dump())
@@ -81,28 +79,33 @@ if __name__ == '__main__':
msg("Tree After Save:\n %s", node.dump())
- TreeNode('node4', parent=node)
- TreeNode('subnode3', parent=node.children['node4'])
- TreeNode('subnode4', parent=node.children['node4'])
- TreeNode('subsubnode1', parent=node.children['node4'].children['subnode3'])
+ TreeNode("node4", parent=node)
+ TreeNode("subnode3", parent=node.children["node4"])
+ TreeNode("subnode4", parent=node.children["node4"])
+ TreeNode("subsubnode1", parent=node.children["node4"].children["subnode3"])
# remove node1 from the parent, which will trigger a delete
# via the delete-orphan cascade.
- del node.children['node1']
+ del node.children["node1"]
msg("Removed node1. flush + commit:")
session.commit()
msg("Tree after save:\n %s", node.dump())
- msg("Emptying out the session entirely, selecting tree on root, using "
- "eager loading to join four levels deep.")
+ msg(
+ "Emptying out the session entirely, selecting tree on root, using "
+ "eager loading to join four levels deep."
+ )
session.expunge_all()
- node = session.query(TreeNode).\
- options(joinedload_all("children", "children",
- "children", "children")).\
- filter(TreeNode.name == "rootnode").\
- first()
+ node = (
+ session.query(TreeNode)
+ .options(
+ joinedload_all("children", "children", "children", "children")
+ )
+ .filter(TreeNode.name == "rootnode")
+ .first()
+ )
msg("Full Tree:\n%s", node.dump())
diff --git a/examples/association/basic_association.py b/examples/association/basic_association.py
index 6714aa681..52476f184 100644
--- a/examples/association/basic_association.py
+++ b/examples/association/basic_association.py
@@ -12,8 +12,16 @@ of "items", with a particular price paid associated with each "item".
from datetime import datetime
-from sqlalchemy import (create_engine, Column, Integer, String, DateTime,
- Float, ForeignKey, and_)
+from sqlalchemy import (
+ create_engine,
+ Column,
+ Integer,
+ String,
+ DateTime,
+ Float,
+ ForeignKey,
+ and_,
+)
from sqlalchemy.orm import relationship, Session
from sqlalchemy.ext.declarative import declarative_base
@@ -21,20 +29,21 @@ Base = declarative_base()
class Order(Base):
- __tablename__ = 'order'
+ __tablename__ = "order"
order_id = Column(Integer, primary_key=True)
customer_name = Column(String(30), nullable=False)
order_date = Column(DateTime, nullable=False, default=datetime.now())
- order_items = relationship("OrderItem", cascade="all, delete-orphan",
- backref='order')
+ order_items = relationship(
+ "OrderItem", cascade="all, delete-orphan", backref="order"
+ )
def __init__(self, customer_name):
self.customer_name = customer_name
class Item(Base):
- __tablename__ = 'item'
+ __tablename__ = "item"
item_id = Column(Integer, primary_key=True)
description = Column(String(30), nullable=False)
price = Column(Float, nullable=False)
@@ -44,41 +53,40 @@ class Item(Base):
self.price = price
def __repr__(self):
- return 'Item(%r, %r)' % (
- self.description, self.price
- )
+ return "Item(%r, %r)" % (self.description, self.price)
class OrderItem(Base):
- __tablename__ = 'orderitem'
- order_id = Column(Integer, ForeignKey('order.order_id'), primary_key=True)
- item_id = Column(Integer, ForeignKey('item.item_id'), primary_key=True)
+ __tablename__ = "orderitem"
+ order_id = Column(Integer, ForeignKey("order.order_id"), primary_key=True)
+ item_id = Column(Integer, ForeignKey("item.item_id"), primary_key=True)
price = Column(Float, nullable=False)
def __init__(self, item, price=None):
self.item = item
self.price = price or item.price
- item = relationship(Item, lazy='joined')
+
+ item = relationship(Item, lazy="joined")
-if __name__ == '__main__':
- engine = create_engine('sqlite://')
+if __name__ == "__main__":
+ engine = create_engine("sqlite://")
Base.metadata.create_all(engine)
session = Session(engine)
# create catalog
tshirt, mug, hat, crowbar = (
- Item('SA T-Shirt', 10.99),
- Item('SA Mug', 6.50),
- Item('SA Hat', 8.99),
- Item('MySQL Crowbar', 16.99)
+ Item("SA T-Shirt", 10.99),
+ Item("SA Mug", 6.50),
+ Item("SA Hat", 8.99),
+ Item("MySQL Crowbar", 16.99),
)
session.add_all([tshirt, mug, hat, crowbar])
session.commit()
# create an order
- order = Order('john smith')
+ order = Order("john smith")
# add three OrderItem associations to the Order and save
order.order_items.append(OrderItem(mug))
@@ -88,13 +96,18 @@ if __name__ == '__main__':
session.commit()
# query the order, print items
- order = session.query(Order).filter_by(customer_name='john smith').one()
- print([(order_item.item.description, order_item.price)
- for order_item in order.order_items])
+ order = session.query(Order).filter_by(customer_name="john smith").one()
+ print(
+ [
+ (order_item.item.description, order_item.price)
+ for order_item in order.order_items
+ ]
+ )
# print customers who bought 'MySQL Crowbar' on sale
- q = session.query(Order).join('order_items', 'item')
- q = q.filter(and_(Item.description == 'MySQL Crowbar',
- Item.price > OrderItem.price))
+ q = session.query(Order).join("order_items", "item")
+ q = q.filter(
+ and_(Item.description == "MySQL Crowbar", Item.price > OrderItem.price)
+ )
print([order.customer_name for order in q])
diff --git a/examples/association/dict_of_sets_with_default.py b/examples/association/dict_of_sets_with_default.py
index fb9b6aa06..7f668c087 100644
--- a/examples/association/dict_of_sets_with_default.py
+++ b/examples/association/dict_of_sets_with_default.py
@@ -37,7 +37,9 @@ class A(Base):
__tablename__ = "a"
associations = relationship(
"B",
- collection_class=lambda: GenDefaultCollection(operator.attrgetter("key"))
+ collection_class=lambda: GenDefaultCollection(
+ operator.attrgetter("key")
+ ),
)
collections = association_proxy("associations", "values")
@@ -71,19 +73,15 @@ class C(Base):
self.value = value
-if __name__ == '__main__':
- engine = create_engine('sqlite://', echo=True)
+if __name__ == "__main__":
+ engine = create_engine("sqlite://", echo=True)
Base.metadata.create_all(engine)
session = Session(engine)
# only "A" is referenced explicitly. Using "collections",
# we deal with a dict of key/sets of integers directly.
- session.add_all([
- A(collections={
- "1": set([1, 2, 3]),
- })
- ])
+ session.add_all([A(collections={"1": set([1, 2, 3])})])
session.commit()
a1 = session.query(A).first()
diff --git a/examples/association/proxied_association.py b/examples/association/proxied_association.py
index 3393fdd1d..46785c6e2 100644
--- a/examples/association/proxied_association.py
+++ b/examples/association/proxied_association.py
@@ -7,8 +7,15 @@ to ``OrderItem`` optional.
from datetime import datetime
-from sqlalchemy import (create_engine, Column, Integer, String, DateTime,
- Float, ForeignKey)
+from sqlalchemy import (
+ create_engine,
+ Column,
+ Integer,
+ String,
+ DateTime,
+ Float,
+ ForeignKey,
+)
from sqlalchemy.orm import relationship, Session
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.associationproxy import association_proxy
@@ -17,13 +24,14 @@ Base = declarative_base()
class Order(Base):
- __tablename__ = 'order'
+ __tablename__ = "order"
order_id = Column(Integer, primary_key=True)
customer_name = Column(String(30), nullable=False)
order_date = Column(DateTime, nullable=False, default=datetime.now())
- order_items = relationship("OrderItem", cascade="all, delete-orphan",
- backref='order')
+ order_items = relationship(
+ "OrderItem", cascade="all, delete-orphan", backref="order"
+ )
items = association_proxy("order_items", "item")
def __init__(self, customer_name):
@@ -31,7 +39,7 @@ class Order(Base):
class Item(Base):
- __tablename__ = 'item'
+ __tablename__ = "item"
item_id = Column(Integer, primary_key=True)
description = Column(String(30), nullable=False)
price = Column(Float, nullable=False)
@@ -41,39 +49,40 @@ class Item(Base):
self.price = price
def __repr__(self):
- return 'Item(%r, %r)' % (self.description, self.price)
+ return "Item(%r, %r)" % (self.description, self.price)
class OrderItem(Base):
- __tablename__ = 'orderitem'
- order_id = Column(Integer, ForeignKey('order.order_id'), primary_key=True)
- item_id = Column(Integer, ForeignKey('item.item_id'), primary_key=True)
+ __tablename__ = "orderitem"
+ order_id = Column(Integer, ForeignKey("order.order_id"), primary_key=True)
+ item_id = Column(Integer, ForeignKey("item.item_id"), primary_key=True)
price = Column(Float, nullable=False)
def __init__(self, item, price=None):
self.item = item
self.price = price or item.price
- item = relationship(Item, lazy='joined')
+
+ item = relationship(Item, lazy="joined")
-if __name__ == '__main__':
- engine = create_engine('sqlite://')
+if __name__ == "__main__":
+ engine = create_engine("sqlite://")
Base.metadata.create_all(engine)
session = Session(engine)
# create catalog
tshirt, mug, hat, crowbar = (
- Item('SA T-Shirt', 10.99),
- Item('SA Mug', 6.50),
- Item('SA Hat', 8.99),
- Item('MySQL Crowbar', 16.99)
+ Item("SA T-Shirt", 10.99),
+ Item("SA Mug", 6.50),
+ Item("SA Hat", 8.99),
+ Item("MySQL Crowbar", 16.99),
)
session.add_all([tshirt, mug, hat, crowbar])
session.commit()
# create an order
- order = Order('john smith')
+ order = Order("john smith")
# add items via the association proxy.
# the OrderItem is created automatically.
@@ -87,19 +96,24 @@ if __name__ == '__main__':
session.commit()
# query the order, print items
- order = session.query(Order).filter_by(customer_name='john smith').one()
+ order = session.query(Order).filter_by(customer_name="john smith").one()
# print items based on the OrderItem collection directly
- print([(assoc.item.description, assoc.price, assoc.item.price)
- for assoc in order.order_items])
+ print(
+ [
+ (assoc.item.description, assoc.price, assoc.item.price)
+ for assoc in order.order_items
+ ]
+ )
# print items based on the "proxied" items collection
- print([(item.description, item.price)
- for item in order.items])
+ print([(item.description, item.price) for item in order.items])
# print customers who bought 'MySQL Crowbar' on sale
- orders = session.query(Order).\
- join('order_items', 'item').\
- filter(Item.description == 'MySQL Crowbar').\
- filter(Item.price > OrderItem.price)
+ orders = (
+ session.query(Order)
+ .join("order_items", "item")
+ .filter(Item.description == "MySQL Crowbar")
+ .filter(Item.price > OrderItem.price)
+ )
print([o.customer_name for o in orders])
diff --git a/examples/custom_attributes/__init__.py b/examples/custom_attributes/__init__.py
index cbc65dfed..8d73d27e3 100644
--- a/examples/custom_attributes/__init__.py
+++ b/examples/custom_attributes/__init__.py
@@ -4,4 +4,4 @@ system.
.. autosource::
-""" \ No newline at end of file
+"""
diff --git a/examples/custom_attributes/active_column_defaults.py b/examples/custom_attributes/active_column_defaults.py
index dd823e814..f05a53173 100644
--- a/examples/custom_attributes/active_column_defaults.py
+++ b/examples/custom_attributes/active_column_defaults.py
@@ -35,6 +35,7 @@ def default_listener(col_attr, default):
user integrating this feature.
"""
+
@event.listens_for(col_attr, "init_scalar", retval=True, propagate=True)
def init_scalar(target, value, dict_):
@@ -52,7 +53,8 @@ def default_listener(col_attr, default):
# or can procure a connection from an Engine
# or Session and actually run the SQL, if desired.
raise NotImplementedError(
- "Can't invoke pre-default for a SQL-level column default")
+ "Can't invoke pre-default for a SQL-level column default"
+ )
# set the value in the given dict_; this won't emit any further
# attribute set events or create attribute "history", but the value
@@ -63,7 +65,7 @@ def default_listener(col_attr, default):
return value
-if __name__ == '__main__':
+if __name__ == "__main__":
from sqlalchemy import Column, Integer, DateTime, create_engine
from sqlalchemy.orm import Session
@@ -72,10 +74,10 @@ if __name__ == '__main__':
Base = declarative_base()
- event.listen(Base, 'mapper_configured', configure_listener, propagate=True)
+ event.listen(Base, "mapper_configured", configure_listener, propagate=True)
class Widget(Base):
- __tablename__ = 'widget'
+ __tablename__ = "widget"
id = Column(Integer, primary_key=True)
@@ -96,8 +98,8 @@ if __name__ == '__main__':
# Column-level default for the "timestamp" column will no longer fire
# off.
current_time = w1.timestamp
- assert (
- current_time > datetime.datetime.now() - datetime.timedelta(seconds=5)
+ assert current_time > datetime.datetime.now() - datetime.timedelta(
+ seconds=5
)
# persist
@@ -107,7 +109,7 @@ if __name__ == '__main__':
# data is persisted. The timestamp is also the one we generated above;
# e.g. the default wasn't re-invoked later.
- assert (
- sess.query(Widget.radius, Widget.timestamp).first() ==
- (30, current_time)
+ assert sess.query(Widget.radius, Widget.timestamp).first() == (
+ 30,
+ current_time,
)
diff --git a/examples/custom_attributes/custom_management.py b/examples/custom_attributes/custom_management.py
index 2199e0138..812385906 100644
--- a/examples/custom_attributes/custom_management.py
+++ b/examples/custom_attributes/custom_management.py
@@ -9,31 +9,44 @@ descriptors with a user-defined system.
"""
-from sqlalchemy import create_engine, MetaData, Table, Column, Integer, Text,\
- ForeignKey
+from sqlalchemy import (
+ create_engine,
+ MetaData,
+ Table,
+ Column,
+ Integer,
+ Text,
+ ForeignKey,
+)
from sqlalchemy.orm import mapper, relationship, Session
-from sqlalchemy.orm.attributes import set_attribute, get_attribute, \
- del_attribute
+from sqlalchemy.orm.attributes import (
+ set_attribute,
+ get_attribute,
+ del_attribute,
+)
from sqlalchemy.orm.instrumentation import is_instrumented
from sqlalchemy.ext.instrumentation import InstrumentationManager
+
class MyClassState(InstrumentationManager):
def get_instance_dict(self, class_, instance):
return instance._goofy_dict
def initialize_instance_dict(self, class_, instance):
- instance.__dict__['_goofy_dict'] = {}
+ instance.__dict__["_goofy_dict"] = {}
def install_state(self, class_, instance, state):
- instance.__dict__['_goofy_dict']['state'] = state
+ instance.__dict__["_goofy_dict"]["state"] = state
def state_getter(self, class_):
def find(instance):
- return instance.__dict__['_goofy_dict']['state']
+ return instance.__dict__["_goofy_dict"]["state"]
+
return find
+
class MyClass(object):
__sa_instrumentation_manager__ = MyClassState
@@ -63,17 +76,23 @@ class MyClass(object):
del self._goofy_dict[key]
-if __name__ == '__main__':
- engine = create_engine('sqlite://')
+if __name__ == "__main__":
+ engine = create_engine("sqlite://")
meta = MetaData()
- table1 = Table('table1', meta,
- Column('id', Integer, primary_key=True),
- Column('name', Text))
- table2 = Table('table2', meta,
- Column('id', Integer, primary_key=True),
- Column('name', Text),
- Column('t1id', Integer, ForeignKey('table1.id')))
+ table1 = Table(
+ "table1",
+ meta,
+ Column("id", Integer, primary_key=True),
+ Column("name", Text),
+ )
+ table2 = Table(
+ "table2",
+ meta,
+ Column("id", Integer, primary_key=True),
+ Column("name", Text),
+ Column("t1id", Integer, ForeignKey("table1.id")),
+ )
meta.create_all(engine)
class A(MyClass):
@@ -82,16 +101,14 @@ if __name__ == '__main__':
class B(MyClass):
pass
- mapper(A, table1, properties={
- 'bs': relationship(B)
- })
+ mapper(A, table1, properties={"bs": relationship(B)})
mapper(B, table2)
- a1 = A(name='a1', bs=[B(name='b1'), B(name='b2')])
+ a1 = A(name="a1", bs=[B(name="b1"), B(name="b2")])
- assert a1.name == 'a1'
- assert a1.bs[0].name == 'b1'
+ assert a1.name == "a1"
+ assert a1.bs[0].name == "b1"
sess = Session(engine)
sess.add(a1)
@@ -100,8 +117,8 @@ if __name__ == '__main__':
a1 = sess.query(A).get(a1.id)
- assert a1.name == 'a1'
- assert a1.bs[0].name == 'b1'
+ assert a1.name == "a1"
+ assert a1.bs[0].name == "b1"
a1.bs.remove(a1.bs[0])
diff --git a/examples/custom_attributes/listen_for_events.py b/examples/custom_attributes/listen_for_events.py
index 0aeebc1d1..e3ef4cbea 100644
--- a/examples/custom_attributes/listen_for_events.py
+++ b/examples/custom_attributes/listen_for_events.py
@@ -5,6 +5,7 @@ and listen for change events.
from sqlalchemy import event
+
def configure_listener(class_, key, inst):
def append(instance, value, initiator):
instance.receive_change_event("append", key, value, None)
@@ -15,19 +16,18 @@ def configure_listener(class_, key, inst):
def set_(instance, value, oldvalue, initiator):
instance.receive_change_event("set", key, value, oldvalue)
- event.listen(inst, 'append', append)
- event.listen(inst, 'remove', remove)
- event.listen(inst, 'set', set_)
+ event.listen(inst, "append", append)
+ event.listen(inst, "remove", remove)
+ event.listen(inst, "set", set_)
-if __name__ == '__main__':
+if __name__ == "__main__":
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship
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:
@@ -37,7 +37,7 @@ if __name__ == '__main__':
Base = declarative_base(cls=Base)
- event.listen(Base, 'attribute_instrument', configure_listener)
+ event.listen(Base, "attribute_instrument", configure_listener)
class MyMappedClass(Base):
__tablename__ = "mytable"
@@ -61,9 +61,7 @@ if __name__ == '__main__':
# classes are instrumented. Demonstrate the events !
- m1 = MyMappedClass(data='m1', related=Related(data='r1'))
- m1.data = 'm1mod'
- m1.related.mapped.append(MyMappedClass(data='m2'))
+ 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/dogpile_caching/advanced.py b/examples/dogpile_caching/advanced.py
index dc2ed0771..8f395bd7b 100644
--- a/examples/dogpile_caching/advanced.py
+++ b/examples/dogpile_caching/advanced.py
@@ -7,6 +7,7 @@ from .environment import Session
from .model import Person, cache_address_bits
from .caching_query import FromCache, RelationshipCache
+
def load_name_range(start, end, invalidate=False):
"""Load Person objects on a range of names.
@@ -24,10 +25,14 @@ def load_name_range(start, end, invalidate=False):
SQL that emits for unloaded Person objects as well as the distribution
of data within the cache.
"""
- q = Session.query(Person).\
- filter(Person.name.between("person %.2d" % start, "person %.2d" % end)).\
- options(cache_address_bits).\
- options(FromCache("default", "name_range"))
+ q = (
+ Session.query(Person)
+ .filter(
+ Person.name.between("person %.2d" % start, "person %.2d" % end)
+ )
+ .options(cache_address_bits)
+ .options(FromCache("default", "name_range"))
+ )
# have the "addresses" collection cached separately
# each lazyload of Person.addresses loads from cache.
@@ -37,7 +42,7 @@ def load_name_range(start, end, invalidate=False):
# 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))
+ # q = q.options(joinedload(Person.addresses))
# if requested, invalidate the cache on current criterion.
if invalidate:
@@ -45,6 +50,7 @@ def load_name_range(start, end, invalidate=False):
return q.all()
+
print("two through twelve, possibly from cache:\n")
print(", ".join([p.name for p in load_name_range(2, 12)]))
@@ -61,7 +67,9 @@ print(", ".join([p.name for p in load_name_range(25, 40, True)]))
# illustrate the address loading from either cache/already
# on the Person
-print("\n\nPeople plus addresses, two through twelve, addresses possibly from cache")
+print(
+ "\n\nPeople plus addresses, two through twelve, addresses possibly from cache"
+)
for p in load_name_range(2, 12):
print(p.format_full())
@@ -71,5 +79,7 @@ print("\n\nPeople plus addresses, two through twelve, addresses from cache")
for p in load_name_range(2, 12):
print(p.format_full())
-print("\n\nIf this was the first run of advanced.py, try "\
- "a second run. Only one SQL statement will be emitted.")
+print(
+ "\n\nIf this was the first run of advanced.py, try "
+ "a second run. Only one SQL statement will be emitted."
+)
diff --git a/examples/dogpile_caching/caching_query.py b/examples/dogpile_caching/caching_query.py
index 6ad2dba4d..060c14613 100644
--- a/examples/dogpile_caching/caching_query.py
+++ b/examples/dogpile_caching/caching_query.py
@@ -59,7 +59,7 @@ class CachingQuery(Query):
"""
super_ = super(CachingQuery, self)
- if hasattr(self, '_cache_region'):
+ if hasattr(self, "_cache_region"):
return self.get_value(createfunc=lambda: list(super_.__iter__()))
else:
return super_.__iter__()
@@ -78,13 +78,11 @@ class CachingQuery(Query):
"""
super_ = super(CachingQuery, self)
- if context.query is not self and hasattr(self, '_cache_region'):
+ if context.query is not self and hasattr(self, "_cache_region"):
# special logic called when the Query._execute_and_instances()
# method is called directly from the baked query
return self.get_value(
- createfunc=lambda: list(
- super_._execute_and_instances(context)
- )
+ createfunc=lambda: list(super_._execute_and_instances(context))
)
else:
return super_._execute_and_instances(context)
@@ -105,8 +103,13 @@ class CachingQuery(Query):
dogpile_region, cache_key = self._get_cache_plus_key()
dogpile_region.delete(cache_key)
- def get_value(self, merge=True, createfunc=None,
- expiration_time=None, ignore_expiration=False):
+ def get_value(
+ self,
+ merge=True,
+ createfunc=None,
+ expiration_time=None,
+ ignore_expiration=False,
+ ):
"""Return the value from the cache for this query.
Raise KeyError if no value present and no
@@ -119,19 +122,20 @@ class CachingQuery(Query):
# but is expired, return it anyway. This doesn't make sense
# with createfunc, which says, if the value is expired, generate
# a new value.
- assert not ignore_expiration or not createfunc, \
- "Can't ignore expiration and also provide createfunc"
+ assert (
+ not ignore_expiration or not createfunc
+ ), "Can't ignore expiration and also provide createfunc"
if ignore_expiration or not createfunc:
- cached_value = dogpile_region.get(cache_key,
- expiration_time=expiration_time,
- ignore_expiration=ignore_expiration)
+ cached_value = dogpile_region.get(
+ cache_key,
+ expiration_time=expiration_time,
+ ignore_expiration=ignore_expiration,
+ )
else:
cached_value = dogpile_region.get_or_create(
- cache_key,
- createfunc,
- expiration_time=expiration_time
- )
+ cache_key, createfunc, expiration_time=expiration_time
+ )
if cached_value is NO_VALUE:
raise KeyError(cache_key)
if merge:
@@ -144,11 +148,14 @@ class CachingQuery(Query):
dogpile_region, cache_key = self._get_cache_plus_key()
dogpile_region.set(cache_key, value)
+
def query_callable(regions, query_cls=CachingQuery):
def query(*arg, **kw):
return query_cls(regions, *arg, **kw)
+
return query
+
def _key_from_query(query, qualifier=None):
"""Given a Query, create a cache key.
@@ -168,9 +175,8 @@ def _key_from_query(query, qualifier=None):
# here we return the key as a long string. our "key mangler"
# set up with the region will boil it down to an md5.
- return " ".join(
- [str(compiled)] +
- [str(params[k]) for k in sorted(params)])
+ return " ".join([str(compiled)] + [str(params[k]) for k in sorted(params)])
+
class FromCache(MapperOption):
"""Specifies that a Query should load results from a cache."""
@@ -198,6 +204,7 @@ class FromCache(MapperOption):
"""Process a Query during normal loading operation."""
query._cache_region = self
+
class RelationshipCache(MapperOption):
"""Specifies that a Query as called within a "lazy load"
should load results from a cache."""
@@ -237,7 +244,9 @@ class RelationshipCache(MapperOption):
for cls in mapper.class_.__mro__:
if (cls, key) in self._relationship_options:
- relationship_option = self._relationship_options[(cls, key)]
+ relationship_option = self._relationship_options[
+ (cls, key)
+ ]
query._cache_region = relationship_option
break
@@ -264,4 +273,3 @@ class RelationshipCache(MapperOption):
"""
return None
-
diff --git a/examples/dogpile_caching/environment.py b/examples/dogpile_caching/environment.py
index 130dfdb2b..13bd0a310 100644
--- a/examples/dogpile_caching/environment.py
+++ b/examples/dogpile_caching/environment.py
@@ -10,6 +10,7 @@ from dogpile.cache.region import make_region
import os
from hashlib import md5
import sys
+
py2k = sys.version_info < (3, 0)
if py2k:
@@ -23,9 +24,7 @@ regions = {}
# using a callable that will associate the dictionary
# of regions with the Query.
Session = scoped_session(
- sessionmaker(
- query_cls=caching_query.query_callable(regions)
- )
+ sessionmaker(query_cls=caching_query.query_callable(regions))
)
# global declarative base class.
@@ -42,7 +41,7 @@ if not os.path.exists(root):
os.makedirs(root)
dbfile = os.path.join(root, "dogpile_demo.db")
-engine = create_engine('sqlite:///%s' % dbfile, echo=True)
+engine = create_engine("sqlite:///%s" % dbfile, echo=True)
Session.configure(bind=engine)
@@ -51,10 +50,11 @@ def md5_key_mangler(key):
distill them into an md5 hash.
"""
- return md5(key.encode('ascii')).hexdigest()
+ return md5(key.encode("ascii")).hexdigest()
+
# configure the "default" cache region.
-regions['default'] = make_region(
+regions["default"] = make_region(
# the "dbm" backend needs
# string-encoded keys
key_mangler=md5_key_mangler
@@ -63,11 +63,9 @@ regions['default'] = make_region(
# serialized persistence. Normally
# memcached or similar is a better choice
# for caching.
- 'dogpile.cache.dbm',
+ "dogpile.cache.dbm",
expiration_time=3600,
- arguments={
- "filename": os.path.join(root, "cache.dbm")
- }
+ arguments={"filename": os.path.join(root, "cache.dbm")},
)
# optional; call invalidate() on the region
@@ -83,6 +81,7 @@ installed = False
def bootstrap():
global installed
from . import fixture_data
+
if not os.path.exists(dbfile):
fixture_data.install()
- installed = True \ No newline at end of file
+ installed = True
diff --git a/examples/dogpile_caching/fixture_data.py b/examples/dogpile_caching/fixture_data.py
index 465171891..e301db2a4 100644
--- a/examples/dogpile_caching/fixture_data.py
+++ b/examples/dogpile_caching/fixture_data.py
@@ -12,13 +12,19 @@ def install():
Base.metadata.create_all(Session().bind)
data = [
- ('Chicago', 'United States', ('60601', '60602', '60603', '60604')),
- ('Montreal', 'Canada', ('H2S 3K9', 'H2B 1V4', 'H7G 2T8')),
- ('Edmonton', 'Canada', ('T5J 1R9', 'T5J 1Z4', 'T5H 1P6')),
- ('New York', 'United States',
- ('10001', '10002', '10003', '10004', '10005', '10006')),
- ('San Francisco', 'United States',
- ('94102', '94103', '94104', '94105', '94107', '94108'))
+ ("Chicago", "United States", ("60601", "60602", "60603", "60604")),
+ ("Montreal", "Canada", ("H2S 3K9", "H2B 1V4", "H7G 2T8")),
+ ("Edmonton", "Canada", ("T5J 1R9", "T5J 1Z4", "T5H 1P6")),
+ (
+ "New York",
+ "United States",
+ ("10001", "10002", "10003", "10004", "10005", "10006"),
+ ),
+ (
+ "San Francisco",
+ "United States",
+ ("94102", "94103", "94104", "94105", "94107", "94108"),
+ ),
]
countries = {}
@@ -40,8 +46,9 @@ def install():
Address(
street="street %.2d" % i,
postal_code=all_post_codes[
- random.randint(0, len(all_post_codes) - 1)]
- )
+ random.randint(0, len(all_post_codes) - 1)
+ ],
+ ),
)
Session.add(person)
diff --git a/examples/dogpile_caching/helloworld.py b/examples/dogpile_caching/helloworld.py
index 0dbde5eaf..eb565344e 100644
--- a/examples/dogpile_caching/helloworld.py
+++ b/examples/dogpile_caching/helloworld.py
@@ -21,28 +21,34 @@ people = Session.query(Person).options(FromCache("default")).all()
# Specifying a different query produces a different cache key, so
# these results are independently cached.
print("loading people two through twelve")
-people_two_through_twelve = Session.query(Person).\
- options(FromCache("default")).\
- filter(Person.name.between("person 02", "person 12")).\
- all()
+people_two_through_twelve = (
+ Session.query(Person)
+ .options(FromCache("default"))
+ .filter(Person.name.between("person 02", "person 12"))
+ .all()
+)
# the data is cached under string structure of the SQL statement, *plus*
# the bind parameters of the query. So this query, having
# different literal parameters under "Person.name.between()" than the
# previous one, issues new SQL...
print("loading people five through fifteen")
-people_five_through_fifteen = Session.query(Person).\
- options(FromCache("default")).\
- filter(Person.name.between("person 05", "person 15")).\
- all()
+people_five_through_fifteen = (
+ Session.query(Person)
+ .options(FromCache("default"))
+ .filter(Person.name.between("person 05", "person 15"))
+ .all()
+)
# ... but using the same params as are already cached, no SQL
print("loading people two through twelve...again!")
-people_two_through_twelve = Session.query(Person).\
- options(FromCache("default")).\
- filter(Person.name.between("person 02", "person 12")).\
- all()
+people_two_through_twelve = (
+ Session.query(Person)
+ .options(FromCache("default"))
+ .filter(Person.name.between("person 02", "person 12"))
+ .all()
+)
# invalidate the cache for the three queries we've done. Recreate
@@ -51,10 +57,9 @@ people_two_through_twelve = Session.query(Person).\
# same order, then call invalidate().
print("invalidating everything")
Session.query(Person).options(FromCache("default")).invalidate()
-Session.query(Person).\
- options(FromCache("default")).\
- filter(Person.name.between("person 02", "person 12")).invalidate()
-Session.query(Person).\
- options(FromCache("default", "people_on_range")).\
- filter(Person.name.between("person 05", "person 15")).invalidate()
-
+Session.query(Person).options(FromCache("default")).filter(
+ Person.name.between("person 02", "person 12")
+).invalidate()
+Session.query(Person).options(FromCache("default", "people_on_range")).filter(
+ Person.name.between("person 05", "person 15")
+).invalidate()
diff --git a/examples/dogpile_caching/local_session_caching.py b/examples/dogpile_caching/local_session_caching.py
index 633252fc7..358886bf0 100644
--- a/examples/dogpile_caching/local_session_caching.py
+++ b/examples/dogpile_caching/local_session_caching.py
@@ -30,7 +30,7 @@ class ScopedSessionBackend(CacheBackend):
"""
def __init__(self, arguments):
- self.scoped_session = arguments['scoped_session']
+ self.scoped_session = arguments["scoped_session"]
def get(self, key):
return self._cache_dictionary.get(key, NO_VALUE)
@@ -52,10 +52,11 @@ class ScopedSessionBackend(CacheBackend):
sess._cache_dictionary = cache_dict = {}
return cache_dict
+
register_backend("sqlalchemy.session", __name__, "ScopedSessionBackend")
-if __name__ == '__main__':
+if __name__ == "__main__":
from .environment import Session, regions
from .caching_query import FromCache
from dogpile.cache import make_region
@@ -63,20 +64,19 @@ if __name__ == '__main__':
# set up a region based on the ScopedSessionBackend,
# pointing to the scoped_session declared in the example
# environment.
- regions['local_session'] = make_region().configure(
- 'sqlalchemy.session',
- arguments={
- "scoped_session": Session
- }
+ regions["local_session"] = make_region().configure(
+ "sqlalchemy.session", arguments={"scoped_session": Session}
)
from .model import Person
# query to load Person by name, with criterion
# of "person 10"
- q = Session.query(Person).\
- options(FromCache("local_session")).\
- filter(Person.name == "person 10")
+ q = (
+ Session.query(Person)
+ .options(FromCache("local_session"))
+ .filter(Person.name == "person 10")
+ )
# load from DB
person10 = q.one()
diff --git a/examples/dogpile_caching/model.py b/examples/dogpile_caching/model.py
index 3eb02108c..f6a259820 100644
--- a/examples/dogpile_caching/model.py
+++ b/examples/dogpile_caching/model.py
@@ -14,7 +14,7 @@ from .environment import Base, bootstrap
class Country(Base):
- __tablename__ = 'country'
+ __tablename__ = "country"
id = Column(Integer, primary_key=True)
name = Column(String(100), nullable=False)
@@ -24,11 +24,11 @@ class Country(Base):
class City(Base):
- __tablename__ = 'city'
+ __tablename__ = "city"
id = Column(Integer, primary_key=True)
name = Column(String(100), nullable=False)
- country_id = Column(Integer, ForeignKey('country.id'), nullable=False)
+ country_id = Column(Integer, ForeignKey("country.id"), nullable=False)
country = relationship(Country)
def __init__(self, name, country):
@@ -37,11 +37,11 @@ class City(Base):
class PostalCode(Base):
- __tablename__ = 'postal_code'
+ __tablename__ = "postal_code"
id = Column(Integer, primary_key=True)
code = Column(String(10), nullable=False)
- city_id = Column(Integer, ForeignKey('city.id'), nullable=False)
+ city_id = Column(Integer, ForeignKey("city.id"), nullable=False)
city = relationship(City)
@property
@@ -54,12 +54,12 @@ class PostalCode(Base):
class Address(Base):
- __tablename__ = 'address'
+ __tablename__ = "address"
id = Column(Integer, primary_key=True)
- person_id = Column(Integer, ForeignKey('person.id'), nullable=False)
+ person_id = Column(Integer, ForeignKey("person.id"), nullable=False)
street = Column(String(200), nullable=False)
- postal_code_id = Column(Integer, ForeignKey('postal_code.id'))
+ postal_code_id = Column(Integer, ForeignKey("postal_code.id"))
postal_code = relationship(PostalCode)
@property
@@ -71,15 +71,16 @@ class Address(Base):
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)
+ return "%s\t%s, %s\t%s" % (
+ self.street,
+ self.city.name,
+ self.postal_code.code,
+ self.country.name,
)
class Person(Base):
- __tablename__ = 'person'
+ __tablename__ = "person"
id = Column(Integer, primary_key=True)
name = Column(String(100), nullable=False)
@@ -98,14 +99,14 @@ class Person(Base):
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.
-cache_address_bits = RelationshipCache(PostalCode.city, "default").\
- and_(
- RelationshipCache(City.country, "default")
-).and_(
- RelationshipCache(Address.postal_code, "default")
+cache_address_bits = (
+ RelationshipCache(PostalCode.city, "default")
+ .and_(RelationshipCache(City.country, "default"))
+ .and_(RelationshipCache(Address.postal_code, "default"))
)
bootstrap()
diff --git a/examples/dogpile_caching/relationship_caching.py b/examples/dogpile_caching/relationship_caching.py
index 920d696f8..76c7e767f 100644
--- a/examples/dogpile_caching/relationship_caching.py
+++ b/examples/dogpile_caching/relationship_caching.py
@@ -12,7 +12,8 @@ from sqlalchemy.orm import joinedload
import os
for p in Session.query(Person).options(
- joinedload(Person.addresses), cache_address_bits):
+ joinedload(Person.addresses), cache_address_bits
+):
print(p.format_full())
@@ -25,5 +26,5 @@ print(
"related data is pulled from cache.\n"
"To clear the cache, delete the file %r. \n"
"This will cause a re-load of cities, postal codes and countries on "
- "the next run.\n"
- % os.path.join(root, 'cache.dbm'))
+ "the next run.\n" % os.path.join(root, "cache.dbm")
+)
diff --git a/examples/dynamic_dict/__init__.py b/examples/dynamic_dict/__init__.py
index e592ea200..ed31df062 100644
--- a/examples/dynamic_dict/__init__.py
+++ b/examples/dynamic_dict/__init__.py
@@ -5,4 +5,4 @@ full collection at once.
.. autosource::
-""" \ No newline at end of file
+"""
diff --git a/examples/dynamic_dict/dynamic_dict.py b/examples/dynamic_dict/dynamic_dict.py
index 530674f2e..62da55c38 100644
--- a/examples/dynamic_dict/dynamic_dict.py
+++ b/examples/dynamic_dict/dynamic_dict.py
@@ -14,7 +14,7 @@ class ProxyDict(object):
return [x[0] for x in self.collection.values(descriptor)]
def __getitem__(self, key):
- x = self.collection.filter_by(**{self.keyname:key}).first()
+ x = self.collection.filter_by(**{self.keyname: key}).first()
if x:
return x
else:
@@ -28,43 +28,48 @@ class ProxyDict(object):
pass
self.collection.append(value)
+
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.orm import sessionmaker, relationship
-engine = create_engine('sqlite://', echo=True)
+engine = create_engine("sqlite://", echo=True)
Base = declarative_base(engine)
+
class Parent(Base):
- __tablename__ = 'parent'
+ __tablename__ = "parent"
id = Column(Integer, primary_key=True)
name = Column(String(50))
- _collection = relationship("Child", lazy="dynamic",
- cascade="all, delete-orphan")
+ _collection = relationship(
+ "Child", lazy="dynamic", cascade="all, delete-orphan"
+ )
@property
def child_map(self):
- return ProxyDict(self, '_collection', Child, 'key')
+ return ProxyDict(self, "_collection", Child, "key")
+
class Child(Base):
- __tablename__ = 'child'
+ __tablename__ = "child"
id = Column(Integer, primary_key=True)
key = Column(String(50))
- parent_id = Column(Integer, ForeignKey('parent.id'))
+ parent_id = Column(Integer, ForeignKey("parent.id"))
def __repr__(self):
return "Child(key=%r)" % self.key
+
Base.metadata.create_all()
sess = sessionmaker()()
-p1 = Parent(name='p1')
+p1 = Parent(name="p1")
sess.add(p1)
print("\n---------begin setting nodes, autoflush occurs\n")
-p1.child_map['k1'] = Child(key='k1')
-p1.child_map['k2'] = Child(key='k2')
+p1.child_map["k1"] = Child(key="k1")
+p1.child_map["k2"] = Child(key="k2")
# this will autoflush the current map.
# ['k1', 'k2']
@@ -73,16 +78,15 @@ print(list(p1.child_map.keys()))
# k1
print("\n---------print 'k1' node\n")
-print(p1.child_map['k1'])
+print(p1.child_map["k1"])
print("\n---------update 'k2' node - must find existing, and replace\n")
-p1.child_map['k2'] = Child(key='k2')
+p1.child_map["k2"] = Child(key="k2")
print("\n---------print 'k2' key - flushes first\n")
# k2
-print(p1.child_map['k2'])
+print(p1.child_map["k2"])
print("\n---------print all child nodes\n")
# [k1, k2b]
print(sess.query(Child).all())
-
diff --git a/examples/elementtree/__init__.py b/examples/elementtree/__init__.py
index 66e9cfbbe..82d00ff5a 100644
--- a/examples/elementtree/__init__.py
+++ b/examples/elementtree/__init__.py
@@ -22,4 +22,4 @@ E.g.::
.. autosource::
:files: pickle.py, adjacency_list.py, optimized_al.py
-""" \ No newline at end of file
+"""
diff --git a/examples/elementtree/adjacency_list.py b/examples/elementtree/adjacency_list.py
index 5e27ba9ca..1f7161212 100644
--- a/examples/elementtree/adjacency_list.py
+++ b/examples/elementtree/adjacency_list.py
@@ -15,42 +15,63 @@ styles of persistence are identical, as is the structure of the main Document cl
"""
################################# PART I - Imports/Coniguration ####################################
-from sqlalchemy import (MetaData, Table, Column, Integer, String, ForeignKey,
- Unicode, and_, create_engine)
+from sqlalchemy import (
+ MetaData,
+ Table,
+ Column,
+ Integer,
+ String,
+ ForeignKey,
+ Unicode,
+ and_,
+ create_engine,
+)
from sqlalchemy.orm import mapper, relationship, Session, lazyload
import sys, os, io, re
from xml.etree import ElementTree
-e = create_engine('sqlite://')
+e = create_engine("sqlite://")
meta = MetaData()
################################# PART II - Table Metadata #########################################
# 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),
- Column('element_id', Integer, ForeignKey('elements.element_id'))
+documents = Table(
+ "documents",
+ meta,
+ Column("document_id", Integer, primary_key=True),
+ Column("filename", String(30), unique=True),
+ Column("element_id", Integer, ForeignKey("elements.element_id")),
)
# stores XML nodes in an adjacency list model. This corresponds to
# Element and SubElement objects.
-elements = Table('elements', meta,
- Column('element_id', Integer, primary_key=True),
- Column('parent_id', Integer, ForeignKey('elements.element_id')),
- Column('tag', Unicode(30), nullable=False),
- Column('text', Unicode),
- Column('tail', Unicode)
- )
+elements = Table(
+ "elements",
+ meta,
+ Column("element_id", Integer, primary_key=True),
+ Column("parent_id", Integer, ForeignKey("elements.element_id")),
+ Column("tag", Unicode(30), nullable=False),
+ Column("text", Unicode),
+ Column("tail", Unicode),
+)
# stores attributes. This corresponds to the dictionary of attributes
# stored by an Element or SubElement.
-attributes = Table('attributes', meta,
- Column('element_id', Integer, ForeignKey('elements.element_id'), primary_key=True),
- Column('name', Unicode(100), nullable=False, primary_key=True),
- Column('value', Unicode(255)))
+attributes = Table(
+ "attributes",
+ meta,
+ Column(
+ "element_id",
+ Integer,
+ ForeignKey("elements.element_id"),
+ primary_key=True,
+ ),
+ Column("name", Unicode(100), nullable=False, primary_key=True),
+ Column("value", Unicode(255)),
+)
meta.create_all(e)
@@ -68,6 +89,7 @@ class Document(object):
self.element.write(buf)
return buf.getvalue()
+
#################################### PART IV - Persistence Mapping #################################
# Node class. a non-public class which will represent
@@ -78,6 +100,7 @@ class Document(object):
class _Node(object):
pass
+
# Attribute class. also internal, this will represent the key/value attributes stored for
# a particular Node.
class _Attribute(object):
@@ -85,16 +108,25 @@ class _Attribute(object):
self.name = name
self.value = value
+
# setup mappers. Document will eagerly load a list of _Node objects.
-mapper(Document, documents, properties={
- '_root':relationship(_Node, lazy='joined', cascade="all")
-})
+mapper(
+ Document,
+ documents,
+ properties={"_root": relationship(_Node, lazy="joined", cascade="all")},
+)
-mapper(_Node, elements, properties={
- 'children':relationship(_Node, cascade="all"),
- # eagerly load attributes
- 'attributes':relationship(_Attribute, lazy='joined', cascade="all, delete-orphan"),
-})
+mapper(
+ _Node,
+ elements,
+ properties={
+ "children": relationship(_Node, cascade="all"),
+ # eagerly load attributes
+ "attributes": relationship(
+ _Attribute, lazy="joined", cascade="all, delete-orphan"
+ ),
+ },
+)
mapper(_Attribute, attributes)
@@ -106,7 +138,7 @@ class ElementTreeMarshal(object):
if document is None:
return self
- if hasattr(document, '_element'):
+ if hasattr(document, "_element"):
return document._element
def traverse(node, parent=None):
@@ -132,7 +164,9 @@ class ElementTreeMarshal(object):
n.text = str(node.text)
n.tail = str(node.tail)
n.children = [traverse(n2) for n2 in node]
- n.attributes = [_Attribute(str(k), str(v)) for k, v in node.attrib.items()]
+ n.attributes = [
+ _Attribute(str(k), str(v)) for k, v in node.attrib.items()
+ ]
return n
document._root = traverse(element.getroot())
@@ -142,6 +176,7 @@ class ElementTreeMarshal(object):
del document._element
document._root = []
+
# override Document's "element" attribute with the marshaller.
Document.element = ElementTreeMarshal()
@@ -153,7 +188,7 @@ line = "\n--------------------------------------------------------"
session = Session(e)
# get ElementTree documents
-for file in ('test.xml', 'test2.xml', 'test3.xml'):
+for file in ("test.xml", "test2.xml", "test3.xml"):
filename = os.path.join(os.path.dirname(__file__), file)
doc = ElementTree.parse(filename)
session.add(Document(file, doc))
@@ -170,10 +205,16 @@ print(document)
############################################ PART VI - Searching for Paths #########################
# manually search for a document which contains "/somefile/header/field1:hi"
-d = session.query(Document).join('_root', aliased=True).filter(_Node.tag=='somefile').\
- join('children', aliased=True, from_joinpoint=True).filter(_Node.tag=='header').\
- join('children', aliased=True, from_joinpoint=True).filter(
- and_(_Node.tag=='field1', _Node.text=='hi')).one()
+d = (
+ session.query(Document)
+ .join("_root", aliased=True)
+ .filter(_Node.tag == "somefile")
+ .join("children", aliased=True, from_joinpoint=True)
+ .filter(_Node.tag == "header")
+ .join("children", aliased=True, from_joinpoint=True)
+ .filter(and_(_Node.tag == "field1", _Node.text == "hi"))
+ .one()
+)
print(d)
# generalize the above approach into an extremely impoverished xpath function:
@@ -181,26 +222,39 @@ def find_document(path, compareto):
j = documents
prev_elements = None
query = session.query(Document)
- attribute = '_root'
- for i, match in enumerate(re.finditer(r'/([\w_]+)(?:\[@([\w_]+)(?:=(.*))?\])?', path)):
+ attribute = "_root"
+ for i, match in enumerate(
+ re.finditer(r"/([\w_]+)(?:\[@([\w_]+)(?:=(.*))?\])?", path)
+ ):
(token, attrname, attrvalue) = match.group(1, 2, 3)
- query = query.join(attribute, aliased=True, from_joinpoint=True).filter(_Node.tag==token)
- attribute = 'children'
+ query = query.join(
+ attribute, aliased=True, from_joinpoint=True
+ ).filter(_Node.tag == token)
+ attribute = "children"
if attrname:
if attrvalue:
- query = query.join('attributes', aliased=True, from_joinpoint=True).filter(
- and_(_Attribute.name==attrname, _Attribute.value==attrvalue))
+ query = query.join(
+ "attributes", aliased=True, from_joinpoint=True
+ ).filter(
+ and_(
+ _Attribute.name == attrname,
+ _Attribute.value == attrvalue,
+ )
+ )
else:
- query = query.join('attributes', aliased=True, from_joinpoint=True).filter(
- _Attribute.name==attrname)
- return query.options(lazyload('_root')).filter(_Node.text==compareto).all()
+ query = query.join(
+ "attributes", aliased=True, from_joinpoint=True
+ ).filter(_Attribute.name == attrname)
+ return (
+ query.options(lazyload("_root")).filter(_Node.text == compareto).all()
+ )
+
for path, compareto in (
- ('/somefile/header/field1', 'hi'),
- ('/somefile/field1', 'hi'),
- ('/somefile/header/field2', 'there'),
- ('/somefile/header/field2[@attr=foo]', 'there')
- ):
+ ("/somefile/header/field1", "hi"),
+ ("/somefile/field1", "hi"),
+ ("/somefile/header/field2", "there"),
+ ("/somefile/header/field2[@attr=foo]", "there"),
+):
print("\nDocuments containing '%s=%s':" % (path, compareto), line)
print([d.filename for d in find_document(path, compareto)])
-
diff --git a/examples/elementtree/optimized_al.py b/examples/elementtree/optimized_al.py
index e13f5b0ee..8e9c48b96 100644
--- a/examples/elementtree/optimized_al.py
+++ b/examples/elementtree/optimized_al.py
@@ -8,42 +8,63 @@
"""
##################### PART I - Imports/Configuration #########################
-from sqlalchemy import (MetaData, Table, Column, Integer, String, ForeignKey,
- Unicode, and_, create_engine)
+from sqlalchemy import (
+ MetaData,
+ Table,
+ Column,
+ Integer,
+ String,
+ ForeignKey,
+ Unicode,
+ and_,
+ create_engine,
+)
from sqlalchemy.orm import mapper, relationship, Session, lazyload
import sys, os, io, re
from xml.etree import ElementTree
-e = create_engine('sqlite://', echo=True)
+e = create_engine("sqlite://", echo=True)
meta = MetaData()
####################### PART II - Table Metadata #############################
# 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),
+documents = Table(
+ "documents",
+ meta,
+ Column("document_id", Integer, primary_key=True),
+ Column("filename", String(30), unique=True),
)
# stores XML nodes in an adjacency list model. This corresponds to
# Element and SubElement objects.
-elements = Table('elements', meta,
- Column('element_id', Integer, primary_key=True),
- Column('parent_id', Integer, ForeignKey('elements.element_id')),
- Column('document_id', Integer, ForeignKey('documents.document_id')),
- Column('tag', Unicode(30), nullable=False),
- Column('text', Unicode),
- Column('tail', Unicode)
- )
+elements = Table(
+ "elements",
+ meta,
+ Column("element_id", Integer, primary_key=True),
+ Column("parent_id", Integer, ForeignKey("elements.element_id")),
+ Column("document_id", Integer, ForeignKey("documents.document_id")),
+ Column("tag", Unicode(30), nullable=False),
+ Column("text", Unicode),
+ Column("tail", Unicode),
+)
# stores attributes. This corresponds to the dictionary of attributes
# stored by an Element or SubElement.
-attributes = Table('attributes', meta,
- Column('element_id', Integer, ForeignKey('elements.element_id'), primary_key=True),
- Column('name', Unicode(100), nullable=False, primary_key=True),
- Column('value', Unicode(255)))
+attributes = Table(
+ "attributes",
+ meta,
+ Column(
+ "element_id",
+ Integer,
+ ForeignKey("elements.element_id"),
+ primary_key=True,
+ ),
+ Column("name", Unicode(100), nullable=False, primary_key=True),
+ Column("value", Unicode(255)),
+)
meta.create_all(e)
@@ -61,6 +82,7 @@ class Document(object):
self.element.write(buf)
return buf.getvalue()
+
########################## PART IV - Persistence Mapping #####################
# Node class. a non-public class which will represent
@@ -71,6 +93,7 @@ class Document(object):
class _Node(object):
pass
+
# Attribute class. also internal, this will represent the key/value attributes stored for
# a particular Node.
class _Attribute(object):
@@ -78,21 +101,36 @@ class _Attribute(object):
self.name = name
self.value = value
+
# setup mappers. Document will eagerly load a list of _Node objects.
# they will be ordered in primary key/insert order, so that we can reconstruct
# an ElementTree structure from the list.
-mapper(Document, documents, properties={
- '_nodes':relationship(_Node, lazy='joined', cascade="all, delete-orphan")
-})
+mapper(
+ Document,
+ documents,
+ properties={
+ "_nodes": relationship(
+ _Node, lazy="joined", cascade="all, delete-orphan"
+ )
+ },
+)
# the _Node objects change the way they load so that a list of _Nodes will organize
# themselves hierarchically using the ElementTreeMarshal. this depends on the ordering of
# nodes being hierarchical as well; relationship() always applies at least ROWID/primary key
# ordering to rows which will suffice.
-mapper(_Node, elements, properties={
- 'children':relationship(_Node, lazy=None), # doesnt load; used only for the save relationship
- 'attributes':relationship(_Attribute, lazy='joined', cascade="all, delete-orphan"), # eagerly load attributes
-})
+mapper(
+ _Node,
+ elements,
+ properties={
+ "children": relationship(
+ _Node, lazy=None
+ ), # doesnt load; used only for the save relationship
+ "attributes": relationship(
+ _Attribute, lazy="joined", cascade="all, delete-orphan"
+ ), # eagerly load attributes
+ },
+)
mapper(_Attribute, attributes)
@@ -104,7 +142,7 @@ class ElementTreeMarshal(object):
if document is None:
return self
- if hasattr(document, '_element'):
+ if hasattr(document, "_element"):
return document._element
nodes = {}
@@ -134,7 +172,9 @@ class ElementTreeMarshal(object):
n.tail = str(node.tail)
document._nodes.append(n)
n.children = [traverse(n2) for n2 in node]
- n.attributes = [_Attribute(str(k), str(v)) for k, v in node.attrib.items()]
+ n.attributes = [
+ _Attribute(str(k), str(v)) for k, v in node.attrib.items()
+ ]
return n
traverse(element.getroot())
@@ -144,6 +184,7 @@ class ElementTreeMarshal(object):
del document._element
document._nodes = []
+
# override Document's "element" attribute with the marshaller.
Document.element = ElementTreeMarshal()
@@ -155,7 +196,7 @@ line = "\n--------------------------------------------------------"
session = Session(e)
# get ElementTree documents
-for file in ('test.xml', 'test2.xml', 'test3.xml'):
+for file in ("test.xml", "test2.xml", "test3.xml"):
filename = os.path.join(os.path.dirname(__file__), file)
doc = ElementTree.parse(filename)
session.add(Document(file, doc))
@@ -173,13 +214,16 @@ print(document)
# manually search for a document which contains "/somefile/header/field1:hi"
print("\nManual search for /somefile/header/field1=='hi':", line)
-d = session.query(Document).join('_nodes', aliased=True).\
- filter(and_(_Node.parent_id==None, _Node.tag=='somefile')).\
- join('children', aliased=True, from_joinpoint=True).\
- filter(_Node.tag=='header').\
- join('children', aliased=True, from_joinpoint=True).\
- filter(and_(_Node.tag=='field1', _Node.text=='hi')).\
- one()
+d = (
+ session.query(Document)
+ .join("_nodes", aliased=True)
+ .filter(and_(_Node.parent_id == None, _Node.tag == "somefile"))
+ .join("children", aliased=True, from_joinpoint=True)
+ .filter(_Node.tag == "header")
+ .join("children", aliased=True, from_joinpoint=True)
+ .filter(and_(_Node.tag == "field1", _Node.text == "hi"))
+ .one()
+)
print(d)
# generalize the above approach into an extremely impoverished xpath function:
@@ -188,28 +232,39 @@ def find_document(path, compareto):
prev_elements = None
query = session.query(Document)
first = True
- for i, match in enumerate(re.finditer(r'/([\w_]+)(?:\[@([\w_]+)(?:=(.*))?\])?', path)):
+ for i, match in enumerate(
+ re.finditer(r"/([\w_]+)(?:\[@([\w_]+)(?:=(.*))?\])?", path)
+ ):
(token, attrname, attrvalue) = match.group(1, 2, 3)
if first:
- query = query.join('_nodes', aliased=True).filter(_Node.parent_id==None)
+ query = query.join("_nodes", aliased=True).filter(
+ _Node.parent_id == None
+ )
first = False
else:
- query = query.join('children', aliased=True, from_joinpoint=True)
- query = query.filter(_Node.tag==token)
+ query = query.join("children", aliased=True, from_joinpoint=True)
+ query = query.filter(_Node.tag == token)
if attrname:
- query = query.join('attributes', aliased=True, from_joinpoint=True)
+ query = query.join("attributes", aliased=True, from_joinpoint=True)
if attrvalue:
- query = query.filter(and_(_Attribute.name==attrname, _Attribute.value==attrvalue))
+ query = query.filter(
+ and_(
+ _Attribute.name == attrname,
+ _Attribute.value == attrvalue,
+ )
+ )
else:
- query = query.filter(_Attribute.name==attrname)
- return query.options(lazyload('_nodes')).filter(_Node.text==compareto).all()
+ query = query.filter(_Attribute.name == attrname)
+ return (
+ query.options(lazyload("_nodes")).filter(_Node.text == compareto).all()
+ )
+
for path, compareto in (
- ('/somefile/header/field1', 'hi'),
- ('/somefile/field1', 'hi'),
- ('/somefile/header/field2', 'there'),
- ('/somefile/header/field2[@attr=foo]', 'there')
- ):
+ ("/somefile/header/field1", "hi"),
+ ("/somefile/field1", "hi"),
+ ("/somefile/header/field2", "there"),
+ ("/somefile/header/field2[@attr=foo]", "there"),
+):
print("\nDocuments containing '%s=%s':" % (path, compareto), line)
print([d.filename for d in find_document(path, compareto)])
-
diff --git a/examples/elementtree/pickle.py b/examples/elementtree/pickle.py
index d40af275b..a86fe30e5 100644
--- a/examples/elementtree/pickle.py
+++ b/examples/elementtree/pickle.py
@@ -6,15 +6,22 @@ structure in distinct rows using two additional mapped entities. Note that the
styles of persistence are identical, as is the structure of the main Document class.
"""
-from sqlalchemy import (create_engine, MetaData, Table, Column, Integer, String,
- PickleType)
+from sqlalchemy import (
+ create_engine,
+ MetaData,
+ Table,
+ Column,
+ Integer,
+ String,
+ PickleType,
+)
from sqlalchemy.orm import mapper, Session
import sys, os
from xml.etree import ElementTree
-e = create_engine('sqlite://')
+e = create_engine("sqlite://")
meta = MetaData()
# setup a comparator for the PickleType since it's a mutable
@@ -22,12 +29,15 @@ meta = MetaData()
def are_elements_equal(x, y):
return x == y
+
# 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),
- Column('filename', String(30), unique=True),
- Column('element', PickleType(comparator=are_elements_equal))
+documents = Table(
+ "documents",
+ meta,
+ Column("document_id", Integer, primary_key=True),
+ Column("filename", String(30), unique=True),
+ Column("element", PickleType(comparator=are_elements_equal)),
)
meta.create_all(e)
@@ -39,6 +49,7 @@ class Document(object):
self.filename = name
self.element = element
+
# setup mapper.
mapper(Document, documents)
@@ -58,4 +69,3 @@ document = session.query(Document).filter_by(filename="test.xml").first()
# print
document.element.write(sys.stdout)
-
diff --git a/examples/generic_associations/__init__.py b/examples/generic_associations/__init__.py
index b6593b4f4..9d103b73e 100644
--- a/examples/generic_associations/__init__.py
+++ b/examples/generic_associations/__init__.py
@@ -15,4 +15,4 @@ are modernized versions of recipes presented in the 2007 blog post
.. autosource::
-""" \ No newline at end of file
+"""
diff --git a/examples/generic_associations/discriminator_on_association.py b/examples/generic_associations/discriminator_on_association.py
index c3501eefb..38f2370f3 100644
--- a/examples/generic_associations/discriminator_on_association.py
+++ b/examples/generic_associations/discriminator_on_association.py
@@ -16,27 +16,31 @@ objects, but is also slightly more complex.
"""
from sqlalchemy.ext.declarative import as_declarative, declared_attr
-from sqlalchemy import create_engine, Integer, Column, \
- String, ForeignKey
+from sqlalchemy import create_engine, Integer, Column, String, ForeignKey
from sqlalchemy.orm import Session, relationship, backref
from sqlalchemy.ext.associationproxy import association_proxy
+
@as_declarative()
class Base(object):
"""Base class which provides automated table name
and surrogate primary key column.
"""
+
@declared_attr
def __tablename__(cls):
return cls.__name__.lower()
+
id = Column(Integer, primary_key=True)
+
class AddressAssociation(Base):
"""Associates a collection of Address objects
with a particular parent.
"""
+
__tablename__ = "address_association"
discriminator = Column(String)
@@ -44,6 +48,7 @@ class AddressAssociation(Base):
__mapper_args__ = {"polymorphic_on": discriminator}
+
class Address(Base):
"""The Address class.
@@ -51,6 +56,7 @@ class Address(Base):
single table.
"""
+
association_id = Column(Integer, ForeignKey("address_association.id"))
street = Column(String)
city = Column(String)
@@ -60,15 +66,20 @@ class Address(Base):
parent = association_proxy("association", "parent")
def __repr__(self):
- return "%s(street=%r, city=%r, zip=%r)" % \
- (self.__class__.__name__, self.street,
- self.city, self.zip)
+ return "%s(street=%r, city=%r, zip=%r)" % (
+ self.__class__.__name__,
+ self.street,
+ self.city,
+ self.zip,
+ )
+
class HasAddresses(object):
"""HasAddresses mixin, creates a relationship to
the address_association table for each parent.
"""
+
@declared_attr
def address_association_id(cls):
return Column(Integer, ForeignKey("address_association.id"))
@@ -79,63 +90,62 @@ class HasAddresses(object):
discriminator = name.lower()
assoc_cls = type(
- "%sAddressAssociation" % name,
- (AddressAssociation, ),
- dict(
- __tablename__=None,
- __mapper_args__={
- "polymorphic_identity": discriminator
- }
- )
- )
+ "%sAddressAssociation" % name,
+ (AddressAssociation,),
+ dict(
+ __tablename__=None,
+ __mapper_args__={"polymorphic_identity": discriminator},
+ ),
+ )
cls.addresses = association_proxy(
- "address_association", "addresses",
- creator=lambda addresses: assoc_cls(addresses=addresses)
- )
- return relationship(assoc_cls,
- backref=backref("parent", uselist=False))
+ "address_association",
+ "addresses",
+ creator=lambda addresses: assoc_cls(addresses=addresses),
+ )
+ return relationship(
+ assoc_cls, backref=backref("parent", uselist=False)
+ )
class Customer(HasAddresses, Base):
name = Column(String)
+
class Supplier(HasAddresses, Base):
company_name = Column(String)
-engine = create_engine('sqlite://', echo=True)
+
+engine = create_engine("sqlite://", echo=True)
Base.metadata.create_all(engine)
session = Session(engine)
-session.add_all([
- Customer(
- name='customer 1',
- addresses=[
- Address(
- street='123 anywhere street',
- city="New York",
- zip="10110"),
- Address(
- street='40 main street',
- city="San Francisco",
- zip="95732")
- ]
- ),
- Supplier(
- company_name="Ace Hammers",
- addresses=[
- Address(
- street='2569 west elm',
- city="Detroit",
- zip="56785")
- ]
- ),
-])
+session.add_all(
+ [
+ Customer(
+ name="customer 1",
+ addresses=[
+ Address(
+ street="123 anywhere street", city="New York", zip="10110"
+ ),
+ Address(
+ street="40 main street", city="San Francisco", zip="95732"
+ ),
+ ],
+ ),
+ Supplier(
+ company_name="Ace Hammers",
+ addresses=[
+ Address(street="2569 west elm", city="Detroit", zip="56785")
+ ],
+ ),
+ ]
+)
session.commit()
for customer in session.query(Customer):
for address in customer.addresses:
print(address)
- print(address.parent) \ No newline at end of file
+ print(address.parent)
diff --git a/examples/generic_associations/generic_fk.py b/examples/generic_associations/generic_fk.py
index 31d2c138d..ded8f749d 100644
--- a/examples/generic_associations/generic_fk.py
+++ b/examples/generic_associations/generic_fk.py
@@ -20,8 +20,7 @@ or "table_per_association" instead of this approach.
"""
from sqlalchemy.ext.declarative import as_declarative, declared_attr
-from sqlalchemy import create_engine, Integer, Column, \
- String, and_
+from sqlalchemy import create_engine, Integer, Column, String, and_
from sqlalchemy.orm import Session, relationship, foreign, remote, backref
from sqlalchemy import event
@@ -32,11 +31,14 @@ class Base(object):
and surrogate primary key column.
"""
+
@declared_attr
def __tablename__(cls):
return cls.__name__.lower()
+
id = Column(Integer, primary_key=True)
+
class Address(Base):
"""The Address class.
@@ -44,6 +46,7 @@ class Address(Base):
single table.
"""
+
street = Column(String)
city = Column(String)
zip = Column(String)
@@ -66,9 +69,13 @@ class Address(Base):
return getattr(self, "parent_%s" % self.discriminator)
def __repr__(self):
- return "%s(street=%r, city=%r, zip=%r)" % \
- (self.__class__.__name__, self.street,
- self.city, self.zip)
+ return "%s(street=%r, city=%r, zip=%r)" % (
+ self.__class__.__name__,
+ self.street,
+ self.city,
+ self.zip,
+ )
+
class HasAddresses(object):
"""HasAddresses mixin, creates a relationship to
@@ -76,63 +83,66 @@ class HasAddresses(object):
"""
+
@event.listens_for(HasAddresses, "mapper_configured", propagate=True)
def setup_listener(mapper, class_):
name = class_.__name__
discriminator = name.lower()
- class_.addresses = relationship(Address,
- primaryjoin=and_(
- class_.id == foreign(remote(Address.parent_id)),
- Address.discriminator == discriminator
- ),
- backref=backref(
- "parent_%s" % discriminator,
- primaryjoin=remote(class_.id) == foreign(Address.parent_id)
- )
- )
+ class_.addresses = relationship(
+ Address,
+ primaryjoin=and_(
+ class_.id == foreign(remote(Address.parent_id)),
+ Address.discriminator == discriminator,
+ ),
+ backref=backref(
+ "parent_%s" % discriminator,
+ primaryjoin=remote(class_.id) == foreign(Address.parent_id),
+ ),
+ )
+
@event.listens_for(class_.addresses, "append")
def append_address(target, value, initiator):
value.discriminator = discriminator
+
class Customer(HasAddresses, Base):
name = Column(String)
+
class Supplier(HasAddresses, Base):
company_name = Column(String)
-engine = create_engine('sqlite://', echo=True)
+
+engine = create_engine("sqlite://", echo=True)
Base.metadata.create_all(engine)
session = Session(engine)
-session.add_all([
- Customer(
- name='customer 1',
- addresses=[
- Address(
- street='123 anywhere street',
- city="New York",
- zip="10110"),
- Address(
- street='40 main street',
- city="San Francisco",
- zip="95732")
- ]
- ),
- Supplier(
- company_name="Ace Hammers",
- addresses=[
- Address(
- street='2569 west elm',
- city="Detroit",
- zip="56785")
- ]
- ),
-])
+session.add_all(
+ [
+ Customer(
+ name="customer 1",
+ addresses=[
+ Address(
+ street="123 anywhere street", city="New York", zip="10110"
+ ),
+ Address(
+ street="40 main street", city="San Francisco", zip="95732"
+ ),
+ ],
+ ),
+ Supplier(
+ company_name="Ace Hammers",
+ addresses=[
+ Address(street="2569 west elm", city="Detroit", zip="56785")
+ ],
+ ),
+ ]
+)
session.commit()
for customer in session.query(Customer):
for address in customer.addresses:
print(address)
- print(address.parent) \ No newline at end of file
+ print(address.parent)
diff --git a/examples/generic_associations/table_per_association.py b/examples/generic_associations/table_per_association.py
index d54d2f1fa..7de246934 100644
--- a/examples/generic_associations/table_per_association.py
+++ b/examples/generic_associations/table_per_association.py
@@ -12,21 +12,31 @@ has no dependency on the system.
"""
from sqlalchemy.ext.declarative import as_declarative, declared_attr
-from sqlalchemy import create_engine, Integer, Column, \
- String, ForeignKey, Table
+from sqlalchemy import (
+ create_engine,
+ Integer,
+ Column,
+ String,
+ ForeignKey,
+ Table,
+)
from sqlalchemy.orm import Session, relationship
+
@as_declarative()
class Base(object):
"""Base class which provides automated table name
and surrogate primary key column.
"""
+
@declared_attr
def __tablename__(cls):
return cls.__name__.lower()
+
id = Column(Integer, primary_key=True)
+
class Address(Base):
"""The Address class.
@@ -34,72 +44,79 @@ class Address(Base):
single table.
"""
+
street = Column(String)
city = Column(String)
zip = Column(String)
def __repr__(self):
- return "%s(street=%r, city=%r, zip=%r)" % \
- (self.__class__.__name__, self.street,
- self.city, self.zip)
+ return "%s(street=%r, city=%r, zip=%r)" % (
+ self.__class__.__name__,
+ self.street,
+ self.city,
+ self.zip,
+ )
+
class HasAddresses(object):
"""HasAddresses mixin, creates a new address_association
table for each parent.
"""
+
@declared_attr
def addresses(cls):
address_association = Table(
"%s_addresses" % cls.__tablename__,
cls.metadata,
- Column("address_id", ForeignKey("address.id"),
- primary_key=True),
- Column("%s_id" % cls.__tablename__,
- ForeignKey("%s.id" % cls.__tablename__),
- primary_key=True),
+ Column("address_id", ForeignKey("address.id"), primary_key=True),
+ Column(
+ "%s_id" % cls.__tablename__,
+ ForeignKey("%s.id" % cls.__tablename__),
+ primary_key=True,
+ ),
)
return relationship(Address, secondary=address_association)
+
class Customer(HasAddresses, Base):
name = Column(String)
+
class Supplier(HasAddresses, Base):
company_name = Column(String)
-engine = create_engine('sqlite://', echo=True)
+
+engine = create_engine("sqlite://", echo=True)
Base.metadata.create_all(engine)
session = Session(engine)
-session.add_all([
- Customer(
- name='customer 1',
- addresses=[
- Address(
- street='123 anywhere street',
- city="New York",
- zip="10110"),
- Address(
- street='40 main street',
- city="San Francisco",
- zip="95732")
- ]
- ),
- Supplier(
- company_name="Ace Hammers",
- addresses=[
- Address(
- street='2569 west elm',
- city="Detroit",
- zip="56785")
- ]
- ),
-])
+session.add_all(
+ [
+ Customer(
+ name="customer 1",
+ addresses=[
+ Address(
+ street="123 anywhere street", city="New York", zip="10110"
+ ),
+ Address(
+ street="40 main street", city="San Francisco", zip="95732"
+ ),
+ ],
+ ),
+ Supplier(
+ company_name="Ace Hammers",
+ addresses=[
+ Address(street="2569 west elm", city="Detroit", zip="56785")
+ ],
+ ),
+ ]
+)
session.commit()
for customer in session.query(Customer):
for address in customer.addresses:
print(address)
- # no parent here \ No newline at end of file
+ # no parent here
diff --git a/examples/generic_associations/table_per_related.py b/examples/generic_associations/table_per_related.py
index 51c9f1b26..9c5e0e179 100644
--- a/examples/generic_associations/table_per_related.py
+++ b/examples/generic_associations/table_per_related.py
@@ -20,17 +20,21 @@ from sqlalchemy.ext.declarative import as_declarative, declared_attr
from sqlalchemy import create_engine, Integer, Column, String, ForeignKey
from sqlalchemy.orm import Session, relationship
+
@as_declarative()
class Base(object):
"""Base class which provides automated table name
and surrogate primary key column.
"""
+
@declared_attr
def __tablename__(cls):
return cls.__name__.lower()
+
id = Column(Integer, primary_key=True)
+
class Address(object):
"""Define columns that will be present in each
'Address' table.
@@ -40,74 +44,82 @@ class Address(object):
should be set up using @declared_attr.
"""
+
street = Column(String)
city = Column(String)
zip = Column(String)
def __repr__(self):
- return "%s(street=%r, city=%r, zip=%r)" % \
- (self.__class__.__name__, self.street,
- self.city, self.zip)
+ return "%s(street=%r, city=%r, zip=%r)" % (
+ self.__class__.__name__,
+ self.street,
+ self.city,
+ self.zip,
+ )
+
class HasAddresses(object):
"""HasAddresses mixin, creates a new Address class
for each parent.
"""
+
@declared_attr
def addresses(cls):
cls.Address = type(
"%sAddress" % cls.__name__,
- (Address, Base,),
+ (Address, Base),
dict(
- __tablename__="%s_address" %
- cls.__tablename__,
- parent_id=Column(Integer,
- ForeignKey("%s.id" % cls.__tablename__)),
- parent=relationship(cls)
- )
+ __tablename__="%s_address" % cls.__tablename__,
+ parent_id=Column(
+ Integer, ForeignKey("%s.id" % cls.__tablename__)
+ ),
+ parent=relationship(cls),
+ ),
)
return relationship(cls.Address)
+
class Customer(HasAddresses, Base):
name = Column(String)
+
class Supplier(HasAddresses, Base):
company_name = Column(String)
-engine = create_engine('sqlite://', echo=True)
+
+engine = create_engine("sqlite://", echo=True)
Base.metadata.create_all(engine)
session = Session(engine)
-session.add_all([
- Customer(
- name='customer 1',
- addresses=[
- Customer.Address(
- street='123 anywhere street',
- city="New York",
- zip="10110"),
- Customer.Address(
- street='40 main street',
- city="San Francisco",
- zip="95732")
- ]
- ),
- Supplier(
- company_name="Ace Hammers",
- addresses=[
- Supplier.Address(
- street='2569 west elm',
- city="Detroit",
- zip="56785")
- ]
- ),
-])
+session.add_all(
+ [
+ Customer(
+ name="customer 1",
+ addresses=[
+ Customer.Address(
+ street="123 anywhere street", city="New York", zip="10110"
+ ),
+ Customer.Address(
+ street="40 main street", city="San Francisco", zip="95732"
+ ),
+ ],
+ ),
+ Supplier(
+ company_name="Ace Hammers",
+ addresses=[
+ Supplier.Address(
+ street="2569 west elm", city="Detroit", zip="56785"
+ )
+ ],
+ ),
+ ]
+)
session.commit()
for customer in session.query(Customer):
for address in customer.addresses:
print(address)
- print(address.parent) \ No newline at end of file
+ print(address.parent)
diff --git a/examples/graphs/__init__.py b/examples/graphs/__init__.py
index 57d41453b..0f8fe58a7 100644
--- a/examples/graphs/__init__.py
+++ b/examples/graphs/__init__.py
@@ -10,4 +10,4 @@ and querying for lower- and upper- neighbors are illustrated::
.. autosource::
-""" \ No newline at end of file
+"""
diff --git a/examples/graphs/directed_graph.py b/examples/graphs/directed_graph.py
index 7bcfc5683..af85a4295 100644
--- a/examples/graphs/directed_graph.py
+++ b/examples/graphs/directed_graph.py
@@ -1,7 +1,6 @@
"""a directed graph example."""
-from sqlalchemy import Column, Integer, ForeignKey, \
- create_engine
+from sqlalchemy import Column, Integer, ForeignKey, create_engine
from sqlalchemy.orm import relationship, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
@@ -9,7 +8,7 @@ Base = declarative_base()
class Node(Base):
- __tablename__ = 'node'
+ __tablename__ = "node"
node_id = Column(Integer, primary_key=True)
@@ -21,33 +20,26 @@ class Node(Base):
class Edge(Base):
- __tablename__ = 'edge'
+ __tablename__ = "edge"
- lower_id = Column(
- Integer,
- ForeignKey('node.node_id'),
- primary_key=True)
+ lower_id = Column(Integer, ForeignKey("node.node_id"), primary_key=True)
- higher_id = Column(
- Integer,
- ForeignKey('node.node_id'),
- primary_key=True)
+ higher_id = Column(Integer, ForeignKey("node.node_id"), primary_key=True)
lower_node = relationship(
- Node,
- primaryjoin=lower_id == Node.node_id,
- backref='lower_edges')
+ Node, primaryjoin=lower_id == Node.node_id, backref="lower_edges"
+ )
higher_node = relationship(
- Node,
- primaryjoin=higher_id == Node.node_id,
- backref='higher_edges')
+ Node, primaryjoin=higher_id == Node.node_id, backref="higher_edges"
+ )
def __init__(self, n1, n2):
self.lower_node = n1
self.higher_node = n2
-engine = create_engine('sqlite://', echo=True)
+
+engine = create_engine("sqlite://", echo=True)
Base.metadata.create_all(engine)
session = sessionmaker(engine)()
@@ -80,4 +72,3 @@ assert [x for x in n3.higher_neighbors()] == [n6]
assert [x for x in n3.lower_neighbors()] == [n1]
assert [x for x in n2.lower_neighbors()] == [n1]
assert [x for x in n2.higher_neighbors()] == [n1, n5, n7]
-
diff --git a/examples/inheritance/concrete.py b/examples/inheritance/concrete.py
index 258f41025..2245aa4e0 100644
--- a/examples/inheritance/concrete.py
+++ b/examples/inheritance/concrete.py
@@ -1,7 +1,14 @@
"""Concrete-table (table-per-class) inheritance example."""
-from sqlalchemy import Column, Integer, String, \
- ForeignKey, create_engine, inspect, or_
+from sqlalchemy import (
+ Column,
+ Integer,
+ String,
+ ForeignKey,
+ create_engine,
+ inspect,
+ or_,
+)
from sqlalchemy.orm import relationship, Session, with_polymorphic
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.declarative import ConcreteBase
@@ -11,107 +18,105 @@ Base = declarative_base()
class Company(Base):
- __tablename__ = 'company'
+ __tablename__ = "company"
id = Column(Integer, primary_key=True)
name = Column(String(50))
employees = relationship(
- "Person",
- back_populates='company',
- cascade='all, delete-orphan')
+ "Person", back_populates="company", cascade="all, delete-orphan"
+ )
def __repr__(self):
return "Company %s" % self.name
class Person(ConcreteBase, Base):
- __tablename__ = 'person'
+ __tablename__ = "person"
id = Column(Integer, primary_key=True)
- company_id = Column(ForeignKey('company.id'))
+ company_id = Column(ForeignKey("company.id"))
name = Column(String(50))
company = relationship("Company", back_populates="employees")
- __mapper_args__ = {
- 'polymorphic_identity': 'person',
- }
+ __mapper_args__ = {"polymorphic_identity": "person"}
def __repr__(self):
return "Ordinary person %s" % self.name
class Engineer(Person):
- __tablename__ = 'engineer'
+ __tablename__ = "engineer"
id = Column(Integer, primary_key=True)
name = Column(String(50))
- company_id = Column(ForeignKey('company.id'))
+ company_id = Column(ForeignKey("company.id"))
status = Column(String(30))
engineer_name = Column(String(30))
primary_language = Column(String(30))
company = relationship("Company", back_populates="employees")
- __mapper_args__ = {
- 'polymorphic_identity': 'engineer',
- 'concrete': True
- }
+ __mapper_args__ = {"polymorphic_identity": "engineer", "concrete": True}
def __repr__(self):
return (
"Engineer %s, status %s, engineer_name %s, "
- "primary_language %s" %
- (
- self.name, self.status,
- self.engineer_name, self.primary_language)
+ "primary_language %s"
+ % (
+ self.name,
+ self.status,
+ self.engineer_name,
+ self.primary_language,
+ )
)
class Manager(Person):
- __tablename__ = 'manager'
+ __tablename__ = "manager"
id = Column(Integer, primary_key=True)
name = Column(String(50))
- company_id = Column(ForeignKey('company.id'))
+ company_id = Column(ForeignKey("company.id"))
status = Column(String(30))
manager_name = Column(String(30))
company = relationship("Company", back_populates="employees")
- __mapper_args__ = {
- 'polymorphic_identity': 'manager',
- 'concrete': True
- }
+ __mapper_args__ = {"polymorphic_identity": "manager", "concrete": True}
def __repr__(self):
return "Manager %s, status %s, manager_name %s" % (
- self.name, self.status, self.manager_name)
+ self.name,
+ self.status,
+ self.manager_name,
+ )
-engine = create_engine('sqlite://', echo=True)
+engine = create_engine("sqlite://", echo=True)
Base.metadata.create_all(engine)
session = Session(engine)
-c = Company(name='company1', employees=[
- Manager(
- name='pointy haired boss',
- status='AAB',
- manager_name='manager1'),
- Engineer(
- name='dilbert',
- status='BBA',
- engineer_name='engineer1',
- primary_language='java'),
- Person(name='joesmith'),
- Engineer(
- name='wally',
- status='CGG',
- engineer_name='engineer2',
- primary_language='python'),
- Manager(
- name='jsmith',
- status='ABA',
- manager_name='manager2')
-])
+c = Company(
+ name="company1",
+ employees=[
+ Manager(
+ name="pointy haired boss", status="AAB", manager_name="manager1"
+ ),
+ Engineer(
+ name="dilbert",
+ status="BBA",
+ engineer_name="engineer1",
+ primary_language="java",
+ ),
+ Person(name="joesmith"),
+ Engineer(
+ name="wally",
+ status="CGG",
+ engineer_name="engineer2",
+ primary_language="python",
+ ),
+ Manager(name="jsmith", status="ABA", manager_name="manager2"),
+ ],
+)
session.add(c)
session.commit()
@@ -120,14 +125,15 @@ c = session.query(Company).get(1)
for e in c.employees:
print(e, inspect(e).key, e.company)
assert set([e.name for e in c.employees]) == set(
- ['pointy haired boss', 'dilbert', 'joesmith', 'wally', 'jsmith'])
+ ["pointy haired boss", "dilbert", "joesmith", "wally", "jsmith"]
+)
print("\n")
-dilbert = session.query(Person).filter_by(name='dilbert').one()
-dilbert2 = session.query(Engineer).filter_by(name='dilbert').one()
+dilbert = session.query(Person).filter_by(name="dilbert").one()
+dilbert2 = session.query(Engineer).filter_by(name="dilbert").one()
assert dilbert is dilbert2
-dilbert.engineer_name = 'hes dilbert!'
+dilbert.engineer_name = "hes dilbert!"
session.commit()
@@ -138,24 +144,28 @@ for e in c.employees:
# query using with_polymorphic.
eng_manager = with_polymorphic(Person, [Engineer, Manager])
print(
- session.query(eng_manager).
- filter(
+ session.query(eng_manager)
+ .filter(
or_(
- eng_manager.Engineer.engineer_name == 'engineer1',
- eng_manager.Manager.manager_name == 'manager2'
+ eng_manager.Engineer.engineer_name == "engineer1",
+ eng_manager.Manager.manager_name == "manager2",
)
- ).all()
+ )
+ .all()
)
# illustrate join from Company
eng_manager = with_polymorphic(Person, [Engineer, Manager])
print(
- session.query(Company).
- join(
- Company.employees.of_type(eng_manager)
- ).filter(
- or_(eng_manager.Engineer.engineer_name == 'engineer1',
- eng_manager.Manager.manager_name == 'manager2')
- ).all())
+ session.query(Company)
+ .join(Company.employees.of_type(eng_manager))
+ .filter(
+ or_(
+ eng_manager.Engineer.engineer_name == "engineer1",
+ eng_manager.Manager.manager_name == "manager2",
+ )
+ )
+ .all()
+)
session.commit()
diff --git a/examples/inheritance/joined.py b/examples/inheritance/joined.py
index f9322158e..a3a61d763 100644
--- a/examples/inheritance/joined.py
+++ b/examples/inheritance/joined.py
@@ -1,7 +1,14 @@
"""Joined-table (table-per-subclass) inheritance example."""
-from sqlalchemy import Column, Integer, String, \
- ForeignKey, create_engine, inspect, or_
+from sqlalchemy import (
+ Column,
+ Integer,
+ String,
+ ForeignKey,
+ create_engine,
+ inspect,
+ or_,
+)
from sqlalchemy.orm import relationship, Session, with_polymorphic
from sqlalchemy.ext.declarative import declarative_base
@@ -9,31 +16,30 @@ Base = declarative_base()
class Company(Base):
- __tablename__ = 'company'
+ __tablename__ = "company"
id = Column(Integer, primary_key=True)
name = Column(String(50))
employees = relationship(
- "Person",
- back_populates='company',
- cascade='all, delete-orphan')
+ "Person", back_populates="company", cascade="all, delete-orphan"
+ )
def __repr__(self):
return "Company %s" % self.name
class Person(Base):
- __tablename__ = 'person'
+ __tablename__ = "person"
id = Column(Integer, primary_key=True)
- company_id = Column(ForeignKey('company.id'))
+ company_id = Column(ForeignKey("company.id"))
name = Column(String(50))
type = Column(String(50))
company = relationship("Company", back_populates="employees")
__mapper_args__ = {
- 'polymorphic_identity': 'person',
- 'polymorphic_on': type
+ "polymorphic_identity": "person",
+ "polymorphic_on": type,
}
def __repr__(self):
@@ -41,67 +47,70 @@ class Person(Base):
class Engineer(Person):
- __tablename__ = 'engineer'
- id = Column(ForeignKey('person.id'), primary_key=True)
+ __tablename__ = "engineer"
+ id = Column(ForeignKey("person.id"), primary_key=True)
status = Column(String(30))
engineer_name = Column(String(30))
primary_language = Column(String(30))
- __mapper_args__ = {
- 'polymorphic_identity': 'engineer',
- }
+ __mapper_args__ = {"polymorphic_identity": "engineer"}
def __repr__(self):
return (
"Engineer %s, status %s, engineer_name %s, "
- "primary_language %s" %
- (
- self.name, self.status,
- self.engineer_name, self.primary_language)
+ "primary_language %s"
+ % (
+ self.name,
+ self.status,
+ self.engineer_name,
+ self.primary_language,
+ )
)
class Manager(Person):
- __tablename__ = 'manager'
- id = Column(ForeignKey('person.id'), primary_key=True)
+ __tablename__ = "manager"
+ id = Column(ForeignKey("person.id"), primary_key=True)
status = Column(String(30))
manager_name = Column(String(30))
- __mapper_args__ = {
- 'polymorphic_identity': 'manager',
- }
+ __mapper_args__ = {"polymorphic_identity": "manager"}
def __repr__(self):
return "Manager %s, status %s, manager_name %s" % (
- self.name, self.status, self.manager_name)
+ self.name,
+ self.status,
+ self.manager_name,
+ )
-engine = create_engine('sqlite://', echo=True)
+engine = create_engine("sqlite://", echo=True)
Base.metadata.create_all(engine)
session = Session(engine)
-c = Company(name='company1', employees=[
- Manager(
- name='pointy haired boss',
- status='AAB',
- manager_name='manager1'),
- Engineer(
- name='dilbert',
- status='BBA',
- engineer_name='engineer1',
- primary_language='java'),
- Person(name='joesmith'),
- Engineer(
- name='wally',
- status='CGG',
- engineer_name='engineer2',
- primary_language='python'),
- Manager(
- name='jsmith',
- status='ABA',
- manager_name='manager2')
-])
+c = Company(
+ name="company1",
+ employees=[
+ Manager(
+ name="pointy haired boss", status="AAB", manager_name="manager1"
+ ),
+ Engineer(
+ name="dilbert",
+ status="BBA",
+ engineer_name="engineer1",
+ primary_language="java",
+ ),
+ Person(name="joesmith"),
+ Engineer(
+ name="wally",
+ status="CGG",
+ engineer_name="engineer2",
+ primary_language="python",
+ ),
+ Manager(name="jsmith", status="ABA", manager_name="manager2"),
+ ],
+)
session.add(c)
session.commit()
@@ -110,14 +119,15 @@ c = session.query(Company).get(1)
for e in c.employees:
print(e, inspect(e).key, e.company)
assert set([e.name for e in c.employees]) == set(
- ['pointy haired boss', 'dilbert', 'joesmith', 'wally', 'jsmith'])
+ ["pointy haired boss", "dilbert", "joesmith", "wally", "jsmith"]
+)
print("\n")
-dilbert = session.query(Person).filter_by(name='dilbert').one()
-dilbert2 = session.query(Engineer).filter_by(name='dilbert').one()
+dilbert = session.query(Person).filter_by(name="dilbert").one()
+dilbert2 = session.query(Engineer).filter_by(name="dilbert").one()
assert dilbert is dilbert2
-dilbert.engineer_name = 'hes dilbert!'
+dilbert.engineer_name = "hes dilbert!"
session.commit()
@@ -128,13 +138,14 @@ for e in c.employees:
# query using with_polymorphic.
eng_manager = with_polymorphic(Person, [Engineer, Manager])
print(
- session.query(eng_manager).
- filter(
+ session.query(eng_manager)
+ .filter(
or_(
- eng_manager.Engineer.engineer_name == 'engineer1',
- eng_manager.Manager.manager_name == 'manager2'
+ eng_manager.Engineer.engineer_name == "engineer1",
+ eng_manager.Manager.manager_name == "manager2",
)
- ).all()
+ )
+ .all()
)
# illustrate join from Company.
@@ -144,12 +155,15 @@ print(
# loading.
eng_manager = with_polymorphic(Person, [Engineer, Manager], flat=True)
print(
- session.query(Company).
- join(
- Company.employees.of_type(eng_manager)
- ).filter(
- or_(eng_manager.Engineer.engineer_name == 'engineer1',
- eng_manager.Manager.manager_name == 'manager2')
- ).all())
+ session.query(Company)
+ .join(Company.employees.of_type(eng_manager))
+ .filter(
+ or_(
+ eng_manager.Engineer.engineer_name == "engineer1",
+ eng_manager.Manager.manager_name == "manager2",
+ )
+ )
+ .all()
+)
session.commit()
diff --git a/examples/inheritance/single.py b/examples/inheritance/single.py
index 56397f540..46d690c94 100644
--- a/examples/inheritance/single.py
+++ b/examples/inheritance/single.py
@@ -1,7 +1,14 @@
"""Single-table (table-per-hierarchy) inheritance example."""
-from sqlalchemy import Column, Integer, String, \
- ForeignKey, create_engine, inspect, or_
+from sqlalchemy import (
+ Column,
+ Integer,
+ String,
+ ForeignKey,
+ create_engine,
+ inspect,
+ or_,
+)
from sqlalchemy.orm import relationship, Session, with_polymorphic
from sqlalchemy.ext.declarative import declarative_base, declared_attr
@@ -9,31 +16,30 @@ Base = declarative_base()
class Company(Base):
- __tablename__ = 'company'
+ __tablename__ = "company"
id = Column(Integer, primary_key=True)
name = Column(String(50))
employees = relationship(
- "Person",
- back_populates='company',
- cascade='all, delete-orphan')
+ "Person", back_populates="company", cascade="all, delete-orphan"
+ )
def __repr__(self):
return "Company %s" % self.name
class Person(Base):
- __tablename__ = 'person'
+ __tablename__ = "person"
id = Column(Integer, primary_key=True)
- company_id = Column(ForeignKey('company.id'))
+ company_id = Column(ForeignKey("company.id"))
name = Column(String(50))
type = Column(String(50))
company = relationship("Company", back_populates="employees")
__mapper_args__ = {
- 'polymorphic_identity': 'person',
- 'polymorphic_on': type
+ "polymorphic_identity": "person",
+ "polymorphic_on": type,
}
def __repr__(self):
@@ -50,19 +56,20 @@ class Engineer(Person):
# declarative/inheritance.html#resolving-column-conflicts
@declared_attr
def status(cls):
- return Person.__table__.c.get('status', Column(String(30)))
+ return Person.__table__.c.get("status", Column(String(30)))
- __mapper_args__ = {
- 'polymorphic_identity': 'engineer',
- }
+ __mapper_args__ = {"polymorphic_identity": "engineer"}
def __repr__(self):
return (
"Engineer %s, status %s, engineer_name %s, "
- "primary_language %s" %
- (
- self.name, self.status,
- self.engineer_name, self.primary_language)
+ "primary_language %s"
+ % (
+ self.name,
+ self.status,
+ self.engineer_name,
+ self.primary_language,
+ )
)
@@ -71,43 +78,45 @@ class Manager(Person):
@declared_attr
def status(cls):
- return Person.__table__.c.get('status', Column(String(30)))
+ return Person.__table__.c.get("status", Column(String(30)))
- __mapper_args__ = {
- 'polymorphic_identity': 'manager',
- }
+ __mapper_args__ = {"polymorphic_identity": "manager"}
def __repr__(self):
return "Manager %s, status %s, manager_name %s" % (
- self.name, self.status, self.manager_name)
+ self.name,
+ self.status,
+ self.manager_name,
+ )
-engine = create_engine('sqlite://', echo=True)
+engine = create_engine("sqlite://", echo=True)
Base.metadata.create_all(engine)
session = Session(engine)
-c = Company(name='company1', employees=[
- Manager(
- name='pointy haired boss',
- status='AAB',
- manager_name='manager1'),
- Engineer(
- name='dilbert',
- status='BBA',
- engineer_name='engineer1',
- primary_language='java'),
- Person(name='joesmith'),
- Engineer(
- name='wally',
- status='CGG',
- engineer_name='engineer2',
- primary_language='python'),
- Manager(
- name='jsmith',
- status='ABA',
- manager_name='manager2')
-])
+c = Company(
+ name="company1",
+ employees=[
+ Manager(
+ name="pointy haired boss", status="AAB", manager_name="manager1"
+ ),
+ Engineer(
+ name="dilbert",
+ status="BBA",
+ engineer_name="engineer1",
+ primary_language="java",
+ ),
+ Person(name="joesmith"),
+ Engineer(
+ name="wally",
+ status="CGG",
+ engineer_name="engineer2",
+ primary_language="python",
+ ),
+ Manager(name="jsmith", status="ABA", manager_name="manager2"),
+ ],
+)
session.add(c)
session.commit()
@@ -116,14 +125,15 @@ c = session.query(Company).get(1)
for e in c.employees:
print(e, inspect(e).key, e.company)
assert set([e.name for e in c.employees]) == set(
- ['pointy haired boss', 'dilbert', 'joesmith', 'wally', 'jsmith'])
+ ["pointy haired boss", "dilbert", "joesmith", "wally", "jsmith"]
+)
print("\n")
-dilbert = session.query(Person).filter_by(name='dilbert').one()
-dilbert2 = session.query(Engineer).filter_by(name='dilbert').one()
+dilbert = session.query(Person).filter_by(name="dilbert").one()
+dilbert2 = session.query(Engineer).filter_by(name="dilbert").one()
assert dilbert is dilbert2
-dilbert.engineer_name = 'hes dilbert!'
+dilbert.engineer_name = "hes dilbert!"
session.commit()
@@ -134,24 +144,28 @@ for e in c.employees:
# query using with_polymorphic.
eng_manager = with_polymorphic(Person, [Engineer, Manager])
print(
- session.query(eng_manager).
- filter(
+ session.query(eng_manager)
+ .filter(
or_(
- eng_manager.Engineer.engineer_name == 'engineer1',
- eng_manager.Manager.manager_name == 'manager2'
+ eng_manager.Engineer.engineer_name == "engineer1",
+ eng_manager.Manager.manager_name == "manager2",
)
- ).all()
+ )
+ .all()
)
# illustrate join from Company,
eng_manager = with_polymorphic(Person, [Engineer, Manager])
print(
- session.query(Company).
- join(
- Company.employees.of_type(eng_manager)
- ).filter(
- or_(eng_manager.Engineer.engineer_name == 'engineer1',
- eng_manager.Manager.manager_name == 'manager2')
- ).all())
+ session.query(Company)
+ .join(Company.employees.of_type(eng_manager))
+ .filter(
+ or_(
+ eng_manager.Engineer.engineer_name == "engineer1",
+ eng_manager.Manager.manager_name == "manager2",
+ )
+ )
+ .all()
+)
session.commit()
diff --git a/examples/join_conditions/__init__.py b/examples/join_conditions/__init__.py
index 3a561d084..d67eb68e4 100644
--- a/examples/join_conditions/__init__.py
+++ b/examples/join_conditions/__init__.py
@@ -4,4 +4,4 @@ of join conditions.
.. autosource::
-""" \ No newline at end of file
+"""
diff --git a/examples/join_conditions/cast.py b/examples/join_conditions/cast.py
index 246bc1d57..7ea775689 100644
--- a/examples/join_conditions/cast.py
+++ b/examples/join_conditions/cast.py
@@ -35,6 +35,7 @@ from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
+
class StringAsInt(TypeDecorator):
"""Coerce string->integer type.
@@ -44,52 +45,55 @@ class StringAsInt(TypeDecorator):
on the child during a flush.
"""
+
impl = Integer
+
def process_bind_param(self, value, dialect):
if value is not None:
value = int(value)
return value
+
class A(Base):
"""Parent. The referenced column is a string type."""
- __tablename__ = 'a'
+ __tablename__ = "a"
id = Column(Integer, primary_key=True)
a_id = Column(String)
+
class B(Base):
"""Child. The column we reference 'A' with is an integer."""
- __tablename__ = 'b'
+ __tablename__ = "b"
id = Column(Integer, primary_key=True)
a_id = Column(StringAsInt)
- a = relationship("A",
- # specify primaryjoin. The string form is optional
- # here, but note that Declarative makes available all
- # of the built-in functions we might need, including
- # cast() and foreign().
- primaryjoin="cast(A.a_id, Integer) == foreign(B.a_id)",
- backref="bs")
+ a = relationship(
+ "A",
+ # specify primaryjoin. The string form is optional
+ # here, but note that Declarative makes available all
+ # of the built-in functions we might need, including
+ # cast() and foreign().
+ primaryjoin="cast(A.a_id, Integer) == foreign(B.a_id)",
+ backref="bs",
+ )
+
# we demonstrate with SQLite, but the important part
# is the CAST rendered in the SQL output.
-e = create_engine('sqlite://', echo=True)
+e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)
s = Session(e)
-s.add_all([
- A(a_id="1"),
- A(a_id="2", bs=[B(), B()]),
- A(a_id="3", bs=[B()]),
-])
+s.add_all([A(a_id="1"), A(a_id="2", bs=[B(), B()]), A(a_id="3", bs=[B()])])
s.commit()
b1 = s.query(B).filter_by(a_id="2").first()
print(b1.a)
a1 = s.query(A).filter_by(a_id="2").first()
-print(a1.bs) \ No newline at end of file
+print(a1.bs)
diff --git a/examples/join_conditions/threeway.py b/examples/join_conditions/threeway.py
index 13df0f349..257002637 100644
--- a/examples/join_conditions/threeway.py
+++ b/examples/join_conditions/threeway.py
@@ -39,46 +39,56 @@ from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
+
class First(Base):
- __tablename__ = 'first'
+ __tablename__ = "first"
first_id = Column(Integer, primary_key=True)
partition_key = Column(String)
def __repr__(self):
- return ("First(%s, %s)" % (self.first_id, self.partition_key))
+ return "First(%s, %s)" % (self.first_id, self.partition_key)
+
class Second(Base):
- __tablename__ = 'second'
+ __tablename__ = "second"
first_id = Column(Integer, primary_key=True)
other_id = Column(Integer, primary_key=True)
+
class Partitioned(Base):
- __tablename__ = 'partitioned'
+ __tablename__ = "partitioned"
other_id = Column(Integer, primary_key=True)
partition_key = Column(String, primary_key=True)
def __repr__(self):
- return ("Partitioned(%s, %s)" % (self.other_id, self.partition_key))
+ return "Partitioned(%s, %s)" % (self.other_id, self.partition_key)
j = join(Partitioned, Second, Partitioned.other_id == Second.other_id)
-partitioned_second = mapper(Partitioned, j, non_primary=True, properties={
+partitioned_second = mapper(
+ Partitioned,
+ j,
+ non_primary=True,
+ properties={
# note we need to disambiguate columns here - the join()
# will provide them as j.c.<tablename>_<colname> for access,
# but they retain their real names in the mapping
- "other_id": [j.c.partitioned_other_id, j.c.second_other_id],
- })
+ "other_id": [j.c.partitioned_other_id, j.c.second_other_id]
+ },
+)
First.partitioned = relationship(
- partitioned_second,
- primaryjoin=and_(
- First.partition_key == partitioned_second.c.partition_key,
- First.first_id == foreign(partitioned_second.c.first_id)
- ), innerjoin=True)
+ partitioned_second,
+ primaryjoin=and_(
+ First.partition_key == partitioned_second.c.partition_key,
+ First.first_id == foreign(partitioned_second.c.first_id),
+ ),
+ innerjoin=True,
+)
# when using any database other than SQLite, we will get a nested
# join, e.g. "first JOIN (partitioned JOIN second ON ..) ON ..".
@@ -87,17 +97,19 @@ e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)
s = Session(e)
-s.add_all([
- First(first_id=1, partition_key='p1'),
- First(first_id=2, partition_key='p1'),
- First(first_id=3, partition_key='p2'),
- Second(first_id=1, other_id=1),
- Second(first_id=2, other_id=1),
- Second(first_id=3, other_id=2),
- Partitioned(partition_key='p1', other_id=1),
- Partitioned(partition_key='p1', other_id=2),
- Partitioned(partition_key='p2', other_id=2),
-])
+s.add_all(
+ [
+ First(first_id=1, partition_key="p1"),
+ First(first_id=2, partition_key="p1"),
+ First(first_id=3, partition_key="p2"),
+ Second(first_id=1, other_id=1),
+ Second(first_id=2, other_id=1),
+ Second(first_id=3, other_id=2),
+ Partitioned(partition_key="p1", other_id=1),
+ Partitioned(partition_key="p1", other_id=2),
+ Partitioned(partition_key="p2", other_id=2),
+ ]
+)
s.commit()
for row in s.query(First, Partitioned).join(First.partitioned):
diff --git a/examples/large_collection/large_collection.py b/examples/large_collection/large_collection.py
index 82d2e554b..eb014c6cb 100644
--- a/examples/large_collection/large_collection.py
+++ b/examples/large_collection/large_collection.py
@@ -1,54 +1,76 @@
-
-from sqlalchemy import (MetaData, Table, Column, Integer, String, ForeignKey,
- create_engine)
-from sqlalchemy.orm import (mapper, relationship, sessionmaker)
+from sqlalchemy import (
+ MetaData,
+ Table,
+ Column,
+ Integer,
+ String,
+ ForeignKey,
+ create_engine,
+)
+from sqlalchemy.orm import mapper, relationship, sessionmaker
meta = MetaData()
-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')
+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
-mapper(Organization, org_table, properties = {
- 'members' : relationship(Member,
- # 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 -
- # *not* sqlite or MySQL with MyISAM
- passive_deletes=True,
- )
-})
+
+mapper(
+ Organization,
+ org_table,
+ properties={
+ "members": relationship(
+ Member,
+ # 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 -
+ # *not* sqlite or MySQL with MyISAM
+ passive_deletes=True,
+ )
+ },
+)
mapper(Member, member_table)
-if __name__ == '__main__':
- engine = create_engine("postgresql://scott:tiger@localhost/test", echo=True)
+if __name__ == "__main__":
+ engine = create_engine(
+ "postgresql://scott:tiger@localhost/test", echo=True
+ )
meta.create_all(engine)
# expire_on_commit=False means the session contents
@@ -56,10 +78,10 @@ if __name__ == '__main__':
sess = sessionmaker(engine, expire_on_commit=False)()
# create org with some members
- org = Organization('org one')
- org.members.append(Member('member one'))
- org.members.append(Member('member two'))
- org.members.append(Member('member three'))
+ org = Organization("org one")
+ org.members.append(Member("member one"))
+ org.members.append(Member("member two"))
+ org.members.append(Member("member three"))
sess.add(org)
@@ -69,14 +91,14 @@ if __name__ == '__main__':
# the 'members' collection is a Query. it issues
# SQL as needed to load subsets of the collection.
print("-------------------------\nload subset of members\n")
- members = org.members.filter(member_table.c.name.like('%member t%')).all()
+ members = org.members.filter(member_table.c.name.like("%member t%")).all()
print(members)
# new Members can be appended without any
# SQL being emitted to load the full collection
- org.members.append(Member('member four'))
- org.members.append(Member('member five'))
- org.members.append(Member('member six'))
+ org.members.append(Member("member four"))
+ org.members.append(Member("member five"))
+ org.members.append(Member("member six"))
print("-------------------------\nflush two - save 3 more members\n")
sess.commit()
@@ -85,7 +107,9 @@ if __name__ == '__main__':
# SQL is only emitted for the head row - the Member rows
# disappear automatically without the need for additional SQL.
sess.delete(org)
- print("-------------------------\nflush three - delete org, delete members in one statement\n")
+ print(
+ "-------------------------\nflush three - delete org, delete members in one statement\n"
+ )
sess.commit()
print("-------------------------\nno Member rows should remain:\n")
@@ -93,4 +117,4 @@ if __name__ == '__main__':
sess.close()
print("------------------------\ndone. dropping tables.")
- meta.drop_all(engine) \ No newline at end of file
+ meta.drop_all(engine)
diff --git a/examples/materialized_paths/materialized_paths.py b/examples/materialized_paths/materialized_paths.py
index 4ded90f7e..45ae0c193 100644
--- a/examples/materialized_paths/materialized_paths.py
+++ b/examples/materialized_paths/materialized_paths.py
@@ -44,21 +44,35 @@ class Node(Base):
# To find the descendants of this node, we look for nodes whose path
# starts with this node's path.
descendants = relationship(
- "Node", viewonly=True, order_by=path,
- primaryjoin=remote(foreign(path)).like(path.concat(".%")))
+ "Node",
+ viewonly=True,
+ order_by=path,
+ primaryjoin=remote(foreign(path)).like(path.concat(".%")),
+ )
# Finding the ancestors is a little bit trickier. We need to create a fake
# secondary table since this behaves like a many-to-many join.
- secondary = select([
- id.label("id"),
- func.unnest(cast(func.string_to_array(
- func.regexp_replace(path, r"\.?\d+$", ""), "."),
- ARRAY(Integer))).label("ancestor_id")
- ]).alias()
- ancestors = relationship("Node", viewonly=True, secondary=secondary,
- primaryjoin=id == secondary.c.id,
- secondaryjoin=secondary.c.ancestor_id == id,
- order_by=path)
+ secondary = select(
+ [
+ id.label("id"),
+ func.unnest(
+ cast(
+ func.string_to_array(
+ func.regexp_replace(path, r"\.?\d+$", ""), "."
+ ),
+ ARRAY(Integer),
+ )
+ ).label("ancestor_id"),
+ ]
+ ).alias()
+ ancestors = relationship(
+ "Node",
+ viewonly=True,
+ secondary=secondary,
+ primaryjoin=id == secondary.c.id,
+ secondaryjoin=secondary.c.ancestor_id == id,
+ order_by=path,
+ )
@property
def depth(self):
@@ -70,38 +84,44 @@ class Node(Base):
def __str__(self):
root_depth = self.depth
s = [str(self.id)]
- s.extend(((n.depth - root_depth) * " " + str(n.id))
- for n in self.descendants)
+ s.extend(
+ ((n.depth - root_depth) * " " + str(n.id))
+ for n in self.descendants
+ )
return "\n".join(s)
def move_to(self, new_parent):
new_path = new_parent.path + "." + str(self.id)
for n in self.descendants:
- n.path = new_path + n.path[len(self.path):]
+ n.path = new_path + n.path[len(self.path) :]
self.path = new_path
if __name__ == "__main__":
- engine = create_engine("postgresql://scott:tiger@localhost/test", echo=True)
+ engine = create_engine(
+ "postgresql://scott:tiger@localhost/test", echo=True
+ )
Base.metadata.create_all(engine)
session = Session(engine)
print("-" * 80)
print("create a tree")
- session.add_all([
- Node(id=1, path="1"),
- Node(id=2, path="1.2"),
- Node(id=3, path="1.3"),
- Node(id=4, path="1.3.4"),
- Node(id=5, path="1.3.5"),
- Node(id=6, path="1.3.6"),
- Node(id=7, path="1.7"),
- Node(id=8, path="1.7.8"),
- Node(id=9, path="1.7.9"),
- Node(id=10, path="1.7.9.10"),
- Node(id=11, path="1.7.11"),
- ])
+ session.add_all(
+ [
+ Node(id=1, path="1"),
+ Node(id=2, path="1.2"),
+ Node(id=3, path="1.3"),
+ Node(id=4, path="1.3.4"),
+ Node(id=5, path="1.3.5"),
+ Node(id=6, path="1.3.6"),
+ Node(id=7, path="1.7"),
+ Node(id=8, path="1.7.8"),
+ Node(id=9, path="1.7.9"),
+ Node(id=10, path="1.7.9.10"),
+ Node(id=11, path="1.7.11"),
+ ]
+ )
session.flush()
print(str(session.query(Node).get(1)))
diff --git a/examples/nested_sets/__init__.py b/examples/nested_sets/__init__.py
index 3e73bb13e..5fdfbcedc 100644
--- a/examples/nested_sets/__init__.py
+++ b/examples/nested_sets/__init__.py
@@ -3,4 +3,4 @@ pattern for hierarchical data using the SQLAlchemy ORM.
.. autosource::
-""" \ No newline at end of file
+"""
diff --git a/examples/nested_sets/nested_sets.py b/examples/nested_sets/nested_sets.py
index c64b15b61..705a3d279 100644
--- a/examples/nested_sets/nested_sets.py
+++ b/examples/nested_sets/nested_sets.py
@@ -4,19 +4,27 @@ http://www.intelligententerprise.com/001020/celko.jhtml
"""
-from sqlalchemy import (create_engine, Column, Integer, String, select, case,
- func)
+from sqlalchemy import (
+ create_engine,
+ Column,
+ Integer,
+ String,
+ select,
+ case,
+ func,
+)
from sqlalchemy.orm import Session, aliased
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import event
Base = declarative_base()
+
class Employee(Base):
- __tablename__ = 'personnel'
+ __tablename__ = "personnel"
__mapper_args__ = {
- 'batch': False # allows extension to fire for each
- # instance before going to the next.
+ "batch": False # allows extension to fire for each
+ # instance before going to the next.
}
parent = None
@@ -29,6 +37,7 @@ class Employee(Base):
def __repr__(self):
return "Employee(%s, %d, %d)" % (self.emp, self.left, self.right)
+
@event.listens_for(Employee, "before_insert")
def before_insert(mapper, connection, instance):
if not instance.parent:
@@ -37,23 +46,31 @@ def before_insert(mapper, connection, instance):
else:
personnel = mapper.mapped_table
right_most_sibling = connection.scalar(
- select([personnel.c.rgt]).
- where(personnel.c.emp == instance.parent.emp)
+ select([personnel.c.rgt]).where(
+ personnel.c.emp == instance.parent.emp
+ )
)
connection.execute(
- personnel.update(
- personnel.c.rgt >= right_most_sibling).values(
- lft=case(
- [(personnel.c.lft > right_most_sibling,
- personnel.c.lft + 2)],
- else_=personnel.c.lft
- ),
- rgt=case(
- [(personnel.c.rgt >= right_most_sibling,
- personnel.c.rgt + 2)],
- else_=personnel.c.rgt
- )
+ personnel.update(personnel.c.rgt >= right_most_sibling).values(
+ lft=case(
+ [
+ (
+ personnel.c.lft > right_most_sibling,
+ personnel.c.lft + 2,
+ )
+ ],
+ else_=personnel.c.lft,
+ ),
+ rgt=case(
+ [
+ (
+ personnel.c.rgt >= right_most_sibling,
+ personnel.c.rgt + 2,
+ )
+ ],
+ else_=personnel.c.rgt,
+ ),
)
)
instance.left = right_most_sibling
@@ -62,18 +79,19 @@ def before_insert(mapper, connection, instance):
# before_update() would be needed to support moving of nodes
# after_delete() would be needed to support removal of nodes.
-engine = create_engine('sqlite://', echo=True)
+
+engine = create_engine("sqlite://", echo=True)
Base.metadata.create_all(engine)
session = Session(bind=engine)
-albert = Employee(emp='Albert')
-bert = Employee(emp='Bert')
-chuck = Employee(emp='Chuck')
-donna = Employee(emp='Donna')
-eddie = Employee(emp='Eddie')
-fred = Employee(emp='Fred')
+albert = Employee(emp="Albert")
+bert = Employee(emp="Bert")
+chuck = Employee(emp="Chuck")
+donna = Employee(emp="Donna")
+eddie = Employee(emp="Eddie")
+fred = Employee(emp="Fred")
bert.parent = albert
chuck.parent = albert
@@ -90,22 +108,28 @@ print(session.query(Employee).all())
# 1. Find an employee and all their supervisors, no matter how deep the tree.
ealias = aliased(Employee)
-print(session.query(Employee).\
- filter(ealias.left.between(Employee.left, Employee.right)).\
- filter(ealias.emp == 'Eddie').all())
-
-#2. Find the employee and all their subordinates.
+print(
+ session.query(Employee)
+ .filter(ealias.left.between(Employee.left, Employee.right))
+ .filter(ealias.emp == "Eddie")
+ .all()
+)
+
+# 2. Find the employee and all their subordinates.
# (This query has a nice symmetry with the first query.)
-print(session.query(Employee).\
- filter(Employee.left.between(ealias.left, ealias.right)).\
- filter(ealias.emp == 'Chuck').all())
-
-#3. Find the level of each node, so you can print the tree
+print(
+ session.query(Employee)
+ .filter(Employee.left.between(ealias.left, ealias.right))
+ .filter(ealias.emp == "Chuck")
+ .all()
+)
+
+# 3. Find the level of each node, so you can print the tree
# as an indented listing.
-for indentation, employee in session.query(
- func.count(Employee.emp).label('indentation') - 1, ealias).\
- filter(ealias.left.between(Employee.left, Employee.right)).\
- group_by(ealias.emp).\
- order_by(ealias.left):
+for indentation, employee in (
+ session.query(func.count(Employee.emp).label("indentation") - 1, ealias)
+ .filter(ealias.left.between(Employee.left, Employee.right))
+ .group_by(ealias.emp)
+ .order_by(ealias.left)
+):
print(" " * indentation + str(employee))
-
diff --git a/examples/performance/__init__.py b/examples/performance/__init__.py
index 6264ae9f7..b66199f3c 100644
--- a/examples/performance/__init__.py
+++ b/examples/performance/__init__.py
@@ -255,7 +255,8 @@ class Profiler(object):
def profile(cls, fn):
if cls.name is None:
raise ValueError(
- "Need to call Profile.init(<suitename>, <default_num>) first.")
+ "Need to call Profile.init(<suitename>, <default_num>) first."
+ )
cls.tests.append(fn)
return fn
@@ -270,7 +271,8 @@ class Profiler(object):
def setup_once(cls, fn):
if cls._setup_once is not None:
raise ValueError(
- "setup_once function already set to %s" % cls._setup_once)
+ "setup_once function already set to %s" % cls._setup_once
+ )
cls._setup_once = staticmethod(fn)
return fn
@@ -298,7 +300,7 @@ class Profiler(object):
finally:
pr.disable()
- stats = pstats.Stats(pr).sort_stats('cumulative')
+ stats = pstats.Stats(pr).sort_stats("cumulative")
self.stats.append(TestResult(self, fn, stats=stats))
return result
@@ -326,7 +328,8 @@ class Profiler(object):
if cls.name is None:
parser.add_argument(
- "name", choices=cls._suite_names(), help="suite to run")
+ "name", choices=cls._suite_names(), help="suite to run"
+ )
if len(sys.argv) > 1:
potential_name = sys.argv[1]
@@ -335,35 +338,44 @@ class Profiler(object):
except ImportError:
pass
- parser.add_argument(
- "--test", type=str,
- help="run specific test name"
- )
+ parser.add_argument("--test", type=str, help="run specific test name")
parser.add_argument(
- '--dburl', type=str, default="sqlite:///profile.db",
- help="database URL, default sqlite:///profile.db"
+ "--dburl",
+ type=str,
+ default="sqlite:///profile.db",
+ help="database URL, default sqlite:///profile.db",
)
parser.add_argument(
- '--num', type=int, default=cls.num,
+ "--num",
+ type=int,
+ default=cls.num,
help="Number of iterations/items/etc for tests; "
- "default is %d module-specific" % cls.num
+ "default is %d module-specific" % cls.num,
)
parser.add_argument(
- '--profile', action='store_true',
- help='run profiling and dump call counts')
+ "--profile",
+ action="store_true",
+ help="run profiling and dump call counts",
+ )
parser.add_argument(
- '--dump', action='store_true',
- help='dump full call profile (implies --profile)')
+ "--dump",
+ action="store_true",
+ help="dump full call profile (implies --profile)",
+ )
parser.add_argument(
- '--callers', action='store_true',
- help='print callers as well (implies --dump)')
+ "--callers",
+ action="store_true",
+ help="print callers as well (implies --dump)",
+ )
parser.add_argument(
- '--runsnake', action='store_true',
- help='invoke runsnakerun (implies --profile)')
+ "--runsnake",
+ action="store_true",
+ help="invoke runsnakerun (implies --profile)",
+ )
parser.add_argument(
- '--echo', action='store_true',
- help="Echo SQL output")
+ "--echo", action="store_true", help="Echo SQL output"
+ )
args = parser.parse_args()
args.dump = args.dump or args.callers
@@ -378,7 +390,7 @@ class Profiler(object):
def _suite_names(cls):
suites = []
for file_ in os.listdir(os.path.dirname(__file__)):
- match = re.match(r'^([a-z].*).py$', file_)
+ match = re.match(r"^([a-z].*).py$", file_)
if match:
suites.append(match.group(1))
return suites
@@ -398,7 +410,10 @@ class TestResult(object):
def _summary(self):
summary = "%s : %s (%d iterations)" % (
- self.test.__name__, self.test.__doc__, self.profile.num)
+ self.test.__name__,
+ self.test.__doc__,
+ self.profile.num,
+ )
if self.total_time:
summary += "; total time %f sec" % self.total_time
if self.stats:
@@ -412,7 +427,7 @@ class TestResult(object):
self._dump()
def _dump(self):
- self.stats.sort_stats('time', 'calls')
+ self.stats.sort_stats("time", "calls")
self.stats.print_stats()
if self.profile.callers:
self.stats.print_callers()
@@ -424,5 +439,3 @@ class TestResult(object):
os.system("runsnake %s" % filename)
finally:
os.remove(filename)
-
-
diff --git a/examples/performance/__main__.py b/examples/performance/__main__.py
index 5e05143bf..945458651 100644
--- a/examples/performance/__main__.py
+++ b/examples/performance/__main__.py
@@ -2,6 +2,5 @@
from . import Profiler
-if __name__ == '__main__':
+if __name__ == "__main__":
Profiler.main()
-
diff --git a/examples/performance/bulk_inserts.py b/examples/performance/bulk_inserts.py
index 9c3cff5b2..52f0f32e6 100644
--- a/examples/performance/bulk_inserts.py
+++ b/examples/performance/bulk_inserts.py
@@ -36,12 +36,15 @@ def test_flush_no_pk(n):
"""Individual INSERT statements via the ORM, calling upon last row id"""
session = Session(bind=engine)
for chunk in range(0, n, 1000):
- session.add_all([
- Customer(
- name='customer name %d' % i,
- description='customer description %d' % i)
- for i in range(chunk, chunk + 1000)
- ])
+ session.add_all(
+ [
+ Customer(
+ name="customer name %d" % i,
+ description="customer description %d" % i,
+ )
+ for i in range(chunk, chunk + 1000)
+ ]
+ )
session.flush()
session.commit()
@@ -50,13 +53,16 @@ def test_flush_no_pk(n):
def test_bulk_save_return_pks(n):
"""Individual INSERT statements in "bulk", but calling upon last row id"""
session = Session(bind=engine)
- session.bulk_save_objects([
- Customer(
- name='customer name %d' % i,
- description='customer description %d' % i
- )
- for i in range(n)
- ], return_defaults=True)
+ session.bulk_save_objects(
+ [
+ Customer(
+ name="customer name %d" % i,
+ description="customer description %d" % i,
+ )
+ for i in range(n)
+ ],
+ return_defaults=True,
+ )
session.commit()
@@ -65,13 +71,16 @@ def test_flush_pk_given(n):
"""Batched INSERT statements via the ORM, PKs already defined"""
session = Session(bind=engine)
for chunk in range(0, n, 1000):
- session.add_all([
- Customer(
- id=i + 1,
- name='customer name %d' % i,
- description='customer description %d' % i)
- for i in range(chunk, chunk + 1000)
- ])
+ session.add_all(
+ [
+ Customer(
+ id=i + 1,
+ name="customer name %d" % i,
+ description="customer description %d" % i,
+ )
+ for i in range(chunk, chunk + 1000)
+ ]
+ )
session.flush()
session.commit()
@@ -80,13 +89,15 @@ def test_flush_pk_given(n):
def test_bulk_save(n):
"""Batched INSERT statements via the ORM in "bulk", discarding PKs."""
session = Session(bind=engine)
- session.bulk_save_objects([
- Customer(
- name='customer name %d' % i,
- description='customer description %d' % i
- )
- for i in range(n)
- ])
+ session.bulk_save_objects(
+ [
+ Customer(
+ name="customer name %d" % i,
+ description="customer description %d" % i,
+ )
+ for i in range(n)
+ ]
+ )
session.commit()
@@ -94,13 +105,16 @@ def test_bulk_save(n):
def test_bulk_insert_mappings(n):
"""Batched INSERT statements via the ORM "bulk", using dictionaries."""
session = Session(bind=engine)
- session.bulk_insert_mappings(Customer, [
- dict(
- name='customer name %d' % i,
- description='customer description %d' % i
- )
- for i in range(n)
- ])
+ session.bulk_insert_mappings(
+ Customer,
+ [
+ dict(
+ name="customer name %d" % i,
+ description="customer description %d" % i,
+ )
+ for i in range(n)
+ ],
+ )
session.commit()
@@ -112,11 +126,12 @@ def test_core_insert(n):
Customer.__table__.insert(),
[
dict(
- name='customer name %d' % i,
- description='customer description %d' % i
+ name="customer name %d" % i,
+ description="customer description %d" % i,
)
for i in range(n)
- ])
+ ],
+ )
@Profiler.profile
@@ -125,30 +140,30 @@ def test_dbapi_raw(n):
conn = engine.pool._creator()
cursor = conn.cursor()
- compiled = Customer.__table__.insert().values(
- name=bindparam('name'),
- description=bindparam('description')).\
- compile(dialect=engine.dialect)
+ compiled = (
+ Customer.__table__.insert()
+ .values(name=bindparam("name"), description=bindparam("description"))
+ .compile(dialect=engine.dialect)
+ )
if compiled.positional:
args = (
- ('customer name %d' % i, 'customer description %d' % i)
- for i in range(n))
+ ("customer name %d" % i, "customer description %d" % i)
+ for i in range(n)
+ )
else:
args = (
dict(
- name='customer name %d' % i,
- description='customer description %d' % i
+ name="customer name %d" % i,
+ description="customer description %d" % i,
)
for i in range(n)
)
- cursor.executemany(
- str(compiled),
- list(args)
- )
+ cursor.executemany(str(compiled), list(args))
conn.commit()
conn.close()
-if __name__ == '__main__':
+
+if __name__ == "__main__":
Profiler.main()
diff --git a/examples/performance/bulk_updates.py b/examples/performance/bulk_updates.py
index 9522e4bf5..ebb700068 100644
--- a/examples/performance/bulk_updates.py
+++ b/examples/performance/bulk_updates.py
@@ -32,12 +32,16 @@ def setup_database(dburl, echo, num):
s = Session(engine)
for chunk in range(0, num, 10000):
- s.bulk_insert_mappings(Customer, [
- {
- 'name': 'customer name %d' % i,
- 'description': 'customer description %d' % i
- } for i in range(chunk, chunk + 10000)
- ])
+ s.bulk_insert_mappings(
+ Customer,
+ [
+ {
+ "name": "customer name %d" % i,
+ "description": "customer description %d" % i,
+ }
+ for i in range(chunk, chunk + 10000)
+ ],
+ )
s.commit()
@@ -46,8 +50,11 @@ def test_orm_flush(n):
"""UPDATE statements via the ORM flush process."""
session = Session(bind=engine)
for chunk in range(0, n, 1000):
- customers = session.query(Customer).\
- filter(Customer.id.between(chunk, chunk + 1000)).all()
+ customers = (
+ session.query(Customer)
+ .filter(Customer.id.between(chunk, chunk + 1000))
+ .all()
+ )
for customer in customers:
customer.description += "updated"
session.flush()
diff --git a/examples/performance/large_resultsets.py b/examples/performance/large_resultsets.py
index c13683040..ad1c23194 100644
--- a/examples/performance/large_resultsets.py
+++ b/examples/performance/large_resultsets.py
@@ -46,9 +46,12 @@ def setup_database(dburl, echo, num):
Customer.__table__.insert(),
params=[
{
- 'name': 'customer name %d' % i,
- 'description': 'customer description %d' % i
- } for i in range(chunk, chunk + 10000)])
+ "name": "customer name %d" % i,
+ "description": "customer description %d" % i,
+ }
+ for i in range(chunk, chunk + 10000)
+ ],
+ )
s.commit()
@@ -74,8 +77,9 @@ def test_orm_bundles(n):
"""Load lightweight "bundle" objects using the ORM."""
sess = Session(engine)
- bundle = Bundle('customer',
- Customer.id, Customer.name, Customer.description)
+ bundle = Bundle(
+ "customer", Customer.id, Customer.name, Customer.description
+ )
for row in sess.query(bundle).yield_per(10000).limit(n):
pass
@@ -85,9 +89,11 @@ def test_orm_columns(n):
"""Load individual columns into named tuples using the ORM."""
sess = Session(engine)
- for row in sess.query(
- Customer.id, Customer.name,
- Customer.description).yield_per(10000).limit(n):
+ for row in (
+ sess.query(Customer.id, Customer.name, Customer.description)
+ .yield_per(10000)
+ .limit(n)
+ ):
pass
@@ -98,7 +104,7 @@ def test_core_fetchall(n):
with engine.connect() as conn:
result = conn.execute(Customer.__table__.select().limit(n)).fetchall()
for row in result:
- data = row['id'], row['name'], row['description']
+ data = row["id"], row["name"], row["description"]
@Profiler.profile
@@ -106,14 +112,15 @@ def test_core_fetchmany_w_streaming(n):
"""Load Core result rows using fetchmany/streaming."""
with engine.connect() as conn:
- result = conn.execution_options(stream_results=True).\
- execute(Customer.__table__.select().limit(n))
+ result = conn.execution_options(stream_results=True).execute(
+ Customer.__table__.select().limit(n)
+ )
while True:
chunk = result.fetchmany(10000)
if not chunk:
break
for row in chunk:
- data = row['id'], row['name'], row['description']
+ data = row["id"], row["name"], row["description"]
@Profiler.profile
@@ -127,7 +134,7 @@ def test_core_fetchmany(n):
if not chunk:
break
for row in chunk:
- data = row['id'], row['name'], row['description']
+ data = row["id"], row["name"], row["description"]
@Profiler.profile
@@ -145,10 +152,13 @@ def test_dbapi_fetchall_no_object(n):
def _test_dbapi_raw(n, make_objects):
- compiled = Customer.__table__.select().limit(n).\
- compile(
- dialect=engine.dialect,
- compile_kwargs={"literal_binds": True})
+ compiled = (
+ Customer.__table__.select()
+ .limit(n)
+ .compile(
+ dialect=engine.dialect, compile_kwargs={"literal_binds": True}
+ )
+ )
if make_objects:
# because if you're going to roll your own, you're probably
@@ -170,7 +180,8 @@ def _test_dbapi_raw(n, make_objects):
for row in cursor.fetchall():
# ensure that we fully fetch!
customer = SimpleCustomer(
- id=row[0], name=row[1], description=row[2])
+ id=row[0], name=row[1], description=row[2]
+ )
else:
for row in cursor.fetchall():
# ensure that we fully fetch!
@@ -178,5 +189,6 @@ def _test_dbapi_raw(n, make_objects):
conn.close()
-if __name__ == '__main__':
+
+if __name__ == "__main__":
Profiler.main()
diff --git a/examples/performance/short_selects.py b/examples/performance/short_selects.py
index 6f64aa63e..4a8d401ad 100644
--- a/examples/performance/short_selects.py
+++ b/examples/performance/short_selects.py
@@ -6,8 +6,14 @@ record by primary key
from . import Profiler
from sqlalchemy.ext.declarative import declarative_base
-from sqlalchemy import Column, Integer, String, create_engine, \
- bindparam, select
+from sqlalchemy import (
+ Column,
+ Integer,
+ String,
+ create_engine,
+ bindparam,
+ select,
+)
from sqlalchemy.orm import Session, deferred
from sqlalchemy.ext import baked
import random
@@ -29,6 +35,7 @@ class Customer(Base):
y = deferred(Column(Integer))
z = deferred(Column(Integer))
+
Profiler.init("short_selects", num=10000)
@@ -39,16 +46,20 @@ def setup_database(dburl, echo, num):
Base.metadata.drop_all(engine)
Base.metadata.create_all(engine)
sess = Session(engine)
- sess.add_all([
- Customer(
- id=i, name='c%d' % i, description="c%d" % i,
- q=i * 10,
- p=i * 20,
- x=i * 30,
- y=i * 40,
- )
- for i in ids
- ])
+ sess.add_all(
+ [
+ Customer(
+ id=i,
+ name="c%d" % i,
+ description="c%d" % i,
+ q=i * 10,
+ p=i * 20,
+ x=i * 30,
+ y=i * 40,
+ )
+ for i in ids
+ ]
+ )
sess.commit()
@@ -65,9 +76,9 @@ def test_orm_query_cols_only(n):
"""test an ORM query of only the entity columns."""
session = Session(bind=engine)
for id_ in random.sample(ids, n):
- session.query(
- Customer.id, Customer.name, Customer.description
- ).filter(Customer.id == id_).one()
+ session.query(Customer.id, Customer.name, Customer.description).filter(
+ Customer.id == id_
+ ).one()
@Profiler.profile
@@ -77,7 +88,7 @@ def test_baked_query(n):
s = Session(bind=engine)
for id_ in random.sample(ids, n):
q = bakery(lambda s: s.query(Customer))
- q += lambda q: q.filter(Customer.id == bindparam('id'))
+ q += lambda q: q.filter(Customer.id == bindparam("id"))
q(s).params(id=id_).one()
@@ -88,9 +99,9 @@ def test_baked_query_cols_only(n):
s = Session(bind=engine)
for id_ in random.sample(ids, n):
q = bakery(
- lambda s: s.query(
- Customer.id, Customer.name, Customer.description))
- q += lambda q: q.filter(Customer.id == bindparam('id'))
+ lambda s: s.query(Customer.id, Customer.name, Customer.description)
+ )
+ q += lambda q: q.filter(Customer.id == bindparam("id"))
q(s).params(id=id_).one()
@@ -109,7 +120,7 @@ def test_core_new_stmt_each_time(n):
def test_core_reuse_stmt(n):
"""test core, reusing the same statement (but recompiling each time)."""
- stmt = select([Customer.__table__]).where(Customer.id == bindparam('id'))
+ stmt = select([Customer.__table__]).where(Customer.id == bindparam("id"))
with engine.connect() as conn:
for id_ in random.sample(ids, n):
@@ -122,13 +133,14 @@ def test_core_reuse_stmt_compiled_cache(n):
"""test core, reusing the same statement + compiled cache."""
compiled_cache = {}
- stmt = select([Customer.__table__]).where(Customer.id == bindparam('id'))
- with engine.connect().\
- execution_options(compiled_cache=compiled_cache) as conn:
+ stmt = select([Customer.__table__]).where(Customer.id == bindparam("id"))
+ with engine.connect().execution_options(
+ compiled_cache=compiled_cache
+ ) as conn:
for id_ in random.sample(ids, n):
row = conn.execute(stmt, id=id_).first()
tuple(row)
-if __name__ == '__main__':
+if __name__ == "__main__":
Profiler.main()
diff --git a/examples/performance/single_inserts.py b/examples/performance/single_inserts.py
index cfce90300..79e34dfe6 100644
--- a/examples/performance/single_inserts.py
+++ b/examples/performance/single_inserts.py
@@ -28,7 +28,7 @@ Profiler.init("single_inserts", num=10000)
def setup_database(dburl, echo, num):
global engine
engine = create_engine(dburl, echo=echo)
- if engine.dialect.name == 'sqlite':
+ if engine.dialect.name == "sqlite":
engine.pool = pool.StaticPool(creator=engine.pool._creator)
Base.metadata.drop_all(engine)
Base.metadata.create_all(engine)
@@ -42,8 +42,9 @@ def test_orm_commit(n):
session = Session(bind=engine)
session.add(
Customer(
- name='customer name %d' % i,
- description='customer description %d' % i)
+ name="customer name %d" % i,
+ description="customer description %d" % i,
+ )
)
session.commit()
@@ -54,11 +55,14 @@ def test_bulk_save(n):
for i in range(n):
session = Session(bind=engine)
- session.bulk_save_objects([
- Customer(
- name='customer name %d' % i,
- description='customer description %d' % i
- )])
+ session.bulk_save_objects(
+ [
+ Customer(
+ name="customer name %d" % i,
+ description="customer description %d" % i,
+ )
+ ]
+ )
session.commit()
@@ -68,11 +72,15 @@ def test_bulk_insert_dictionaries(n):
for i in range(n):
session = Session(bind=engine)
- session.bulk_insert_mappings(Customer, [
- dict(
- name='customer name %d' % i,
- description='customer description %d' % i
- )])
+ session.bulk_insert_mappings(
+ Customer,
+ [
+ dict(
+ name="customer name %d" % i,
+ description="customer description %d" % i,
+ )
+ ],
+ )
session.commit()
@@ -85,9 +93,9 @@ def test_core(n):
conn.execute(
Customer.__table__.insert(),
dict(
- name='customer name %d' % i,
- description='customer description %d' % i
- )
+ name="customer name %d" % i,
+ description="customer description %d" % i,
+ ),
)
@@ -102,9 +110,9 @@ def test_core_query_caching(n):
conn.execution_options(compiled_cache=cache).execute(
ins,
dict(
- name='customer name %d' % i,
- description='customer description %d' % i
- )
+ name="customer name %d" % i,
+ description="customer description %d" % i,
+ ),
)
@@ -123,20 +131,22 @@ def test_dbapi_raw_w_pool(n):
def _test_dbapi_raw(n, connect):
- compiled = Customer.__table__.insert().values(
- name=bindparam('name'),
- description=bindparam('description')).\
- compile(dialect=engine.dialect)
+ compiled = (
+ Customer.__table__.insert()
+ .values(name=bindparam("name"), description=bindparam("description"))
+ .compile(dialect=engine.dialect)
+ )
if compiled.positional:
args = (
- ('customer name %d' % i, 'customer description %d' % i)
- for i in range(n))
+ ("customer name %d" % i, "customer description %d" % i)
+ for i in range(n)
+ )
else:
args = (
dict(
- name='customer name %d' % i,
- description='customer description %d' % i
+ name="customer name %d" % i,
+ description="customer description %d" % i,
)
for i in range(n)
)
@@ -162,5 +172,5 @@ def _test_dbapi_raw(n, connect):
conn.close()
-if __name__ == '__main__':
+if __name__ == "__main__":
Profiler.main()
diff --git a/examples/postgis/__init__.py b/examples/postgis/__init__.py
index 250d9ce87..66ae65d3c 100644
--- a/examples/postgis/__init__.py
+++ b/examples/postgis/__init__.py
@@ -36,4 +36,3 @@ E.g.::
.. autosource::
"""
-
diff --git a/examples/postgis/postgis.py b/examples/postgis/postgis.py
index ffea3d018..508d63398 100644
--- a/examples/postgis/postgis.py
+++ b/examples/postgis/postgis.py
@@ -5,6 +5,7 @@ import binascii
# Python datatypes
+
class GisElement(object):
"""Represents a geometry value."""
@@ -12,16 +13,21 @@ class GisElement(object):
return self.desc
def __repr__(self):
- return "<%s at 0x%x; %r>" % (self.__class__.__name__,
- id(self), self.desc)
+ return "<%s at 0x%x; %r>" % (
+ self.__class__.__name__,
+ id(self),
+ self.desc,
+ )
+
class BinaryGisElement(GisElement, expression.Function):
"""Represents a Geometry value expressed as binary."""
def __init__(self, data):
self.data = data
- expression.Function.__init__(self, "ST_GeomFromEWKB", data,
- type_=Geometry(coerce_="binary"))
+ expression.Function.__init__(
+ self, "ST_GeomFromEWKB", data, type_=Geometry(coerce_="binary")
+ )
@property
def desc(self):
@@ -31,24 +37,26 @@ class BinaryGisElement(GisElement, expression.Function):
def as_hex(self):
return binascii.hexlify(self.data)
+
class TextualGisElement(GisElement, expression.Function):
"""Represents a Geometry value expressed as text."""
def __init__(self, desc, srid=-1):
self.desc = desc
- expression.Function.__init__(self, "ST_GeomFromText", desc, srid,
- type_=Geometry)
+ expression.Function.__init__(
+ self, "ST_GeomFromText", desc, srid, type_=Geometry
+ )
# SQL datatypes.
+
class Geometry(UserDefinedType):
"""Base PostGIS Geometry column type."""
name = "GEOMETRY"
- def __init__(self, dimension=None, srid=-1,
- coerce_="text"):
+ def __init__(self, dimension=None, srid=-1, coerce_="text"):
self.dimension = dimension
self.srid = srid
self.coerce = coerce_
@@ -58,11 +66,11 @@ class Geometry(UserDefinedType):
# override the __eq__() operator
def __eq__(self, other):
- return self.op('~=')(other)
+ return self.op("~=")(other)
# add a custom operator
def intersects(self, other):
- return self.op('&&')(other)
+ return self.op("&&")(other)
# any number of GIS operators can be overridden/added here
# using the techniques above.
@@ -95,6 +103,7 @@ class Geometry(UserDefinedType):
return value.desc
else:
return value
+
return process
def result_processor(self, dialect, coltype):
@@ -104,27 +113,35 @@ class Geometry(UserDefinedType):
fac = BinaryGisElement
else:
assert False
+
def process(value):
if value is not None:
return fac(value)
else:
return value
+
return process
def adapt(self, impltype):
- return impltype(dimension=self.dimension,
- srid=self.srid, coerce_=self.coerce)
+ return impltype(
+ dimension=self.dimension, srid=self.srid, coerce_=self.coerce
+ )
+
# other datatypes can be added as needed.
+
class Point(Geometry):
- name = 'POINT'
+ name = "POINT"
+
class Curve(Geometry):
- name = 'CURVE'
+ name = "CURVE"
+
class LineString(Curve):
- name = 'LINESTRING'
+ name = "LINESTRING"
+
# ... etc.
@@ -135,6 +152,7 @@ class LineString(Curve):
# versions don't appear to require these special steps anymore. However,
# here we illustrate how to set up these features in any case.
+
def setup_ddl_events():
@event.listens_for(Table, "before_create")
def before_create(target, connection, **kw):
@@ -153,9 +171,10 @@ def setup_ddl_events():
dispatch("after-drop", target, connection)
def dispatch(event, table, bind):
- if event in ('before-create', 'before-drop'):
- regular_cols = [c for c in table.c if not
- isinstance(c.type, Geometry)]
+ 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)
table.info["_saved_columns"] = table.c
@@ -163,85 +182,129 @@ def setup_ddl_events():
# Geometry columns
table.columns = expression.ColumnCollection(*regular_cols)
- if event == 'before-drop':
+ if event == "before-drop":
for c in gis_cols:
bind.execute(
- select([
+ select(
+ [
func.DropGeometryColumn(
- 'public', table.name, c.name)],
- autocommit=True)
- )
+ "public", table.name, c.name
+ )
+ ],
+ autocommit=True,
+ )
+ )
- elif event == 'after-create':
- table.columns = table.info.pop('_saved_columns')
+ elif event == "after-create":
+ table.columns = table.info.pop("_saved_columns")
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)
+ select(
+ [
+ func.AddGeometryColumn(
+ table.name,
+ c.name,
+ c.type.srid,
+ c.type.name,
+ c.type.dimension,
+ )
+ ],
+ autocommit=True,
)
- elif event == 'after-drop':
- table.columns = table.info.pop('_saved_columns')
-setup_ddl_events()
+ )
+ elif event == "after-drop":
+ table.columns = table.info.pop("_saved_columns")
+setup_ddl_events()
+
# illustrate usage
-if __name__ == '__main__':
- from sqlalchemy import (create_engine, MetaData, Column, Integer, String,
- func, select)
+if __name__ == "__main__":
+ from sqlalchemy import (
+ create_engine,
+ MetaData,
+ Column,
+ Integer,
+ String,
+ func,
+ select,
+ )
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
- engine = create_engine('postgresql://scott:tiger@localhost/test', echo=True)
+ engine = create_engine(
+ "postgresql://scott:tiger@localhost/test", echo=True
+ )
metadata = MetaData(engine)
Base = declarative_base(metadata=metadata)
class Road(Base):
- __tablename__ = 'roads'
+ __tablename__ = "roads"
road_id = Column(Integer, primary_key=True)
road_name = Column(String)
road_geom = Column(Geometry(2))
-
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)'),
- Road(road_name='Geordie Rd', road_geom='LINESTRING(189141 244158,189265 244817)'),
- Road(road_name='Paul St', road_geom='LINESTRING(192783 228138,192612 229814)'),
- Road(road_name='Graeme Ave', road_geom='LINESTRING(189412 252431,189631 259122)'),
- Road(road_name='Phil Tce', road_geom='LINESTRING(190131 224148,190871 228134)'),
- ])
+ session.add_all(
+ [
+ Road(
+ road_name="Jeff Rd",
+ road_geom="LINESTRING(191232 243118,191108 243242)",
+ ),
+ Road(
+ road_name="Geordie Rd",
+ road_geom="LINESTRING(189141 244158,189265 244817)",
+ ),
+ Road(
+ road_name="Paul St",
+ road_geom="LINESTRING(192783 228138,192612 229814)",
+ ),
+ 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))
+ 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 str(r.road_geom) == "LINESTRING(198231 263418,198213 268322)"
session.commit()
# after flush and/or commit, all the TextualGisElements become PersistentGisElements.
assert str(r.road_geom) == "LINESTRING(198231 263418,198213 268322)"
- r1 = session.query(Road).filter(Road.road_name == 'Graeme Ave').one()
+ 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()
+ r2 = (
+ session.query(Road)
+ .filter(Road.road_geom == "LINESTRING(189412 252431,189631 259122)")
+ .one()
+ )
r3 = session.query(Road).filter(Road.road_geom == r1.road_geom).one()
@@ -250,22 +313,29 @@ if __name__ == '__main__':
# core usage just fine:
road_table = Road.__table__
- stmt = select([road_table]).where(road_table.c.road_geom.intersects(r1.road_geom))
+ stmt = select([road_table]).where(
+ road_table.c.road_geom.intersects(r1.road_geom)
+ )
print(session.execute(stmt).fetchall())
# TODO: for some reason the auto-generated labels have the internal replacement
# strings exposed, even though PG doesn't complain
# look up the hex binary version, using SQLAlchemy casts
- as_binary = session.scalar(select([type_coerce(r.road_geom, Geometry(coerce_="binary"))]))
- assert as_binary.as_hex == \
- '01020000000200000000000000b832084100000000e813104100000000283208410000000088601041'
+ as_binary = session.scalar(
+ select([type_coerce(r.road_geom, Geometry(coerce_="binary"))])
+ )
+ assert (
+ as_binary.as_hex
+ == "01020000000200000000000000b832084100000000e813104100000000283208410000000088601041"
+ )
# back again, same method !
- as_text = session.scalar(select([type_coerce(as_binary, Geometry(coerce_="text"))]))
+ as_text = session.scalar(
+ select([type_coerce(as_binary, Geometry(coerce_="text"))])
+ )
assert as_text.desc == "LINESTRING(198231 263418,198213 268322)"
-
session.rollback()
metadata.drop_all()
diff --git a/examples/sharding/attribute_shard.py b/examples/sharding/attribute_shard.py
index 0e19b69f3..48a3dc932 100644
--- a/examples/sharding/attribute_shard.py
+++ b/examples/sharding/attribute_shard.py
@@ -1,5 +1,13 @@
-from sqlalchemy import (create_engine, Table, Column, Integer,
- String, ForeignKey, Float, DateTime)
+from sqlalchemy import (
+ create_engine,
+ Table,
+ Column,
+ Integer,
+ String,
+ ForeignKey,
+ Float,
+ DateTime,
+)
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy.ext.horizontal_shard import ShardedSession
from sqlalchemy.sql import operators, visitors
@@ -12,22 +20,24 @@ import datetime
# causes the id_generator() to use the same connection as that
# of an ongoing transaction within db1.
echo = True
-db1 = create_engine('sqlite://', echo=echo, pool_threadlocal=True)
-db2 = create_engine('sqlite://', echo=echo)
-db3 = create_engine('sqlite://', echo=echo)
-db4 = create_engine('sqlite://', echo=echo)
+db1 = create_engine("sqlite://", echo=echo, pool_threadlocal=True)
+db2 = create_engine("sqlite://", echo=echo)
+db3 = create_engine("sqlite://", echo=echo)
+db4 = create_engine("sqlite://", echo=echo)
# create session function. this binds the shard ids
# to databases within a ShardedSession and returns it.
create_session = sessionmaker(class_=ShardedSession)
-create_session.configure(shards={
- 'north_america': db1,
- 'asia': db2,
- 'europe': db3,
- 'south_america': db4
-})
+create_session.configure(
+ shards={
+ "north_america": db1,
+ "asia": db2,
+ "europe": db3,
+ "south_america": db4,
+ }
+)
# mappings and tables
@@ -40,9 +50,7 @@ Base = declarative_base()
# #1. Any other method will do just as well; UUID, hilo, application-specific,
# etc.
-ids = Table(
- 'ids', Base.metadata,
- Column('nextid', Integer, nullable=False))
+ids = Table("ids", Base.metadata, Column("nextid", Integer, nullable=False))
def id_generator(ctx):
@@ -52,6 +60,7 @@ def id_generator(ctx):
conn.execute(ids.update(values={ids.c.nextid: ids.c.nextid + 1}))
return nextid
+
# table setup. we'll store a lead table of continents/cities, and a secondary
# table storing locations. a particular row will be placed in the database
# whose shard id corresponds to the 'continent'. in this setup, secondary rows
@@ -67,7 +76,7 @@ class WeatherLocation(Base):
continent = Column(String(30), nullable=False)
city = Column(String(50), nullable=False)
- reports = relationship("Report", backref='location')
+ reports = relationship("Report", backref="location")
def __init__(self, continent, city):
self.continent = continent
@@ -79,14 +88,17 @@ class Report(Base):
id = Column(Integer, primary_key=True)
location_id = Column(
- 'location_id', Integer, ForeignKey('weather_locations.id'))
- temperature = Column('temperature', Float)
+ "location_id", Integer, ForeignKey("weather_locations.id")
+ )
+ temperature = Column("temperature", Float)
report_time = Column(
- 'report_time', DateTime, default=datetime.datetime.now)
+ "report_time", DateTime, default=datetime.datetime.now
+ )
def __init__(self, temperature):
self.temperature = temperature
+
# create tables
for db in (db1, db2, db3, db4):
Base.metadata.drop_all(db)
@@ -101,10 +113,10 @@ db1.execute(ids.insert(), nextid=1)
# we'll use a straight mapping of a particular set of "country"
# attributes to shard id.
shard_lookup = {
- 'North America': 'north_america',
- 'Asia': 'asia',
- 'Europe': 'europe',
- 'South America': 'south_america'
+ "North America": "north_america",
+ "Asia": "asia",
+ "Europe": "europe",
+ "South America": "south_america",
}
@@ -139,7 +151,7 @@ def id_chooser(query, ident):
# set things up.
return [query.lazy_loaded_from.identity_token]
else:
- return ['north_america', 'asia', 'europe', 'south_america']
+ return ["north_america", "asia", "europe", "south_america"]
def query_chooser(query):
@@ -168,7 +180,7 @@ def query_chooser(query):
ids.extend(shard_lookup[v] for v in value)
if len(ids) == 0:
- return ['north_america', 'asia', 'europe', 'south_america']
+ return ["north_america", "asia", "europe", "south_america"]
else:
return ids
@@ -208,13 +220,16 @@ def _get_query_comparisons(query):
def visit_binary(binary):
# special handling for "col IN (params)"
- if binary.left in clauses and \
- binary.operator == operators.in_op and \
- hasattr(binary.right, 'clauses'):
+ if (
+ binary.left in clauses
+ and binary.operator == operators.in_op
+ and hasattr(binary.right, "clauses")
+ ):
comparisons.append(
(
- binary.left, binary.operator,
- tuple(binds[bind] for bind in binary.right.clauses)
+ binary.left,
+ binary.operator,
+ tuple(binds[bind] for bind in binary.right.clauses),
)
)
elif binary.left in clauses and binary.right in binds:
@@ -232,29 +247,33 @@ def _get_query_comparisons(query):
# into a list.
if query._criterion is not None:
visitors.traverse_depthfirst(
- query._criterion, {},
- {'bindparam': visit_bindparam,
- 'binary': visit_binary,
- 'column': visit_column}
+ query._criterion,
+ {},
+ {
+ "bindparam": visit_bindparam,
+ "binary": visit_binary,
+ "column": visit_column,
+ },
)
return comparisons
+
# further configure create_session to use these functions
create_session.configure(
shard_chooser=shard_chooser,
id_chooser=id_chooser,
- query_chooser=query_chooser
+ query_chooser=query_chooser,
)
# save and load objects!
-tokyo = WeatherLocation('Asia', 'Tokyo')
-newyork = WeatherLocation('North America', 'New York')
-toronto = WeatherLocation('North America', 'Toronto')
-london = WeatherLocation('Europe', 'London')
-dublin = WeatherLocation('Europe', 'Dublin')
-brasilia = WeatherLocation('South America', 'Brasila')
-quito = WeatherLocation('South America', 'Quito')
+tokyo = WeatherLocation("Asia", "Tokyo")
+newyork = WeatherLocation("North America", "New York")
+toronto = WeatherLocation("North America", "Toronto")
+london = WeatherLocation("Europe", "London")
+dublin = WeatherLocation("Europe", "Dublin")
+brasilia = WeatherLocation("South America", "Brasila")
+quito = WeatherLocation("South America", "Quito")
tokyo.reports.append(Report(80.0))
newyork.reports.append(Report(75))
@@ -271,12 +290,14 @@ assert t.city == tokyo.city
assert t.reports[0].temperature == 80.0
north_american_cities = sess.query(WeatherLocation).filter(
- WeatherLocation.continent == 'North America')
-assert {c.city for c in north_american_cities} == {'New York', 'Toronto'}
+ WeatherLocation.continent == "North America"
+)
+assert {c.city for c in north_american_cities} == {"New York", "Toronto"}
asia_and_europe = sess.query(WeatherLocation).filter(
- WeatherLocation.continent.in_(['Europe', 'Asia']))
-assert {c.city for c in asia_and_europe} == {'Tokyo', 'London', 'Dublin'}
+ WeatherLocation.continent.in_(["Europe", "Asia"])
+)
+assert {c.city for c in asia_and_europe} == {"Tokyo", "London", "Dublin"}
# the Report class uses a simple integer primary key. So across two databases,
# a primary key will be repeated. The "identity_token" tracks in memory
@@ -284,8 +305,8 @@ assert {c.city for c in asia_and_europe} == {'Tokyo', 'London', 'Dublin'}
newyork_report = newyork.reports[0]
tokyo_report = tokyo.reports[0]
-assert inspect(newyork_report).identity_key == (Report, (1, ), "north_america")
-assert inspect(tokyo_report).identity_key == (Report, (1, ), "asia")
+assert inspect(newyork_report).identity_key == (Report, (1,), "north_america")
+assert inspect(tokyo_report).identity_key == (Report, (1,), "asia")
# the token representing the originating shard is also available directly
diff --git a/examples/space_invaders/__init__.py b/examples/space_invaders/__init__.py
index 8816045dc..944f8bb46 100644
--- a/examples/space_invaders/__init__.py
+++ b/examples/space_invaders/__init__.py
@@ -21,4 +21,4 @@ enjoy!
.. autosource::
-""" \ No newline at end of file
+"""
diff --git a/examples/space_invaders/space_invaders.py b/examples/space_invaders/space_invaders.py
index 3ce280aec..d5437d8cf 100644
--- a/examples/space_invaders/space_invaders.py
+++ b/examples/space_invaders/space_invaders.py
@@ -1,7 +1,6 @@
import sys
from sqlalchemy.ext.declarative import declarative_base
-from sqlalchemy import create_engine, Integer, Column, ForeignKey, \
- String, func
+from sqlalchemy import create_engine, Integer, Column, ForeignKey, String, func
from sqlalchemy.orm import relationship, Session, joinedload
from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method
import curses
@@ -18,7 +17,7 @@ if _PY3:
logging.basicConfig(
filename="space_invaders.log",
- format="%(asctime)s,%(msecs)03d %(levelname)-5.5s %(message)s"
+ format="%(asctime)s,%(msecs)03d %(levelname)-5.5s %(message)s",
)
logging.getLogger("sqlalchemy.engine").setLevel(logging.INFO)
@@ -47,7 +46,7 @@ COLOR_MAP = {
"M": curses.COLOR_MAGENTA,
"R": curses.COLOR_RED,
"W": curses.COLOR_WHITE,
- "Y": curses.COLOR_YELLOW
+ "Y": curses.COLOR_YELLOW,
}
@@ -56,7 +55,8 @@ class Glyph(Base):
to be painted on the screen.
"""
- __tablename__ = 'glyph'
+
+ __tablename__ = "glyph"
id = Column(Integer, primary_key=True)
name = Column(String)
type = Column(String)
@@ -68,11 +68,9 @@ class Glyph(Base):
def __init__(self, name, img, alt=None):
self.name = name
- self.data, self.width, self.height = \
- self._encode_glyph(img)
+ self.data, self.width, self.height = self._encode_glyph(img)
if alt is not None:
- self.alt_data, alt_w, alt_h = \
- self._encode_glyph(alt)
+ self.alt_data, alt_w, alt_h = self._encode_glyph(alt)
def _encode_glyph(self, img):
"""Receive a textual description of the glyph and
@@ -80,7 +78,7 @@ class Glyph(Base):
GlyphCoordinate.render().
"""
- img = re.sub(r'^\n', "", textwrap.dedent(img))
+ img = re.sub(r"^\n", "", textwrap.dedent(img))
color = "W"
lines = [line.rstrip() for line in img.split("\n")]
data = []
@@ -89,15 +87,15 @@ class Glyph(Base):
line = list(line)
while line:
char = line.pop(0)
- if char == '#':
+ if char == "#":
color = line.pop(0)
continue
render_line.append((color, char))
data.append(render_line)
width = max([len(rl) for rl in data])
data = "".join(
- "".join("%s%s" % (color, char) for color, char in render_line) +
- ("W " * (width - len(render_line)))
+ "".join("%s%s" % (color, char) for color, char in render_line)
+ + ("W " * (width - len(render_line)))
for render_line in data
)
return data, width, len(lines)
@@ -121,9 +119,10 @@ class GlyphCoordinate(Base):
score value.
"""
- __tablename__ = 'glyph_coordinate'
+
+ __tablename__ = "glyph_coordinate"
id = Column(Integer, primary_key=True)
- glyph_id = Column(Integer, ForeignKey('glyph.id'))
+ glyph_id = Column(Integer, ForeignKey("glyph.id"))
x = Column(Integer)
y = Column(Integer)
tick = Column(Integer)
@@ -132,11 +131,9 @@ class GlyphCoordinate(Base):
glyph = relationship(Glyph, innerjoin=True)
def __init__(
- self,
- session, glyph_name, x, y,
- tick=None, label=None, score=None):
- self.glyph = session.query(Glyph).\
- filter_by(name=glyph_name).one()
+ self, session, glyph_name, x, y, tick=None, label=None, score=None
+ ):
+ self.glyph = session.query(Glyph).filter_by(name=glyph_name).one()
self.x = x
self.y = y
self.tick = tick
@@ -152,8 +149,7 @@ class GlyphCoordinate(Base):
glyph = self.glyph
data = glyph.glyph_for_state(self, state)
for color, char in [
- (data[i], data[i + 1])
- for i in xrange(0, len(data), 2)
+ (data[i], data[i + 1]) for i in xrange(0, len(data), 2)
]:
x = self.x + col
@@ -163,7 +159,8 @@ class GlyphCoordinate(Base):
y + VERT_PADDING,
x + HORIZ_PADDING,
char,
- _COLOR_PAIRS[color])
+ _COLOR_PAIRS[color],
+ )
col += 1
if col == glyph.width:
col = 0
@@ -186,10 +183,7 @@ class GlyphCoordinate(Base):
width = min(glyph.width, MAX_X - x) or 1
for y_a in xrange(self.y, self.y + glyph.height):
y = y_a
- window.addstr(
- y + VERT_PADDING,
- x + HORIZ_PADDING,
- " " * width)
+ window.addstr(y + VERT_PADDING, x + HORIZ_PADDING, " " * width)
if self.label:
self._render_label(window, True)
@@ -236,21 +230,22 @@ class GlyphCoordinate(Base):
the given GlyphCoordinate."""
return ~(
- (self.x + self.width < other.x) |
- (self.x > other.x + other.width)
+ (self.x + self.width < other.x) | (self.x > other.x + other.width)
) & ~(
- (self.y + self.height < other.y) |
- (self.y > other.y + other.height)
+ (self.y + self.height < other.y)
+ | (self.y > other.y + other.height)
)
class EnemyGlyph(Glyph):
"""Describe an enemy."""
+
__mapper_args__ = {"polymorphic_identity": "enemy"}
class ArmyGlyph(EnemyGlyph):
"""Describe an enemy that's part of the "army". """
+
__mapper_args__ = {"polymorphic_identity": "army"}
def glyph_for_state(self, coord, state):
@@ -262,6 +257,7 @@ class ArmyGlyph(EnemyGlyph):
class SaucerGlyph(EnemyGlyph):
"""Describe the enemy saucer flying overhead."""
+
__mapper_args__ = {"polymorphic_identity": "saucer"}
def glyph_for_state(self, coord, state):
@@ -273,21 +269,25 @@ class SaucerGlyph(EnemyGlyph):
class MessageGlyph(Glyph):
"""Describe a glyph for displaying a message."""
+
__mapper_args__ = {"polymorphic_identity": "message"}
class PlayerGlyph(Glyph):
"""Describe a glyph representing the player."""
+
__mapper_args__ = {"polymorphic_identity": "player"}
class MissileGlyph(Glyph):
"""Describe a glyph representing a missile."""
+
__mapper_args__ = {"polymorphic_identity": "missile"}
class SplatGlyph(Glyph):
"""Describe a glyph representing a "splat"."""
+
__mapper_args__ = {"polymorphic_identity": "splat"}
def glyph_for_state(self, coord, state):
@@ -302,36 +302,39 @@ def init_glyph(session):
"""Create the glyphs used during play."""
enemy1 = ArmyGlyph(
- "enemy1", """
+ "enemy1",
+ """
#W-#B^#R-#B^#W-
#G| |
""",
"""
#W>#B^#R-#B^#W<
#G^ ^
- """
+ """,
)
enemy2 = ArmyGlyph(
- "enemy2", """
+ "enemy2",
+ """
#W***
#R<#C~~~#R>
""",
"""
#W@@@
#R<#C---#R>
- """
+ """,
)
enemy3 = ArmyGlyph(
- "enemy3", """
+ "enemy3",
+ """
#Y((--))
#M-~-~-~
""",
"""
#Y[[--]]
#M~-~-~-
- """
+ """,
)
saucer = SaucerGlyph(
@@ -351,35 +354,49 @@ def init_glyph(session):
#M|
#M- #Y+++ #M-
#M|
- """
+ """,
)
- ship = PlayerGlyph("ship", """
+ ship = PlayerGlyph(
+ "ship",
+ """
#Y^
#G=====
- """)
+ """,
+ )
- missile = MissileGlyph("missile", """
+ missile = MissileGlyph(
+ "missile",
+ """
|
- """)
+ """,
+ )
start = MessageGlyph(
"start_message",
"J = move left; L = move right; SPACE = fire\n"
- " #GPress any key to start")
- lose = MessageGlyph("lose_message",
- "#YY O U L O S E ! ! !")
- win = MessageGlyph(
- "win_message",
- "#RL E V E L C L E A R E D ! ! !"
+ " #GPress any key to start",
)
+ lose = MessageGlyph("lose_message", "#YY O U L O S E ! ! !")
+ win = MessageGlyph("win_message", "#RL E V E L C L E A R E D ! ! !")
paused = MessageGlyph(
- "pause_message",
- "#WP A U S E D\n#GPress P to continue")
+ "pause_message", "#WP A U S E D\n#GPress P to continue"
+ )
session.add_all(
- [enemy1, enemy2, enemy3, ship, saucer,
- missile, start, lose, win,
- paused, splat1])
+ [
+ enemy1,
+ enemy2,
+ enemy3,
+ ship,
+ saucer,
+ missile,
+ start,
+ lose,
+ win,
+ paused,
+ splat1,
+ ]
+ )
def setup_curses():
@@ -392,7 +409,8 @@ def setup_curses():
WINDOW_HEIGHT + (VERT_PADDING * 2),
WINDOW_WIDTH + (HORIZ_PADDING * 2),
WINDOW_TOP - VERT_PADDING,
- WINDOW_LEFT - HORIZ_PADDING)
+ WINDOW_LEFT - HORIZ_PADDING,
+ )
curses.start_color()
global _COLOR_PAIRS
@@ -416,24 +434,25 @@ def init_positions(session):
session.add(
GlyphCoordinate(
- session, "ship",
- WINDOW_WIDTH // 2 - 2,
- WINDOW_HEIGHT - 4)
+ session, "ship", WINDOW_WIDTH // 2 - 2, WINDOW_HEIGHT - 4
+ )
)
arrangement = (
- ("enemy3", 50), ("enemy2", 25),
- ("enemy1", 10), ("enemy2", 25),
- ("enemy1", 10))
+ ("enemy3", 50),
+ ("enemy2", 25),
+ ("enemy1", 10),
+ ("enemy2", 25),
+ ("enemy1", 10),
+ )
for (ship_vert, (etype, score)) in zip(
- xrange(5, 30, ENEMY_VERT_SPACING), arrangement):
+ xrange(5, 30, ENEMY_VERT_SPACING), arrangement
+ ):
for ship_horiz in xrange(0, 50, 10):
session.add(
GlyphCoordinate(
- session, etype,
- ship_horiz,
- ship_vert,
- score=score)
+ session, etype, ship_horiz, ship_vert, score=score
+ )
)
@@ -442,12 +461,9 @@ def draw(session, window, state):
database and render.
"""
- for gcoord in session.query(GlyphCoordinate).\
- options(joinedload("glyph")):
+ for gcoord in session.query(GlyphCoordinate).options(joinedload("glyph")):
gcoord.render(window, state)
- window.addstr(
- 1, WINDOW_WIDTH - 5,
- "Score: %.4d" % state['score'])
+ window.addstr(1, WINDOW_WIDTH - 5, "Score: %.4d" % state["score"])
window.move(0, 0)
window.refresh()
@@ -456,11 +472,11 @@ def check_win(session, state):
"""Return the number of army glyphs remaining -
the player wins if this is zero."""
- return session.query(
- func.count(GlyphCoordinate.id)
- ).join(
- GlyphCoordinate.glyph.of_type(ArmyGlyph)
- ).scalar()
+ return (
+ session.query(func.count(GlyphCoordinate.id))
+ .join(GlyphCoordinate.glyph.of_type(ArmyGlyph))
+ .scalar()
+ )
def check_lose(session, state):
@@ -470,12 +486,14 @@ def check_lose(session, state):
The player loses if this is non-zero."""
player = state["player"]
- return session.query(GlyphCoordinate).join(
- GlyphCoordinate.glyph.of_type(ArmyGlyph)
- ).filter(
- GlyphCoordinate.intersects(player) |
- GlyphCoordinate.bottom_bound
- ).count()
+ return (
+ session.query(GlyphCoordinate)
+ .join(GlyphCoordinate.glyph.of_type(ArmyGlyph))
+ .filter(
+ GlyphCoordinate.intersects(player) | GlyphCoordinate.bottom_bound
+ )
+ .count()
+ )
def render_message(session, window, msg, x, y):
@@ -490,9 +508,11 @@ def render_message(session, window, msg, x, y):
msg = GlyphCoordinate(session, msg, x, y)
# clear existing glyphs which intersect
- for gly in session.query(GlyphCoordinate).join(
- GlyphCoordinate.glyph
- ).filter(GlyphCoordinate.intersects(msg)):
+ for gly in (
+ session.query(GlyphCoordinate)
+ .join(GlyphCoordinate.glyph)
+ .filter(GlyphCoordinate.intersects(msg))
+ ):
gly.blank(window)
# render
@@ -551,12 +571,14 @@ def move_army(session, window, state):
# get the lower/upper boundaries of the army
# along the X axis.
- min_x, max_x = session.query(
- func.min(GlyphCoordinate.x),
- func.max(GlyphCoordinate.x + GlyphCoordinate.width),
- ).join(
- GlyphCoordinate.glyph.of_type(ArmyGlyph)
- ).first()
+ min_x, max_x = (
+ session.query(
+ func.min(GlyphCoordinate.x),
+ func.max(GlyphCoordinate.x + GlyphCoordinate.width),
+ )
+ .join(GlyphCoordinate.glyph.of_type(ArmyGlyph))
+ .first()
+ )
if min_x is None or max_x is None:
# no enemies
@@ -603,27 +625,26 @@ def move_player(session, window, state):
player.x -= 1
elif ch == FIRE_KEY and state["missile"] is None:
state["missile"] = GlyphCoordinate(
- session,
- "missile",
- player.x + 3,
- player.y - 1)
+ session, "missile", player.x + 3, player.y - 1
+ )
def move_missile(session, window, state):
"""Update the status of the current missile, if any."""
- if state["missile"] is None or \
- state["tick"] % 2 != 0:
+ if state["missile"] is None or state["tick"] % 2 != 0:
return
missile = state["missile"]
# locate enemy glyphs which intersect with the
# missile's current position; i.e. a hit
- glyph = session.query(GlyphCoordinate).\
- join(GlyphCoordinate.glyph.of_type(EnemyGlyph)).\
- filter(GlyphCoordinate.intersects(missile)).\
- first()
+ glyph = (
+ session.query(GlyphCoordinate)
+ .join(GlyphCoordinate.glyph.of_type(EnemyGlyph))
+ .filter(GlyphCoordinate.intersects(missile))
+ .first()
+ )
missile.blank(window)
if glyph or missile.top_bound:
# missle is done
@@ -642,15 +663,13 @@ def move_saucer(session, window, state):
saucer_interval = 500
saucer_speed_interval = 4
- if state["saucer"] is None and \
- state["tick"] % saucer_interval != 0:
+ if state["saucer"] is None and state["tick"] % saucer_interval != 0:
return
if state["saucer"] is None:
state["saucer"] = saucer = GlyphCoordinate(
- session,
- "saucer", -6, 1,
- score=random.randrange(100, 600, 100))
+ session, "saucer", -6, 1, score=random.randrange(100, 600, 100)
+ )
elif state["tick"] % saucer_speed_interval == 0:
saucer = state["saucer"]
saucer.blank(window)
@@ -663,8 +682,9 @@ def move_saucer(session, window, state):
def update_splat(session, window, state):
"""Render splat animations."""
- for splat in session.query(GlyphCoordinate).\
- join(GlyphCoordinate.glyph.of_type(SplatGlyph)):
+ for splat in session.query(GlyphCoordinate).join(
+ GlyphCoordinate.glyph.of_type(SplatGlyph)
+ ):
age = state["tick"] - splat.tick
if age > 10:
splat.blank(window)
@@ -683,8 +703,13 @@ def score(session, window, state, glyph):
state["score"] += glyph.score
# render a splat !
GlyphCoordinate(
- session, "splat1", glyph.x, glyph.y,
- tick=state["tick"], label=str(glyph.score))
+ session,
+ "splat1",
+ glyph.x,
+ glyph.y,
+ tick=state["tick"],
+ label=str(glyph.score),
+ )
def update_state(session, window, state):
@@ -713,19 +738,23 @@ def start(session, window, state, continue_=False):
init_positions(session)
- player = session.query(GlyphCoordinate).join(
- GlyphCoordinate.glyph.of_type(PlayerGlyph)
- ).one()
- state.update({
- "field_pos": 0,
- "alt": False,
- "tick": 0,
- "missile": None,
- "saucer": None,
- "player": player,
- "army_direction": 0,
- "flip": False
- })
+ player = (
+ session.query(GlyphCoordinate)
+ .join(GlyphCoordinate.glyph.of_type(PlayerGlyph))
+ .one()
+ )
+ state.update(
+ {
+ "field_pos": 0,
+ "alt": False,
+ "tick": 0,
+ "missile": None,
+ "saucer": None,
+ "player": player,
+ "army_direction": 0,
+ "flip": False,
+ }
+ )
if not continue_:
state["score"] = 0
@@ -748,7 +777,8 @@ def main():
while True:
update_state(session, window, state)
draw(session, window, state)
- time.sleep(.01)
+ time.sleep(0.01)
+
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
diff --git a/examples/versioned_history/__init__.py b/examples/versioned_history/__init__.py
index 7478450ac..7670cd613 100644
--- a/examples/versioned_history/__init__.py
+++ b/examples/versioned_history/__init__.py
@@ -60,4 +60,4 @@ can be applied::
.. autosource::
-""" \ No newline at end of file
+"""
diff --git a/examples/versioned_history/history_meta.py b/examples/versioned_history/history_meta.py
index bad60a398..749a6a5ca 100644
--- a/examples/versioned_history/history_meta.py
+++ b/examples/versioned_history/history_meta.py
@@ -30,7 +30,7 @@ def _history_mapper(local_mapper):
getattr(local_mapper.class_, prop.key).impl.active_history = True
super_mapper = local_mapper.inherits
- super_history_mapper = getattr(cls, '__history_mapper__', None)
+ super_history_mapper = getattr(cls, "__history_mapper__", None)
polymorphic_on = None
super_fks = []
@@ -38,18 +38,20 @@ def _history_mapper(local_mapper):
def _col_copy(col):
orig = col
col = col.copy()
- orig.info['history_copy'] = col
+ orig.info["history_copy"] = col
col.unique = False
col.default = col.server_default = None
col.autoincrement = False
return col
properties = util.OrderedDict()
- if not super_mapper or \
- local_mapper.local_table is not super_mapper.local_table:
+ if (
+ not super_mapper
+ or local_mapper.local_table is not super_mapper.local_table
+ ):
cols = []
version_meta = {"version_meta": True} # add column.info to identify
- # columns specific to versioning
+ # columns specific to versioning
for column in local_mapper.local_table.c:
if _is_versioning_col(column):
@@ -57,12 +59,13 @@ def _history_mapper(local_mapper):
col = _col_copy(column)
- if super_mapper and \
- col_references_table(column, super_mapper.local_table):
+ if super_mapper and col_references_table(
+ column, super_mapper.local_table
+ ):
super_fks.append(
(
col.key,
- list(super_history_mapper.local_table.primary_key)[0]
+ list(super_history_mapper.local_table.primary_key)[0],
)
)
@@ -73,38 +76,48 @@ def _history_mapper(local_mapper):
orig_prop = local_mapper.get_property_by_column(column)
# carry over column re-mappings
- if len(orig_prop.columns) > 1 or \
- orig_prop.columns[0].key != orig_prop.key:
+ if (
+ len(orig_prop.columns) > 1
+ or orig_prop.columns[0].key != orig_prop.key
+ ):
properties[orig_prop.key] = tuple(
- col.info['history_copy'] for col in orig_prop.columns)
+ col.info["history_copy"] for col in orig_prop.columns
+ )
if super_mapper:
super_fks.append(
- (
- 'version', super_history_mapper.local_table.c.version
- )
+ ("version", super_history_mapper.local_table.c.version)
)
# "version" stores the integer version id. This column is
# required.
cols.append(
Column(
- 'version', Integer, primary_key=True,
- autoincrement=False, info=version_meta))
+ "version",
+ Integer,
+ primary_key=True,
+ autoincrement=False,
+ info=version_meta,
+ )
+ )
# "changed" column stores the UTC timestamp of when the
# history row was created.
# This column is optional and can be omitted.
- cols.append(Column(
- 'changed', DateTime,
- default=datetime.datetime.utcnow,
- info=version_meta))
+ cols.append(
+ Column(
+ "changed",
+ DateTime,
+ default=datetime.datetime.utcnow,
+ info=version_meta,
+ )
+ )
if super_fks:
cols.append(ForeignKeyConstraint(*zip(*super_fks)))
table = Table(
- local_mapper.local_table.name + '_history',
+ local_mapper.local_table.name + "_history",
local_mapper.local_table.metadata,
*cols,
schema=local_mapper.local_table.schema
@@ -122,9 +135,8 @@ def _history_mapper(local_mapper):
bases = (super_history_mapper.class_,)
if table is not None:
- properties['changed'] = (
- (table.c.changed, ) +
- tuple(super_history_mapper.attrs.changed.columns)
+ properties["changed"] = (table.c.changed,) + tuple(
+ super_history_mapper.attrs.changed.columns
)
else:
@@ -137,16 +149,17 @@ def _history_mapper(local_mapper):
inherits=super_history_mapper,
polymorphic_on=polymorphic_on,
polymorphic_identity=local_mapper.polymorphic_identity,
- properties=properties
+ properties=properties,
)
cls.__history_mapper__ = m
if not super_history_mapper:
local_mapper.local_table.append_column(
- Column('version', Integer, default=1, nullable=False)
+ Column("version", Integer, default=1, nullable=False)
)
local_mapper.add_property(
- "version", local_mapper.local_table.c.version)
+ "version", local_mapper.local_table.c.version
+ )
class Versioned(object):
@@ -156,16 +169,17 @@ class Versioned(object):
mp = mapper(cls, *arg, **kw)
_history_mapper(mp)
return mp
+
return map
- __table_args__ = {'sqlite_autoincrement': True}
+ __table_args__ = {"sqlite_autoincrement": True}
"""Use sqlite_autoincrement, to ensure unique integer values
are used for new rows even for rows taht have been deleted."""
def versioned_objects(iter):
for obj in iter:
- if hasattr(obj, '__history_mapper__'):
+ if hasattr(obj, "__history_mapper__"):
yield obj
@@ -181,8 +195,7 @@ def create_version(obj, session, deleted=False):
obj_changed = False
for om, hm in zip(
- obj_mapper.iterate_to_root(),
- history_mapper.iterate_to_root()
+ obj_mapper.iterate_to_root(), history_mapper.iterate_to_root()
):
if hm.single:
continue
@@ -228,10 +241,12 @@ def create_version(obj, session, deleted=False):
# not changed, but we have relationships. OK
# check those too
for prop in obj_mapper.iterate_properties:
- if isinstance(prop, RelationshipProperty) and \
- attributes.get_history(
- obj, prop.key,
- passive=attributes.PASSIVE_NO_INITIALIZE).has_changes():
+ if (
+ isinstance(prop, RelationshipProperty)
+ and attributes.get_history(
+ obj, prop.key, passive=attributes.PASSIVE_NO_INITIALIZE
+ ).has_changes()
+ ):
for p in prop.local_columns:
if p.foreign_keys:
obj_changed = True
@@ -242,7 +257,7 @@ def create_version(obj, session, deleted=False):
if not obj_changed and not deleted:
return
- attr['version'] = obj.version
+ attr["version"] = obj.version
hist = history_cls()
for key, value in attr.items():
setattr(hist, key, value)
@@ -251,7 +266,7 @@ def create_version(obj, session, deleted=False):
def versioned_session(session):
- @event.listens_for(session, 'before_flush')
+ @event.listens_for(session, "before_flush")
def before_flush(session, flush_context, instances):
for obj in versioned_objects(session.dirty):
create_version(obj, session)
diff --git a/examples/versioned_history/test_versioning.py b/examples/versioned_history/test_versioning.py
index 37ef73936..3270ad5fd 100644
--- a/examples/versioned_history/test_versioning.py
+++ b/examples/versioned_history/test_versioning.py
@@ -4,10 +4,22 @@ module functions."""
from unittest import TestCase
from sqlalchemy.ext.declarative import declarative_base
from .history_meta import Versioned, versioned_session
-from sqlalchemy import create_engine, Column, Integer, String, \
- ForeignKey, Boolean, select
-from sqlalchemy.orm import clear_mappers, Session, deferred, relationship, \
- column_property
+from sqlalchemy import (
+ create_engine,
+ Column,
+ Integer,
+ String,
+ ForeignKey,
+ Boolean,
+ select,
+)
+from sqlalchemy.orm import (
+ clear_mappers,
+ Session,
+ deferred,
+ relationship,
+ column_property,
+)
from sqlalchemy.testing import AssertsCompiledSQL, eq_, assert_raises, ne_
from sqlalchemy.testing.entities import ComparableEntity
from sqlalchemy.orm import exc as orm_exc
@@ -20,11 +32,11 @@ engine = None
def setup_module():
global engine
- engine = create_engine('sqlite://', echo=True)
+ engine = create_engine("sqlite://", echo=True)
class TestVersioning(TestCase, AssertsCompiledSQL):
- __dialect__ = 'default'
+ __dialect__ = "default"
def setUp(self):
self.session = Session(engine)
@@ -41,18 +53,18 @@ class TestVersioning(TestCase, AssertsCompiledSQL):
def test_plain(self):
class SomeClass(Versioned, self.Base, ComparableEntity):
- __tablename__ = 'sometable'
+ __tablename__ = "sometable"
id = Column(Integer, primary_key=True)
name = Column(String(50))
self.create_tables()
sess = self.session
- sc = SomeClass(name='sc1')
+ sc = SomeClass(name="sc1")
sess.add(sc)
sess.commit()
- sc.name = 'sc1modified'
+ sc.name = "sc1modified"
sess.commit()
assert sc.version == 2
@@ -60,56 +72,60 @@ class TestVersioning(TestCase, AssertsCompiledSQL):
SomeClassHistory = SomeClass.__history_mapper__.class_
eq_(
- sess.query(SomeClassHistory).filter(
- SomeClassHistory.version == 1).all(),
- [SomeClassHistory(version=1, name='sc1')]
+ sess.query(SomeClassHistory)
+ .filter(SomeClassHistory.version == 1)
+ .all(),
+ [SomeClassHistory(version=1, name="sc1")],
)
- sc.name = 'sc1modified2'
+ sc.name = "sc1modified2"
eq_(
- sess.query(SomeClassHistory).order_by(
- SomeClassHistory.version).all(),
+ sess.query(SomeClassHistory)
+ .order_by(SomeClassHistory.version)
+ .all(),
[
- SomeClassHistory(version=1, name='sc1'),
- SomeClassHistory(version=2, name='sc1modified')
- ]
+ SomeClassHistory(version=1, name="sc1"),
+ SomeClassHistory(version=2, name="sc1modified"),
+ ],
)
assert sc.version == 3
sess.commit()
- sc.name = 'temp'
- sc.name = 'sc1modified2'
+ sc.name = "temp"
+ sc.name = "sc1modified2"
sess.commit()
eq_(
- sess.query(SomeClassHistory).order_by(
- SomeClassHistory.version).all(),
+ sess.query(SomeClassHistory)
+ .order_by(SomeClassHistory.version)
+ .all(),
[
- SomeClassHistory(version=1, name='sc1'),
- SomeClassHistory(version=2, name='sc1modified')
- ]
+ SomeClassHistory(version=1, name="sc1"),
+ SomeClassHistory(version=2, name="sc1modified"),
+ ],
)
sess.delete(sc)
sess.commit()
eq_(
- sess.query(SomeClassHistory).order_by(
- SomeClassHistory.version).all(),
+ sess.query(SomeClassHistory)
+ .order_by(SomeClassHistory.version)
+ .all(),
[
- SomeClassHistory(version=1, name='sc1'),
- SomeClassHistory(version=2, name='sc1modified'),
- SomeClassHistory(version=3, name='sc1modified2')
- ]
+ SomeClassHistory(version=1, name="sc1"),
+ SomeClassHistory(version=2, name="sc1modified"),
+ SomeClassHistory(version=3, name="sc1modified2"),
+ ],
)
def test_w_mapper_versioning(self):
class SomeClass(Versioned, self.Base, ComparableEntity):
- __tablename__ = 'sometable'
+ __tablename__ = "sometable"
id = Column(Integer, primary_key=True)
name = Column(String(50))
@@ -118,27 +134,24 @@ class TestVersioning(TestCase, AssertsCompiledSQL):
self.create_tables()
sess = self.session
- sc = SomeClass(name='sc1')
+ sc = SomeClass(name="sc1")
sess.add(sc)
sess.commit()
s2 = Session(sess.bind)
sc2 = s2.query(SomeClass).first()
- sc2.name = 'sc1modified'
+ sc2.name = "sc1modified"
- sc.name = 'sc1modified_again'
+ sc.name = "sc1modified_again"
sess.commit()
eq_(sc.version, 2)
- assert_raises(
- orm_exc.StaleDataError,
- s2.flush
- )
+ assert_raises(orm_exc.StaleDataError, s2.flush)
def test_from_null(self):
class SomeClass(Versioned, self.Base, ComparableEntity):
- __tablename__ = 'sometable'
+ __tablename__ = "sometable"
id = Column(Integer, primary_key=True)
name = Column(String(50))
@@ -149,14 +162,14 @@ class TestVersioning(TestCase, AssertsCompiledSQL):
sess.add(sc)
sess.commit()
- sc.name = 'sc1'
+ sc.name = "sc1"
sess.commit()
assert sc.version == 2
def test_insert_null(self):
class SomeClass(Versioned, self.Base, ComparableEntity):
- __tablename__ = 'sometable'
+ __tablename__ = "sometable"
id = Column(Integer, primary_key=True)
boole = Column(Boolean, default=False)
@@ -176,9 +189,10 @@ class TestVersioning(TestCase, AssertsCompiledSQL):
SomeClassHistory = SomeClass.__history_mapper__.class_
eq_(
- sess.query(SomeClassHistory.boole).order_by(
- SomeClassHistory.id).all(),
- [(True, ), (None, )]
+ sess.query(SomeClassHistory.boole)
+ .order_by(SomeClassHistory.id)
+ .all(),
+ [(True,), (None,)],
)
eq_(sc.version, 3)
@@ -187,7 +201,7 @@ class TestVersioning(TestCase, AssertsCompiledSQL):
"""test versioning of unloaded, deferred columns."""
class SomeClass(Versioned, self.Base, ComparableEntity):
- __tablename__ = 'sometable'
+ __tablename__ = "sometable"
id = Column(Integer, primary_key=True)
name = Column(String(50))
@@ -195,15 +209,15 @@ class TestVersioning(TestCase, AssertsCompiledSQL):
self.create_tables()
sess = self.session
- sc = SomeClass(name='sc1', data='somedata')
+ sc = SomeClass(name="sc1", data="somedata")
sess.add(sc)
sess.commit()
sess.close()
sc = sess.query(SomeClass).first()
- assert 'data' not in sc.__dict__
+ assert "data" not in sc.__dict__
- sc.name = 'sc1modified'
+ sc.name = "sc1modified"
sess.commit()
assert sc.version == 2
@@ -211,137 +225,149 @@ class TestVersioning(TestCase, AssertsCompiledSQL):
SomeClassHistory = SomeClass.__history_mapper__.class_
eq_(
- sess.query(SomeClassHistory).filter(
- SomeClassHistory.version == 1).all(),
- [SomeClassHistory(version=1, name='sc1', data='somedata')]
+ sess.query(SomeClassHistory)
+ .filter(SomeClassHistory.version == 1)
+ .all(),
+ [SomeClassHistory(version=1, name="sc1", data="somedata")],
)
def test_joined_inheritance(self):
class BaseClass(Versioned, self.Base, ComparableEntity):
- __tablename__ = 'basetable'
+ __tablename__ = "basetable"
id = Column(Integer, primary_key=True)
name = Column(String(50))
type = Column(String(20))
__mapper_args__ = {
- 'polymorphic_on': type,
- 'polymorphic_identity': 'base'}
+ "polymorphic_on": type,
+ "polymorphic_identity": "base",
+ }
class SubClassSeparatePk(BaseClass):
- __tablename__ = 'subtable1'
+ __tablename__ = "subtable1"
id = column_property(
- Column(Integer, primary_key=True),
- BaseClass.id
+ Column(Integer, primary_key=True), BaseClass.id
)
- base_id = Column(Integer, ForeignKey('basetable.id'))
+ base_id = Column(Integer, ForeignKey("basetable.id"))
subdata1 = Column(String(50))
- __mapper_args__ = {'polymorphic_identity': 'sep'}
+ __mapper_args__ = {"polymorphic_identity": "sep"}
class SubClassSamePk(BaseClass):
- __tablename__ = 'subtable2'
+ __tablename__ = "subtable2"
- id = Column(
- Integer, ForeignKey('basetable.id'), primary_key=True)
+ id = Column(Integer, ForeignKey("basetable.id"), primary_key=True)
subdata2 = Column(String(50))
- __mapper_args__ = {'polymorphic_identity': 'same'}
+ __mapper_args__ = {"polymorphic_identity": "same"}
self.create_tables()
sess = self.session
- sep1 = SubClassSeparatePk(name='sep1', subdata1='sep1subdata')
- base1 = BaseClass(name='base1')
- same1 = SubClassSamePk(name='same1', subdata2='same1subdata')
+ sep1 = SubClassSeparatePk(name="sep1", subdata1="sep1subdata")
+ base1 = BaseClass(name="base1")
+ same1 = SubClassSamePk(name="same1", subdata2="same1subdata")
sess.add_all([sep1, base1, same1])
sess.commit()
- base1.name = 'base1mod'
- same1.subdata2 = 'same1subdatamod'
- sep1.name = 'sep1mod'
+ base1.name = "base1mod"
+ same1.subdata2 = "same1subdatamod"
+ sep1.name = "sep1mod"
sess.commit()
BaseClassHistory = BaseClass.__history_mapper__.class_
- SubClassSeparatePkHistory = \
+ SubClassSeparatePkHistory = (
SubClassSeparatePk.__history_mapper__.class_
+ )
SubClassSamePkHistory = SubClassSamePk.__history_mapper__.class_
eq_(
sess.query(BaseClassHistory).order_by(BaseClassHistory.id).all(),
[
SubClassSeparatePkHistory(
- id=1, name='sep1', type='sep', version=1),
- BaseClassHistory(id=2, name='base1', type='base', version=1),
+ id=1, name="sep1", type="sep", version=1
+ ),
+ BaseClassHistory(id=2, name="base1", type="base", version=1),
SubClassSamePkHistory(
- id=3, name='same1', type='same', version=1)
- ]
+ id=3, name="same1", type="same", version=1
+ ),
+ ],
)
- same1.subdata2 = 'same1subdatamod2'
+ same1.subdata2 = "same1subdatamod2"
eq_(
- sess.query(BaseClassHistory).order_by(
- BaseClassHistory.id, BaseClassHistory.version).all(),
+ sess.query(BaseClassHistory)
+ .order_by(BaseClassHistory.id, BaseClassHistory.version)
+ .all(),
[
SubClassSeparatePkHistory(
- id=1, name='sep1', type='sep', version=1),
- BaseClassHistory(id=2, name='base1', type='base', version=1),
+ id=1, name="sep1", type="sep", version=1
+ ),
+ BaseClassHistory(id=2, name="base1", type="base", version=1),
SubClassSamePkHistory(
- id=3, name='same1', type='same', version=1),
+ id=3, name="same1", type="same", version=1
+ ),
SubClassSamePkHistory(
- id=3, name='same1', type='same', version=2)
- ]
+ id=3, name="same1", type="same", version=2
+ ),
+ ],
)
- base1.name = 'base1mod2'
+ base1.name = "base1mod2"
eq_(
- sess.query(BaseClassHistory).order_by(
- BaseClassHistory.id, BaseClassHistory.version).all(),
+ sess.query(BaseClassHistory)
+ .order_by(BaseClassHistory.id, BaseClassHistory.version)
+ .all(),
[
SubClassSeparatePkHistory(
- id=1, name='sep1', type='sep', version=1),
- BaseClassHistory(id=2, name='base1', type='base', version=1),
+ id=1, name="sep1", type="sep", version=1
+ ),
+ BaseClassHistory(id=2, name="base1", type="base", version=1),
BaseClassHistory(
- id=2, name='base1mod', type='base', version=2),
+ id=2, name="base1mod", type="base", version=2
+ ),
SubClassSamePkHistory(
- id=3, name='same1', type='same', version=1),
+ id=3, name="same1", type="same", version=1
+ ),
SubClassSamePkHistory(
- id=3, name='same1', type='same', version=2)
- ]
+ id=3, name="same1", type="same", version=2
+ ),
+ ],
)
def test_joined_inheritance_multilevel(self):
class BaseClass(Versioned, self.Base, ComparableEntity):
- __tablename__ = 'basetable'
+ __tablename__ = "basetable"
id = Column(Integer, primary_key=True)
name = Column(String(50))
type = Column(String(20))
__mapper_args__ = {
- 'polymorphic_on': type,
- 'polymorphic_identity': 'base'}
+ "polymorphic_on": type,
+ "polymorphic_identity": "base",
+ }
class SubClass(BaseClass):
- __tablename__ = 'subtable'
+ __tablename__ = "subtable"
id = column_property(
- Column(Integer, primary_key=True),
- BaseClass.id
+ Column(Integer, primary_key=True), BaseClass.id
)
- base_id = Column(Integer, ForeignKey('basetable.id'))
+ base_id = Column(Integer, ForeignKey("basetable.id"))
subdata1 = Column(String(50))
- __mapper_args__ = {'polymorphic_identity': 'sub'}
+ __mapper_args__ = {"polymorphic_identity": "sub"}
class SubSubClass(SubClass):
- __tablename__ = 'subsubtable'
+ __tablename__ = "subsubtable"
- id = Column(Integer, ForeignKey('subtable.id'), primary_key=True)
+ id = Column(Integer, ForeignKey("subtable.id"), primary_key=True)
subdata2 = Column(String(50))
- __mapper_args__ = {'polymorphic_identity': 'subsub'}
+ __mapper_args__ = {"polymorphic_identity": "subsub"}
self.create_tables()
@@ -350,27 +376,18 @@ class TestVersioning(TestCase, AssertsCompiledSQL):
q = sess.query(SubSubHistory)
self.assert_compile(
q,
-
-
"SELECT "
-
"subsubtable_history.id AS subsubtable_history_id, "
"subtable_history.id AS subtable_history_id, "
"basetable_history.id AS basetable_history_id, "
-
"subsubtable_history.changed AS subsubtable_history_changed, "
"subtable_history.changed AS subtable_history_changed, "
"basetable_history.changed AS basetable_history_changed, "
-
"basetable_history.name AS basetable_history_name, "
-
"basetable_history.type AS basetable_history_type, "
-
"subsubtable_history.version AS subsubtable_history_version, "
"subtable_history.version AS subtable_history_version, "
"basetable_history.version AS basetable_history_version, "
-
-
"subtable_history.base_id AS subtable_history_base_id, "
"subtable_history.subdata1 AS subtable_history_subdata1, "
"subsubtable_history.subdata2 AS subsubtable_history_subdata2 "
@@ -380,64 +397,73 @@ class TestVersioning(TestCase, AssertsCompiledSQL):
"AND basetable_history.version = subtable_history.version "
"JOIN subsubtable_history ON subtable_history.id = "
"subsubtable_history.id AND subtable_history.version = "
- "subsubtable_history.version"
+ "subsubtable_history.version",
)
- ssc = SubSubClass(name='ss1', subdata1='sd1', subdata2='sd2')
+ ssc = SubSubClass(name="ss1", subdata1="sd1", subdata2="sd2")
sess.add(ssc)
sess.commit()
+ eq_(sess.query(SubSubHistory).all(), [])
+ ssc.subdata1 = "sd11"
+ ssc.subdata2 = "sd22"
+ sess.commit()
eq_(
sess.query(SubSubHistory).all(),
- []
+ [
+ SubSubHistory(
+ name="ss1",
+ subdata1="sd1",
+ subdata2="sd2",
+ type="subsub",
+ version=1,
+ )
+ ],
)
- ssc.subdata1 = 'sd11'
- ssc.subdata2 = 'sd22'
- sess.commit()
eq_(
- sess.query(SubSubHistory).all(),
- [SubSubHistory(name='ss1', subdata1='sd1',
- subdata2='sd2', type='subsub', version=1)]
+ ssc,
+ SubSubClass(
+ name="ss1", subdata1="sd11", subdata2="sd22", version=2
+ ),
)
- eq_(ssc, SubSubClass(
- name='ss1', subdata1='sd11',
- subdata2='sd22', version=2))
def test_joined_inheritance_changed(self):
class BaseClass(Versioned, self.Base, ComparableEntity):
- __tablename__ = 'basetable'
+ __tablename__ = "basetable"
id = Column(Integer, primary_key=True)
name = Column(String(50))
type = Column(String(20))
__mapper_args__ = {
- 'polymorphic_on': type,
- 'polymorphic_identity': 'base'
+ "polymorphic_on": type,
+ "polymorphic_identity": "base",
}
class SubClass(BaseClass):
- __tablename__ = 'subtable'
+ __tablename__ = "subtable"
- id = Column(Integer, ForeignKey('basetable.id'), primary_key=True)
+ id = Column(Integer, ForeignKey("basetable.id"), primary_key=True)
- __mapper_args__ = {'polymorphic_identity': 'sep'}
+ __mapper_args__ = {"polymorphic_identity": "sep"}
self.create_tables()
BaseClassHistory = BaseClass.__history_mapper__.class_
SubClassHistory = SubClass.__history_mapper__.class_
sess = self.session
- s1 = SubClass(name='s1')
+ s1 = SubClass(name="s1")
sess.add(s1)
sess.commit()
- s1.name = 's2'
+ s1.name = "s2"
sess.commit()
actual_changed_base = sess.scalar(
- select([BaseClass.__history_mapper__.local_table.c.changed]))
+ select([BaseClass.__history_mapper__.local_table.c.changed])
+ )
actual_changed_sub = sess.scalar(
- select([SubClass.__history_mapper__.local_table.c.changed]))
+ select([SubClass.__history_mapper__.local_table.c.changed])
+ )
h1 = sess.query(BaseClassHistory).first()
eq_(h1.changed, actual_changed_base)
eq_(h1.changed, actual_changed_sub)
@@ -448,53 +474,57 @@ class TestVersioning(TestCase, AssertsCompiledSQL):
def test_single_inheritance(self):
class BaseClass(Versioned, self.Base, ComparableEntity):
- __tablename__ = 'basetable'
+ __tablename__ = "basetable"
id = Column(Integer, primary_key=True)
name = Column(String(50))
type = Column(String(50))
__mapper_args__ = {
- 'polymorphic_on': type,
- 'polymorphic_identity': 'base'}
+ "polymorphic_on": type,
+ "polymorphic_identity": "base",
+ }
class SubClass(BaseClass):
subname = Column(String(50), unique=True)
- __mapper_args__ = {'polymorphic_identity': 'sub'}
+ __mapper_args__ = {"polymorphic_identity": "sub"}
self.create_tables()
sess = self.session
- b1 = BaseClass(name='b1')
- sc = SubClass(name='s1', subname='sc1')
+ b1 = BaseClass(name="b1")
+ sc = SubClass(name="s1", subname="sc1")
sess.add_all([b1, sc])
sess.commit()
- b1.name = 'b1modified'
+ 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='b1', type='base', version=1)]
+ sess.query(BaseClassHistory)
+ .order_by(BaseClassHistory.id, BaseClassHistory.version)
+ .all(),
+ [BaseClassHistory(id=1, name="b1", type="base", version=1)],
)
- sc.name = 's1modified'
- b1.name = 'b1modified2'
+ sc.name = "s1modified"
+ b1.name = "b1modified2"
eq_(
- sess.query(BaseClassHistory).order_by(
- BaseClassHistory.id, BaseClassHistory.version).all(),
+ sess.query(BaseClassHistory)
+ .order_by(BaseClassHistory.id, BaseClassHistory.version)
+ .all(),
[
- BaseClassHistory(id=1, name='b1', type='base', version=1),
+ BaseClassHistory(id=1, name="b1", type="base", version=1),
BaseClassHistory(
- id=1, name='b1modified', type='base', version=2),
- SubClassHistory(id=2, name='s1', type='sub', version=1)
- ]
+ id=1, name="b1modified", type="base", version=2
+ ),
+ SubClassHistory(id=2, name="s1", type="sub", version=1),
+ ],
)
# test the unique constraint on the subclass
@@ -504,7 +534,7 @@ class TestVersioning(TestCase, AssertsCompiledSQL):
def test_unique(self):
class SomeClass(Versioned, self.Base, ComparableEntity):
- __tablename__ = 'sometable'
+ __tablename__ = "sometable"
id = Column(Integer, primary_key=True)
name = Column(String(50), unique=True)
@@ -512,40 +542,39 @@ class TestVersioning(TestCase, AssertsCompiledSQL):
self.create_tables()
sess = self.session
- sc = SomeClass(name='sc1', data='sc1')
+ sc = SomeClass(name="sc1", data="sc1")
sess.add(sc)
sess.commit()
- sc.data = 'sc1modified'
+ sc.data = "sc1modified"
sess.commit()
assert sc.version == 2
- sc.data = 'sc1modified2'
+ sc.data = "sc1modified2"
sess.commit()
assert sc.version == 3
def test_relationship(self):
-
class SomeRelated(self.Base, ComparableEntity):
- __tablename__ = 'somerelated'
+ __tablename__ = "somerelated"
id = Column(Integer, primary_key=True)
class SomeClass(Versioned, self.Base, ComparableEntity):
- __tablename__ = 'sometable'
+ __tablename__ = "sometable"
id = Column(Integer, primary_key=True)
name = Column(String(50))
- related_id = Column(Integer, ForeignKey('somerelated.id'))
- related = relationship("SomeRelated", backref='classes')
+ related_id = Column(Integer, ForeignKey("somerelated.id"))
+ related = relationship("SomeRelated", backref="classes")
SomeClassHistory = SomeClass.__history_mapper__.class_
self.create_tables()
sess = self.session
- sc = SomeClass(name='sc1')
+ sc = SomeClass(name="sc1")
sess.add(sc)
sess.commit()
@@ -558,36 +587,37 @@ class TestVersioning(TestCase, AssertsCompiledSQL):
assert sc.version == 2
eq_(
- sess.query(SomeClassHistory).filter(
- SomeClassHistory.version == 1).all(),
- [SomeClassHistory(version=1, name='sc1', related_id=None)]
+ sess.query(SomeClassHistory)
+ .filter(SomeClassHistory.version == 1)
+ .all(),
+ [SomeClassHistory(version=1, name="sc1", related_id=None)],
)
sc.related = None
eq_(
- sess.query(SomeClassHistory).order_by(
- SomeClassHistory.version).all(),
+ sess.query(SomeClassHistory)
+ .order_by(SomeClassHistory.version)
+ .all(),
[
- SomeClassHistory(version=1, name='sc1', related_id=None),
- SomeClassHistory(version=2, name='sc1', related_id=sr1.id)
- ]
+ SomeClassHistory(version=1, name="sc1", related_id=None),
+ SomeClassHistory(version=2, name="sc1", related_id=sr1.id),
+ ],
)
assert sc.version == 3
def test_backref_relationship(self):
-
class SomeRelated(self.Base, ComparableEntity):
- __tablename__ = 'somerelated'
+ __tablename__ = "somerelated"
id = Column(Integer, primary_key=True)
name = Column(String(50))
- related_id = Column(Integer, ForeignKey('sometable.id'))
- related = relationship("SomeClass", backref='related')
+ related_id = Column(Integer, ForeignKey("sometable.id"))
+ related = relationship("SomeClass", backref="related")
class SomeClass(Versioned, self.Base, ComparableEntity):
- __tablename__ = 'sometable'
+ __tablename__ = "sometable"
id = Column(Integer, primary_key=True)
@@ -599,13 +629,13 @@ class TestVersioning(TestCase, AssertsCompiledSQL):
assert sc.version == 1
- sr = SomeRelated(name='sr', related=sc)
+ sr = SomeRelated(name="sr", related=sc)
sess.add(sr)
sess.commit()
assert sc.version == 1
- sr.name = 'sr2'
+ sr.name = "sr2"
sess.commit()
assert sc.version == 1
@@ -616,9 +646,8 @@ class TestVersioning(TestCase, AssertsCompiledSQL):
assert sc.version == 1
def test_create_double_flush(self):
-
class SomeClass(Versioned, self.Base, ComparableEntity):
- __tablename__ = 'sometable'
+ __tablename__ = "sometable"
id = Column(Integer, primary_key=True)
name = Column(String(30))
@@ -629,56 +658,56 @@ class TestVersioning(TestCase, AssertsCompiledSQL):
sc = SomeClass()
self.session.add(sc)
self.session.flush()
- sc.name = 'Foo'
+ sc.name = "Foo"
self.session.flush()
assert sc.version == 2
def test_mutate_plain_column(self):
class Document(self.Base, Versioned):
- __tablename__ = 'document'
+ __tablename__ = "document"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String, nullable=True)
- description_ = Column('description', String, nullable=True)
+ description_ = Column("description", String, nullable=True)
self.create_tables()
document = Document()
self.session.add(document)
- document.name = 'Foo'
+ document.name = "Foo"
self.session.commit()
- document.name = 'Bar'
+ document.name = "Bar"
self.session.commit()
DocumentHistory = Document.__history_mapper__.class_
v2 = self.session.query(Document).one()
v1 = self.session.query(DocumentHistory).one()
self.assertEqual(v1.id, v2.id)
- self.assertEqual(v2.name, 'Bar')
- self.assertEqual(v1.name, 'Foo')
+ self.assertEqual(v2.name, "Bar")
+ self.assertEqual(v1.name, "Foo")
def test_mutate_named_column(self):
class Document(self.Base, Versioned):
- __tablename__ = 'document'
+ __tablename__ = "document"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String, nullable=True)
- description_ = Column('description', String, nullable=True)
+ description_ = Column("description", String, nullable=True)
self.create_tables()
document = Document()
self.session.add(document)
- document.description_ = 'Foo'
+ document.description_ = "Foo"
self.session.commit()
- document.description_ = 'Bar'
+ document.description_ = "Bar"
self.session.commit()
DocumentHistory = Document.__history_mapper__.class_
v2 = self.session.query(Document).one()
v1 = self.session.query(DocumentHistory).one()
self.assertEqual(v1.id, v2.id)
- self.assertEqual(v2.description_, 'Bar')
- self.assertEqual(v1.description_, 'Foo')
+ self.assertEqual(v2.description_, "Bar")
+ self.assertEqual(v1.description_, "Foo")
def test_unique_identifiers_across_deletes(self):
"""Ensure unique integer values are used for the primary table.
@@ -690,21 +719,21 @@ class TestVersioning(TestCase, AssertsCompiledSQL):
"""
class SomeClass(Versioned, self.Base, ComparableEntity):
- __tablename__ = 'sometable'
+ __tablename__ = "sometable"
id = Column(Integer, primary_key=True)
name = Column(String(50))
self.create_tables()
sess = self.session
- sc = SomeClass(name='sc1')
+ sc = SomeClass(name="sc1")
sess.add(sc)
sess.commit()
sess.delete(sc)
sess.commit()
- sc2 = SomeClass(name='sc2')
+ sc2 = SomeClass(name="sc2")
sess.add(sc2)
sess.commit()
@@ -721,5 +750,5 @@ class TestVersioning(TestCase, AssertsCompiledSQL):
ne_(sc2.id, scdeleted.id)
# If previous assertion fails, this will also fail:
- sc2.name = 'sc2 modified'
+ sc2.name = "sc2 modified"
sess.commit()
diff --git a/examples/versioned_rows/__init__.py b/examples/versioned_rows/__init__.py
index 637e1aca6..e5016a740 100644
--- a/examples/versioned_rows/__init__.py
+++ b/examples/versioned_rows/__init__.py
@@ -9,4 +9,4 @@ history row to a separate history table.
.. autosource::
-""" \ No newline at end of file
+"""
diff --git a/examples/versioned_rows/versioned_map.py b/examples/versioned_rows/versioned_map.py
index 6a5c86a3a..46bdbb783 100644
--- a/examples/versioned_rows/versioned_map.py
+++ b/examples/versioned_rows/versioned_map.py
@@ -28,11 +28,17 @@ those additional values.
"""
-from sqlalchemy import Column, String, Integer, ForeignKey, \
- create_engine
+from sqlalchemy import Column, String, Integer, ForeignKey, create_engine
from sqlalchemy.ext.declarative import declarative_base
-from sqlalchemy.orm import attributes, relationship, backref, \
- sessionmaker, make_transient, validates, Session
+from sqlalchemy.orm import (
+ attributes,
+ relationship,
+ backref,
+ sessionmaker,
+ make_transient,
+ validates,
+ Session,
+)
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.orm.collections import attribute_mapped_collection
from sqlalchemy import event
@@ -45,8 +51,9 @@ def before_flush(session, flush_context, instances):
"""
for instance in session.dirty:
- if hasattr(instance, 'new_version') and \
- session.is_modified(instance, passive=True):
+ if hasattr(instance, "new_version") and session.is_modified(
+ instance, passive=True
+ ):
# make it transient
instance.new_version(session)
@@ -54,6 +61,7 @@ def before_flush(session, flush_context, instances):
# re-add
session.add(instance)
+
Base = declarative_base()
@@ -67,7 +75,8 @@ class ConfigData(Base):
string name mapped to a string/int value.
"""
- __tablename__ = 'config'
+
+ __tablename__ = "config"
id = Column(Integer, primary_key=True)
"""Primary key column of this ConfigData."""
@@ -76,7 +85,7 @@ class ConfigData(Base):
"ConfigValueAssociation",
collection_class=attribute_mapped_collection("name"),
backref=backref("config_data"),
- lazy="subquery"
+ lazy="subquery",
)
"""Dictionary-backed collection of ConfigValueAssociation objects,
keyed to the name of the associated ConfigValue.
@@ -97,7 +106,7 @@ class ConfigData(Base):
def __init__(self, data):
self.data = data
- @validates('elements')
+ @validates("elements")
def _associate_with_element(self, key, element):
"""Associate incoming ConfigValues with this
ConfigData, if not already associated.
@@ -117,11 +126,11 @@ class ConfigData(Base):
# history of the 'elements' collection.
# this is a tuple of groups: (added, unchanged, deleted)
- hist = attributes.get_history(self, 'elements')
+ hist = attributes.get_history(self, "elements")
# rewrite the 'elements' collection
# from scratch, removing all history
- attributes.set_committed_value(self, 'elements', {})
+ attributes.set_committed_value(self, "elements", {})
# new elements in the "added" group
# are moved to our new collection.
@@ -133,7 +142,8 @@ class ConfigData(Base):
# the old ones stay associated with the old ConfigData
for elem in hist.unchanged:
self.elements[elem.name] = ConfigValueAssociation(
- elem.config_value)
+ elem.config_value
+ )
# we also need to expire changes on each ConfigValueAssociation
# that is to remain associated with the old ConfigData.
@@ -144,12 +154,12 @@ class ConfigData(Base):
class ConfigValueAssociation(Base):
"""Relate ConfigData objects to associated ConfigValue objects."""
- __tablename__ = 'config_value_association'
+ __tablename__ = "config_value_association"
- config_id = Column(ForeignKey('config.id'), primary_key=True)
+ config_id = Column(ForeignKey("config.id"), primary_key=True)
"""Reference the primary key of the ConfigData object."""
- config_value_id = Column(ForeignKey('config_value.id'), primary_key=True)
+ config_value_id = Column(ForeignKey("config_value.id"), primary_key=True)
"""Reference the primary key of the ConfigValue object."""
config_value = relationship("ConfigValue", lazy="joined", innerjoin=True)
@@ -182,8 +192,7 @@ class ConfigValueAssociation(Base):
"""
if value != self.config_value.value:
- self.config_data.elements[self.name] = \
- ConfigValueAssociation(
+ self.config_data.elements[self.name] = ConfigValueAssociation(
ConfigValue(self.config_value.name, value)
)
@@ -194,13 +203,14 @@ class ConfigValue(Base):
ConfigValue is immutable.
"""
- __tablename__ = 'config_value'
+
+ __tablename__ = "config_value"
id = Column(Integer, primary_key=True)
name = Column(String(50), nullable=False)
originating_config_id = Column(
- Integer, ForeignKey('config.id'),
- nullable=False)
+ Integer, ForeignKey("config.id"), nullable=False
+ )
int_value = Column(Integer)
string_value = Column(String(255))
@@ -221,7 +231,7 @@ class ConfigValue(Base):
@property
def value(self):
- for k in ('int_value', 'string_value'):
+ for k in ("int_value", "string_value"):
v = getattr(self, k)
if v is not None:
return v
@@ -237,25 +247,23 @@ class ConfigValue(Base):
self.string_value = str(value)
self.int_value = None
-if __name__ == '__main__':
- engine = create_engine('sqlite://', echo=True)
+
+if __name__ == "__main__":
+ engine = create_engine("sqlite://", echo=True)
Base.metadata.create_all(engine)
Session = sessionmaker(engine)
sess = Session()
- config = ConfigData({
- 'user_name': 'twitter',
- 'hash_id': '4fedffca37eaf',
- 'x': 27,
- 'y': 450
- })
+ config = ConfigData(
+ {"user_name": "twitter", "hash_id": "4fedffca37eaf", "x": 27, "y": 450}
+ )
sess.add(config)
sess.commit()
version_one = config.id
- config.data['user_name'] = 'yahoo'
+ config.data["user_name"] = "yahoo"
sess.commit()
version_two = config.id
@@ -265,27 +273,29 @@ if __name__ == '__main__':
# two versions have been created.
assert config.data == {
- 'user_name': 'yahoo',
- 'hash_id': '4fedffca37eaf',
- 'x': 27,
- 'y': 450
+ "user_name": "yahoo",
+ "hash_id": "4fedffca37eaf",
+ "x": 27,
+ "y": 450,
}
old_config = sess.query(ConfigData).get(version_one)
assert old_config.data == {
- 'user_name': 'twitter',
- 'hash_id': '4fedffca37eaf',
- 'x': 27,
- 'y': 450
+ "user_name": "twitter",
+ "hash_id": "4fedffca37eaf",
+ "x": 27,
+ "y": 450,
}
# the history of any key can be acquired using
# the originating_config_id attribute
- history = sess.query(ConfigValue).\
- filter(ConfigValue.name == 'user_name').\
- order_by(ConfigValue.originating_config_id).\
- all()
+ history = (
+ sess.query(ConfigValue)
+ .filter(ConfigValue.name == "user_name")
+ .order_by(ConfigValue.originating_config_id)
+ .all()
+ )
assert [(h.value, h.originating_config_id) for h in history] == (
- [('twitter', version_one), ('yahoo', version_two)]
+ [("twitter", version_one), ("yahoo", version_two)]
)
diff --git a/examples/versioned_rows/versioned_rows.py b/examples/versioned_rows/versioned_rows.py
index ca896190d..03e1c3510 100644
--- a/examples/versioned_rows/versioned_rows.py
+++ b/examples/versioned_rows/versioned_rows.py
@@ -3,8 +3,13 @@ an UPDATE statement on a single row into an INSERT statement, so that a new
row is inserted with the new data, keeping the old row intact.
"""
-from sqlalchemy.orm import sessionmaker, relationship, make_transient, \
- backref, Session
+from sqlalchemy.orm import (
+ sessionmaker,
+ relationship,
+ make_transient,
+ backref,
+ Session,
+)
from sqlalchemy import Column, ForeignKey, create_engine, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import attributes
@@ -38,9 +43,10 @@ def before_flush(session, flush_context, instances):
# re-add
session.add(instance)
+
Base = declarative_base()
-engine = create_engine('sqlite://', echo=True)
+engine = create_engine("sqlite://", echo=True)
Session = sessionmaker(engine)
@@ -48,43 +54,44 @@ Session = sessionmaker(engine)
class Example(Versioned, Base):
- __tablename__ = 'example'
+ __tablename__ = "example"
id = Column(Integer, primary_key=True)
data = Column(String)
+
Base.metadata.create_all(engine)
session = Session()
-e1 = Example(data='e1')
+e1 = Example(data="e1")
session.add(e1)
session.commit()
-e1.data = 'e2'
+e1.data = "e2"
session.commit()
assert session.query(Example.id, Example.data).order_by(Example.id).all() == (
- [(1, 'e1'), (2, 'e2')]
+ [(1, "e1"), (2, "e2")]
)
# example 2, versioning with a parent
class Parent(Base):
- __tablename__ = 'parent'
+ __tablename__ = "parent"
id = Column(Integer, primary_key=True)
- child_id = Column(Integer, ForeignKey('child.id'))
- child = relationship("Child", backref=backref('parent', uselist=False))
+ child_id = Column(Integer, ForeignKey("child.id"))
+ child = relationship("Child", backref=backref("parent", uselist=False))
class Child(Versioned, Base):
- __tablename__ = 'child'
+ __tablename__ = "child"
id = Column(Integer, primary_key=True)
data = Column(String)
def new_version(self, session):
# expire parent's reference to us
- session.expire(self.parent, ['child'])
+ session.expire(self.parent, ["child"])
# create new version
Versioned.new_version(self, session)
@@ -92,18 +99,19 @@ class Child(Versioned, Base):
# re-add ourselves to the parent
self.parent.child = self
+
Base.metadata.create_all(engine)
session = Session()
-p1 = Parent(child=Child(data='c1'))
+p1 = Parent(child=Child(data="c1"))
session.add(p1)
session.commit()
-p1.child.data = 'c2'
+p1.child.data = "c2"
session.commit()
assert p1.child_id == 2
assert session.query(Child.id, Child.data).order_by(Child.id).all() == (
- [(1, 'c1'), (2, 'c2')]
+ [(1, "c1"), (2, "c2")]
)
diff --git a/examples/versioned_rows/versioned_rows_w_versionid.py b/examples/versioned_rows/versioned_rows_w_versionid.py
index 8445401c5..5fd6f9fc4 100644
--- a/examples/versioned_rows/versioned_rows_w_versionid.py
+++ b/examples/versioned_rows/versioned_rows_w_versionid.py
@@ -6,10 +6,24 @@ This example adds a numerical version_id to the Versioned class as well
as the ability to see which row is the most "current" vesion.
"""
-from sqlalchemy.orm import sessionmaker, relationship, make_transient, \
- backref, Session, column_property
-from sqlalchemy import Column, ForeignKeyConstraint, create_engine, \
- Integer, String, Boolean, select, func
+from sqlalchemy.orm import (
+ sessionmaker,
+ relationship,
+ make_transient,
+ backref,
+ Session,
+ column_property,
+)
+from sqlalchemy import (
+ Column,
+ ForeignKeyConstraint,
+ create_engine,
+ Integer,
+ String,
+ Boolean,
+ select,
+ func,
+)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import attributes
from sqlalchemy import event
@@ -38,7 +52,8 @@ class Versioned(object):
# optional - set previous version to have is_current_version=False
old_id = self.id
session.query(self.__class__).filter_by(id=old_id).update(
- values=dict(is_current_version=False), synchronize_session=False)
+ values=dict(is_current_version=False), synchronize_session=False
+ )
# make us transient (removes persistent
# identity).
@@ -65,9 +80,10 @@ def before_flush(session, flush_context, instances):
# re-add
session.add(instance)
+
Base = declarative_base()
-engine = create_engine('sqlite://', echo=True)
+engine = create_engine("sqlite://", echo=True)
Session = sessionmaker(engine)
@@ -75,17 +91,18 @@ Session = sessionmaker(engine)
class Example(Versioned, Base):
- __tablename__ = 'example'
+ __tablename__ = "example"
data = Column(String)
+
Base.metadata.create_all(engine)
session = Session()
-e1 = Example(id=1, data='e1')
+e1 = Example(id=1, data="e1")
session.add(e1)
session.commit()
-e1.data = 'e2'
+e1.data = "e2"
session.commit()
assert session.query(
@@ -93,36 +110,36 @@ assert session.query(
Example.version_id,
Example.is_current_version,
Example.calc_is_current_version,
- Example.data).order_by(Example.id, Example.version_id).all() == (
- [(1, 1, False, False, 'e1'), (1, 2, True, True, 'e2')]
+ Example.data,
+).order_by(Example.id, Example.version_id).all() == (
+ [(1, 1, False, False, "e1"), (1, 2, True, True, "e2")]
)
# example 2, versioning with a parent
class Parent(Base):
- __tablename__ = 'parent'
+ __tablename__ = "parent"
id = Column(Integer, primary_key=True)
child_id = Column(Integer)
child_version_id = Column(Integer)
- child = relationship("Child", backref=backref('parent', uselist=False))
+ child = relationship("Child", backref=backref("parent", uselist=False))
__table_args__ = (
ForeignKeyConstraint(
- ['child_id', 'child_version_id'],
- ['child.id', 'child.version_id'],
+ ["child_id", "child_version_id"], ["child.id", "child.version_id"]
),
)
class Child(Versioned, Base):
- __tablename__ = 'child'
+ __tablename__ = "child"
data = Column(String)
def new_version(self, session):
# expire parent's reference to us
- session.expire(self.parent, ['child'])
+ session.expire(self.parent, ["child"])
# create new version
Versioned.new_version(self, session)
@@ -131,15 +148,16 @@ class Child(Versioned, Base):
# parent foreign key to be updated also
self.parent.child = self
+
Base.metadata.create_all(engine)
session = Session()
-p1 = Parent(child=Child(id=1, data='c1'))
+p1 = Parent(child=Child(id=1, data="c1"))
session.add(p1)
session.commit()
-p1.child.data = 'c2'
+p1.child.data = "c2"
session.commit()
assert p1.child_id == 1
@@ -150,6 +168,7 @@ assert session.query(
Child.version_id,
Child.is_current_version,
Child.calc_is_current_version,
- Child.data).order_by(Child.id, Child.version_id).all() == (
- [(1, 1, False, False, 'c1'), (1, 2, True, True, 'c2')]
+ Child.data,
+).order_by(Child.id, Child.version_id).all() == (
+ [(1, 1, False, False, "c1"), (1, 2, True, True, "c2")]
)
diff --git a/examples/versioned_rows/versioned_update_old_row.py b/examples/versioned_rows/versioned_update_old_row.py
index 0159d2567..17c82fdc3 100644
--- a/examples/versioned_rows/versioned_update_old_row.py
+++ b/examples/versioned_rows/versioned_update_old_row.py
@@ -6,12 +6,23 @@ to only the most recent version.
"""
from sqlalchemy import (
- create_engine, Integer, String, event, Column, DateTime,
- inspect, literal
+ create_engine,
+ Integer,
+ String,
+ event,
+ Column,
+ DateTime,
+ inspect,
+ literal,
)
from sqlalchemy.orm import (
- make_transient, Session, relationship, attributes, backref,
- make_transient_to_detached, Query
+ make_transient,
+ Session,
+ relationship,
+ attributes,
+ backref,
+ make_transient_to_detached,
+ Query,
)
from sqlalchemy.ext.declarative import declarative_base
import datetime
@@ -50,7 +61,8 @@ class VersionedStartEnd(object):
# make the "old" version of us, which we will turn into an
# UPDATE
old_copy_of_us = self.__class__(
- id=self.id, start=self.start, end=self.end)
+ id=self.id, start=self.start, end=self.end
+ )
# turn old_copy_of_us into an UPDATE
make_transient_to_detached(old_copy_of_us)
@@ -95,11 +107,11 @@ def before_compile(query):
"""ensure all queries for VersionedStartEnd include criteria """
for ent in query.column_descriptions:
- entity = ent['entity']
+ entity = ent["entity"]
if entity is None:
continue
- insp = inspect(ent['entity'])
- mapper = getattr(insp, 'mapper', None)
+ insp = inspect(ent["entity"])
+ mapper = getattr(insp, "mapper", None)
if mapper and issubclass(mapper.class_, VersionedStartEnd):
query = query.enable_assertions(False).filter(
# using a literal "now" because SQLite's "between"
@@ -107,14 +119,14 @@ def before_compile(query):
# ``func.now()`` and we'd be using PostgreSQL
literal(
current_time() + datetime.timedelta(seconds=1)
- ).between(ent['entity'].start, ent['entity'].end)
+ ).between(ent["entity"].start, ent["entity"].end)
)
return query
class Parent(VersionedStartEnd, Base):
- __tablename__ = 'parent'
+ __tablename__ = "parent"
id = Column(Integer, primary_key=True)
start = Column(DateTime, primary_key=True)
end = Column(DateTime, primary_key=True)
@@ -124,10 +136,7 @@ class Parent(VersionedStartEnd, Base):
child = relationship(
"Child",
- primaryjoin=(
- "Child.id == foreign(Parent.child_n)"
- ),
-
+ primaryjoin=("Child.id == foreign(Parent.child_n)"),
# note the primaryjoin can also be:
#
# "and_(Child.id == foreign(Parent.child_n), "
@@ -138,14 +147,13 @@ class Parent(VersionedStartEnd, Base):
# as well, it just means the criteria will be present twice for most
# parent->child load operations
#
-
uselist=False,
- backref=backref('parent', uselist=False)
+ backref=backref("parent", uselist=False),
)
class Child(VersionedStartEnd, Base):
- __tablename__ = 'child'
+ __tablename__ = "child"
id = Column(Integer, primary_key=True)
start = Column(DateTime, primary_key=True)
@@ -155,7 +163,7 @@ class Child(VersionedStartEnd, Base):
def new_version(self, session):
# expire parent's reference to us
- session.expire(self.parent, ['child'])
+ session.expire(self.parent, ["child"])
# create new version
VersionedStartEnd.new_version(self, session)
@@ -163,6 +171,7 @@ class Child(VersionedStartEnd, Base):
# re-add ourselves to the parent
self.parent.child = self
+
times = []
@@ -185,27 +194,37 @@ def time_passes(s):
assert times[-1] > times[-2]
return times[-1]
-e = create_engine("sqlite://", echo='debug')
+
+e = create_engine("sqlite://", echo="debug")
Base.metadata.create_all(e)
s = Session(e)
now = time_passes(s)
-c1 = Child(id=1, data='child 1')
-p1 = Parent(id=1, data='c1', child=c1)
+c1 = Child(id=1, data="child 1")
+p1 = Parent(id=1, data="c1", child=c1)
s.add(p1)
s.commit()
# assert raw DB data
assert s.query(Parent.__table__).all() == [
- (1, times[0] - datetime.timedelta(days=3),
- times[0] + datetime.timedelta(days=3), 'c1', 1)
+ (
+ 1,
+ times[0] - datetime.timedelta(days=3),
+ times[0] + datetime.timedelta(days=3),
+ "c1",
+ 1,
+ )
]
assert s.query(Child.__table__).all() == [
- (1, times[0] - datetime.timedelta(days=3),
- times[0] + datetime.timedelta(days=3), 'child 1')
+ (
+ 1,
+ times[0] - datetime.timedelta(days=3),
+ times[0] + datetime.timedelta(days=3),
+ "child 1",
+ )
]
now = time_passes(s)
@@ -214,7 +233,7 @@ p1_check = s.query(Parent).first()
assert p1_check is p1
assert p1_check.child is c1
-p1.child.data = 'elvis presley'
+p1.child.data = "elvis presley"
s.commit()
@@ -226,40 +245,51 @@ c2_check = p2_check.child
assert p2_check.child is c1
# new data
-assert c1.data == 'elvis presley'
+assert c1.data == "elvis presley"
# new end time
assert c1.end == now + datetime.timedelta(days=2)
# assert raw DB data
assert s.query(Parent.__table__).all() == [
- (1, times[0] - datetime.timedelta(days=3),
- times[0] + datetime.timedelta(days=3), 'c1', 1)
+ (
+ 1,
+ times[0] - datetime.timedelta(days=3),
+ times[0] + datetime.timedelta(days=3),
+ "c1",
+ 1,
+ )
]
assert s.query(Child.__table__).order_by(Child.end).all() == [
- (1, times[0] - datetime.timedelta(days=3), times[1], 'child 1'),
- (1, times[1], times[1] + datetime.timedelta(days=2), 'elvis presley')
+ (1, times[0] - datetime.timedelta(days=3), times[1], "child 1"),
+ (1, times[1], times[1] + datetime.timedelta(days=2), "elvis presley"),
]
now = time_passes(s)
-p1.data = 'c2 elvis presley'
+p1.data = "c2 elvis presley"
s.commit()
# assert raw DB data. now there are two parent rows.
assert s.query(Parent.__table__).order_by(Parent.end).all() == [
- (1, times[0] - datetime.timedelta(days=3), times[2], 'c1', 1),
- (1, times[2], times[2] + datetime.timedelta(days=2), 'c2 elvis presley', 1)
+ (1, times[0] - datetime.timedelta(days=3), times[2], "c1", 1),
+ (
+ 1,
+ times[2],
+ times[2] + datetime.timedelta(days=2),
+ "c2 elvis presley",
+ 1,
+ ),
]
assert s.query(Child.__table__).order_by(Child.end).all() == [
- (1, times[0] - datetime.timedelta(days=3), times[1], 'child 1'),
- (1, times[1], times[1] + datetime.timedelta(days=2), 'elvis presley')
+ (1, times[0] - datetime.timedelta(days=3), times[1], "child 1"),
+ (1, times[1], times[1] + datetime.timedelta(days=2), "elvis presley"),
]
# add some more rows to test that these aren't coming back for
# queries
-s.add(Parent(id=2, data='unrelated', child=Child(id=2, data='unrelated')))
+s.add(Parent(id=2, data="unrelated", child=Child(id=2, data="unrelated")))
s.commit()
@@ -274,6 +304,6 @@ c3_check = s.query(Child).filter(Child.parent == p3_check).one()
assert c3_check is c1
# one child one parent....
-c3_check = s.query(Child).join(Parent.child).filter(
- Parent.id == p3_check.id).one()
-
+c3_check = (
+ s.query(Child).join(Parent.child).filter(Parent.id == p3_check.id).one()
+)
diff --git a/examples/vertical/__init__.py b/examples/vertical/__init__.py
index 0b69f32ea..0e09b9a55 100644
--- a/examples/vertical/__init__.py
+++ b/examples/vertical/__init__.py
@@ -31,4 +31,4 @@ Example::
.. autosource::
-""" \ No newline at end of file
+"""
diff --git a/examples/vertical/dictlike-polymorphic.py b/examples/vertical/dictlike-polymorphic.py
index 7147ac40b..c000ff3cf 100644
--- a/examples/vertical/dictlike-polymorphic.py
+++ b/examples/vertical/dictlike-polymorphic.py
@@ -30,6 +30,7 @@ from sqlalchemy import event
from sqlalchemy import literal_column
from .dictlike import ProxiedDictMixin
+
class PolymorphicVerticalProperty(object):
"""A key/value pair with polymorphic value storage.
@@ -69,6 +70,7 @@ class PolymorphicVerticalProperty(object):
"""A comparator for .value, builds a polymorphic comparison via CASE.
"""
+
def __init__(self, cls):
self.cls = cls
@@ -77,40 +79,59 @@ class PolymorphicVerticalProperty(object):
whens = [
(
literal_column("'%s'" % discriminator),
- cast(getattr(self.cls, attribute), String)
- ) for attribute, discriminator in pairs
+ cast(getattr(self.cls, attribute), String),
+ )
+ for attribute, discriminator in pairs
if attribute is not None
]
return case(whens, self.cls.type, null())
+
def __eq__(self, other):
return self._case() == cast(other, String)
+
def __ne__(self, other):
return self._case() != cast(other, String)
def __repr__(self):
- return '<%s %r=%r>' % (self.__class__.__name__, self.key, self.value)
+ return "<%s %r=%r>" % (self.__class__.__name__, self.key, self.value)
+
-@event.listens_for(PolymorphicVerticalProperty, "mapper_configured", propagate=True)
+@event.listens_for(
+ PolymorphicVerticalProperty, "mapper_configured", propagate=True
+)
def on_new_class(mapper, cls_):
"""Look for Column objects with type info in them, and work up
a lookup table."""
info_dict = {}
- info_dict[type(None)] = (None, 'none')
- info_dict['none'] = (None, 'none')
+ info_dict[type(None)] = (None, "none")
+ info_dict["none"] = (None, "none")
for k in mapper.c.keys():
col = mapper.c[k]
- if 'type' in col.info:
- python_type, discriminator = col.info['type']
+ if "type" in col.info:
+ python_type, discriminator = col.info["type"]
info_dict[python_type] = (k, discriminator)
info_dict[discriminator] = (k, discriminator)
cls_.type_map = info_dict
-if __name__ == '__main__':
- from sqlalchemy import (Column, Integer, Unicode,
- ForeignKey, UnicodeText, and_, or_, String, Boolean, cast,
- null, case, create_engine)
+
+if __name__ == "__main__":
+ from sqlalchemy import (
+ Column,
+ Integer,
+ Unicode,
+ ForeignKey,
+ UnicodeText,
+ and_,
+ or_,
+ String,
+ Boolean,
+ cast,
+ null,
+ case,
+ create_engine,
+ )
from sqlalchemy.orm import relationship, Session
from sqlalchemy.orm.collections import attribute_mapped_collection
from sqlalchemy.ext.declarative import declarative_base
@@ -118,36 +139,38 @@ if __name__ == '__main__':
Base = declarative_base()
-
class AnimalFact(PolymorphicVerticalProperty, Base):
"""A fact about an animal."""
- __tablename__ = 'animal_fact'
+ __tablename__ = "animal_fact"
- animal_id = Column(ForeignKey('animal.id'), primary_key=True)
+ animal_id = Column(ForeignKey("animal.id"), primary_key=True)
key = Column(Unicode(64), primary_key=True)
type = Column(Unicode(16))
# add information about storage for different types
# in the info dictionary of Columns
- int_value = Column(Integer, info={'type': (int, 'integer')})
- char_value = Column(UnicodeText, info={'type': (str, 'string')})
- boolean_value = Column(Boolean, info={'type': (bool, 'boolean')})
+ int_value = Column(Integer, info={"type": (int, "integer")})
+ char_value = Column(UnicodeText, info={"type": (str, "string")})
+ boolean_value = Column(Boolean, info={"type": (bool, "boolean")})
class Animal(ProxiedDictMixin, Base):
"""an Animal"""
- __tablename__ = 'animal'
+ __tablename__ = "animal"
id = Column(Integer, primary_key=True)
name = Column(Unicode(100))
- facts = relationship("AnimalFact",
- collection_class=attribute_mapped_collection('key'))
+ facts = relationship(
+ "AnimalFact", collection_class=attribute_mapped_collection("key")
+ )
- _proxied = association_proxy("facts", "value",
- creator=
- lambda key, value: AnimalFact(key=key, value=value))
+ _proxied = association_proxy(
+ "facts",
+ "value",
+ creator=lambda key, value: AnimalFact(key=key, value=value),
+ )
def __init__(self, name):
self.name = name
@@ -159,66 +182,66 @@ if __name__ == '__main__':
def with_characteristic(self, key, value):
return self.facts.any(key=key, value=value)
- engine = create_engine('sqlite://', echo=True)
+ engine = create_engine("sqlite://", echo=True)
Base.metadata.create_all(engine)
session = Session(engine)
- stoat = Animal('stoat')
- stoat['color'] = 'red'
- stoat['cuteness'] = 7
- stoat['weasel-like'] = True
+ stoat = Animal("stoat")
+ stoat["color"] = "red"
+ stoat["cuteness"] = 7
+ stoat["weasel-like"] = True
session.add(stoat)
session.commit()
- critter = session.query(Animal).filter(Animal.name == 'stoat').one()
- print(critter['color'])
- print(critter['cuteness'])
+ critter = session.query(Animal).filter(Animal.name == "stoat").one()
+ print(critter["color"])
+ print(critter["cuteness"])
print("changing cuteness value and type:")
- critter['cuteness'] = 'very cute'
+ critter["cuteness"] = "very cute"
session.commit()
- marten = Animal('marten')
- marten['cuteness'] = 5
- marten['weasel-like'] = True
- marten['poisonous'] = False
+ marten = Animal("marten")
+ marten["cuteness"] = 5
+ marten["weasel-like"] = True
+ marten["poisonous"] = False
session.add(marten)
- shrew = Animal('shrew')
- shrew['cuteness'] = 5
- shrew['weasel-like'] = False
- shrew['poisonous'] = True
+ shrew = Animal("shrew")
+ shrew["cuteness"] = 5
+ shrew["weasel-like"] = False
+ shrew["poisonous"] = True
session.add(shrew)
session.commit()
- q = (session.query(Animal).
- filter(Animal.facts.any(
- and_(AnimalFact.key == 'weasel-like',
- AnimalFact.value == True))))
- print('weasel-like animals', q.all())
-
- q = (session.query(Animal).
- filter(Animal.with_characteristic('weasel-like', True)))
- print('weasel-like animals again', q.all())
-
- q = (session.query(Animal).
- filter(Animal.with_characteristic('poisonous', False)))
- print('animals with poisonous=False', q.all())
-
- q = (session.query(Animal).
- filter(or_(
- Animal.with_characteristic('poisonous', False),
- ~Animal.facts.any(AnimalFact.key == 'poisonous')
- )
- )
+ q = session.query(Animal).filter(
+ Animal.facts.any(
+ and_(AnimalFact.key == "weasel-like", AnimalFact.value == True)
)
- print('non-poisonous animals', q.all())
-
- q = (session.query(Animal).
- filter(Animal.facts.any(AnimalFact.value == 5)))
- print('any animal with a .value of 5', q.all())
+ )
+ print("weasel-like animals", q.all())
+
+ q = session.query(Animal).filter(
+ Animal.with_characteristic("weasel-like", True)
+ )
+ print("weasel-like animals again", q.all())
+
+ q = session.query(Animal).filter(
+ Animal.with_characteristic("poisonous", False)
+ )
+ print("animals with poisonous=False", q.all())
+
+ q = session.query(Animal).filter(
+ or_(
+ Animal.with_characteristic("poisonous", False),
+ ~Animal.facts.any(AnimalFact.key == "poisonous"),
+ )
+ )
+ print("non-poisonous animals", q.all())
+ q = session.query(Animal).filter(Animal.facts.any(AnimalFact.value == 5))
+ print("any animal with a .value of 5", q.all())
diff --git a/examples/vertical/dictlike.py b/examples/vertical/dictlike.py
index 08989d8c2..f1f364207 100644
--- a/examples/vertical/dictlike.py
+++ b/examples/vertical/dictlike.py
@@ -32,6 +32,7 @@ can be used with many common vertical schemas as-is or with minor adaptations.
"""
from __future__ import unicode_literals
+
class ProxiedDictMixin(object):
"""Adds obj[key] access to a mapped class.
@@ -60,9 +61,16 @@ class ProxiedDictMixin(object):
del self._proxied[key]
-if __name__ == '__main__':
- from sqlalchemy import (Column, Integer, Unicode,
- ForeignKey, UnicodeText, and_, create_engine)
+if __name__ == "__main__":
+ from sqlalchemy import (
+ Column,
+ Integer,
+ Unicode,
+ ForeignKey,
+ UnicodeText,
+ and_,
+ create_engine,
+ )
from sqlalchemy.orm import relationship, Session
from sqlalchemy.orm.collections import attribute_mapped_collection
from sqlalchemy.ext.declarative import declarative_base
@@ -73,26 +81,29 @@ if __name__ == '__main__':
class AnimalFact(Base):
"""A fact about an animal."""
- __tablename__ = 'animal_fact'
+ __tablename__ = "animal_fact"
- animal_id = Column(ForeignKey('animal.id'), primary_key=True)
+ animal_id = Column(ForeignKey("animal.id"), primary_key=True)
key = Column(Unicode(64), primary_key=True)
value = Column(UnicodeText)
class Animal(ProxiedDictMixin, Base):
"""an Animal"""
- __tablename__ = 'animal'
+ __tablename__ = "animal"
id = Column(Integer, primary_key=True)
name = Column(Unicode(100))
- facts = relationship("AnimalFact",
- collection_class=attribute_mapped_collection('key'))
+ facts = relationship(
+ "AnimalFact", collection_class=attribute_mapped_collection("key")
+ )
- _proxied = association_proxy("facts", "value",
- creator=
- lambda key, value: AnimalFact(key=key, value=value))
+ _proxied = association_proxy(
+ "facts",
+ "value",
+ creator=lambda key, value: AnimalFact(key=key, value=value),
+ )
def __init__(self, name):
self.name = name
@@ -109,57 +120,56 @@ if __name__ == '__main__':
session = Session(bind=engine)
- stoat = Animal('stoat')
- stoat['color'] = 'reddish'
- stoat['cuteness'] = 'somewhat'
+ stoat = Animal("stoat")
+ stoat["color"] = "reddish"
+ stoat["cuteness"] = "somewhat"
# dict-like assignment transparently creates entries in the
# stoat.facts collection:
- print(stoat.facts['color'])
+ print(stoat.facts["color"])
session.add(stoat)
session.commit()
- critter = session.query(Animal).filter(Animal.name == 'stoat').one()
- print(critter['color'])
- print(critter['cuteness'])
+ critter = session.query(Animal).filter(Animal.name == "stoat").one()
+ print(critter["color"])
+ print(critter["cuteness"])
- critter['cuteness'] = 'very'
+ critter["cuteness"] = "very"
- print('changing cuteness:')
+ print("changing cuteness:")
- marten = Animal('marten')
- marten['color'] = 'brown'
- marten['cuteness'] = 'somewhat'
+ marten = Animal("marten")
+ marten["color"] = "brown"
+ marten["cuteness"] = "somewhat"
session.add(marten)
- shrew = Animal('shrew')
- shrew['cuteness'] = 'somewhat'
- shrew['poisonous-part'] = 'saliva'
+ shrew = Animal("shrew")
+ shrew["cuteness"] = "somewhat"
+ shrew["poisonous-part"] = "saliva"
session.add(shrew)
- loris = Animal('slow loris')
- loris['cuteness'] = 'fairly'
- loris['poisonous-part'] = 'elbows'
+ loris = Animal("slow loris")
+ loris["cuteness"] = "fairly"
+ loris["poisonous-part"] = "elbows"
session.add(loris)
- q = (session.query(Animal).
- filter(Animal.facts.any(
- and_(AnimalFact.key == 'color',
- AnimalFact.value == 'reddish'))))
- print('reddish animals', q.all())
+ q = session.query(Animal).filter(
+ Animal.facts.any(
+ and_(AnimalFact.key == "color", AnimalFact.value == "reddish")
+ )
+ )
+ print("reddish animals", q.all())
- q = session.query(Animal).\
- filter(Animal.with_characteristic("color", 'brown'))
- print('brown animals', q.all())
+ q = session.query(Animal).filter(
+ Animal.with_characteristic("color", "brown")
+ )
+ print("brown animals", q.all())
- q = session.query(Animal).\
- filter(~Animal.with_characteristic("poisonous-part", 'elbows'))
- print('animals without poisonous-part == elbows', q.all())
+ q = session.query(Animal).filter(
+ ~Animal.with_characteristic("poisonous-part", "elbows")
+ )
+ print("animals without poisonous-part == elbows", q.all())
- q = (session.query(Animal).
- filter(Animal.facts.any(value='somewhat')))
+ q = session.query(Animal).filter(Animal.facts.any(value="somewhat"))
print('any animal with any .value of "somewhat"', q.all())
-
-
-