summaryrefslogtreecommitdiff
path: root/examples/elementtree
diff options
context:
space:
mode:
Diffstat (limited to 'examples/elementtree')
-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
4 files changed, 225 insertions, 106 deletions
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)
-