summaryrefslogtreecommitdiff
path: root/examples/postgis/postgis.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2011-01-02 14:23:42 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2011-01-02 14:23:42 -0500
commit350aed3fdb9f1e73e69655e53f44ca6a91c196da (patch)
tree3d2a128667b5f6ca6d0b4e1f4865fc98aac6b60b /examples/postgis/postgis.py
parent71f92436bdc86f30e2c21d8f5244733601e8c39e (diff)
downloadsqlalchemy-350aed3fdb9f1e73e69655e53f44ca6a91c196da.tar.gz
- whitespace removal bonanza
Diffstat (limited to 'examples/postgis/postgis.py')
-rw-r--r--examples/postgis/postgis.py90
1 files changed, 45 insertions, 45 deletions
diff --git a/examples/postgis/postgis.py b/examples/postgis/postgis.py
index d3f728293..68f5ecae9 100644
--- a/examples/postgis/postgis.py
+++ b/examples/postgis/postgis.py
@@ -24,18 +24,18 @@ class GisElement(object):
class PersistentGisElement(GisElement):
"""Represents a Geometry value as loaded from the database."""
-
+
def __init__(self, desc):
self.desc = desc
class TextualGisElement(GisElement, expression.Function):
"""Represents a Geometry value as expressed within application code; i.e. in wkt format.
-
+
Extends expression.Function so that the value is interpreted as
GeomFromText(value) in a SQL expression context.
-
+
"""
-
+
def __init__(self, desc, srid=-1):
assert isinstance(desc, basestring)
self.desc = desc
@@ -46,17 +46,17 @@ class TextualGisElement(GisElement, expression.Function):
class Geometry(TypeEngine):
"""Base PostGIS Geometry column type.
-
+
Converts bind/result values to/from a PersistentGisElement.
-
+
"""
-
+
name = 'GEOMETRY'
-
+
def __init__(self, dimension=None, srid=-1):
self.dimension = dimension
self.srid = srid
-
+
def bind_processor(self, dialect):
def process(value):
if value is not None:
@@ -64,7 +64,7 @@ class Geometry(TypeEngine):
else:
return value
return process
-
+
def result_processor(self, dialect, coltype):
def process(value):
if value is not None:
@@ -78,10 +78,10 @@ class Geometry(TypeEngine):
class Point(Geometry):
name = 'POINT'
-
+
class Curve(Geometry):
name = 'CURVE'
-
+
class LineString(Curve):
name = 'LINESTRING'
@@ -93,36 +93,36 @@ class LineString(Curve):
class GISDDL(object):
"""A DDL extension which integrates SQLAlchemy table create/drop
methods with PostGis' AddGeometryColumn/DropGeometryColumn functions.
-
+
Usage::
-
+
sometable = Table('sometable', metadata, ...)
-
+
GISDDL(sometable)
sometable.create()
-
+
"""
-
+
def __init__(self, table):
for event in ('before-create', 'after-create', 'before-drop', 'after-drop'):
table.ddl_listeners[event].append(self)
self._stack = []
-
+
def __call__(self, event, table, bind):
if event in ('before-create', 'before-drop'):
regular_cols = [c for c in table.c if not isinstance(c.type, Geometry)]
gis_cols = set(table.c).difference(regular_cols)
self._stack.append(table.c)
table._columns = expression.ColumnCollection(*regular_cols)
-
+
if event == 'before-drop':
for c in gis_cols:
bind.execute(select([func.DropGeometryColumn('public', table.name, c.name)], autocommit=True))
-
+
elif event == 'after-create':
table._columns = self._stack.pop()
-
+
for c in table.c:
if isinstance(c.type, Geometry):
bind.execute(select([func.AddGeometryColumn(table.name, c.name, c.type.srid, c.type.name, c.type.dimension)], autocommit=True))
@@ -133,7 +133,7 @@ class GISDDL(object):
def _to_postgis(value):
"""Interpret a value as a GIS-compatible construct."""
-
+
if hasattr(value, '__clause_element__'):
return value.__clause_element__()
elif isinstance(value, (expression.ClauseElement, GisElement)):
@@ -149,18 +149,18 @@ def _to_postgis(value):
class GisAttribute(AttributeExtension):
"""Intercepts 'set' events on a mapped instance attribute and
converts the incoming value to a GIS expression.
-
+
"""
-
+
def set(self, state, value, oldvalue, initiator):
return _to_postgis(value)
-
+
class GisComparator(ColumnProperty.ColumnComparator):
"""Intercepts standard Column operators on mapped class attributes
and overrides their behavior.
-
+
"""
-
+
# override the __eq__() operator
def __eq__(self, other):
return self.__clause_element__().op('~=')(_to_postgis(other))
@@ -168,19 +168,19 @@ class GisComparator(ColumnProperty.ColumnComparator):
# add a custom operator
def intersects(self, other):
return self.__clause_element__().op('&&')(_to_postgis(other))
-
+
# any number of GIS operators can be overridden/added here
# using the techniques above.
-
+
def GISColumn(*args, **kw):
"""Define a declarative column property with GIS behavior.
-
+
This just produces orm.column_property() with the appropriate
extension and comparator_factory arguments. The given arguments
are passed through to Column. The declarative module extracts
the Column for inclusion in the mapped table.
-
+
"""
return column_property(
Column(*args, **kw),
@@ -201,21 +201,21 @@ if __name__ == '__main__':
class Road(Base):
__tablename__ = 'roads'
-
+
road_id = Column(Integer, primary_key=True)
road_name = Column(String)
road_geom = GISColumn(Geometry(2))
-
+
# enable the DDL extension, which allows CREATE/DROP operations
# to work correctly. This is not needed if working with externally
- # defined tables.
+ # defined tables.
GISDDL(Road.__table__)
metadata.drop_all()
metadata.create_all()
session = sessionmaker(bind=engine)()
-
+
# Add objects. We can use strings...
session.add_all([
Road(road_name='Jeff Rd', road_geom='LINESTRING(191232 243118,191108 243242)'),
@@ -224,30 +224,30 @@ if __name__ == '__main__':
Road(road_name='Graeme Ave', road_geom='LINESTRING(189412 252431,189631 259122)'),
Road(road_name='Phil Tce', road_geom='LINESTRING(190131 224148,190871 228134)'),
])
-
+
# or use an explicit TextualGisElement (similar to saying func.GeomFromText())
r = Road(road_name='Dave Cres', road_geom=TextualGisElement('LINESTRING(198231 263418,198213 268322)', -1))
session.add(r)
-
+
# pre flush, the TextualGisElement represents the string we sent.
assert str(r.road_geom) == 'LINESTRING(198231 263418,198213 268322)'
assert session.scalar(r.road_geom.wkt) == 'LINESTRING(198231 263418,198213 268322)'
-
+
session.commit()
# after flush and/or commit, all the TextualGisElements become PersistentGisElements.
assert str(r.road_geom) == "01020000000200000000000000B832084100000000E813104100000000283208410000000088601041"
-
+
r1 = session.query(Road).filter(Road.road_name=='Graeme Ave').one()
-
+
# illustrate the overridden __eq__() operator.
-
+
# strings come in as TextualGisElements
r2 = session.query(Road).filter(Road.road_geom == 'LINESTRING(189412 252431,189631 259122)').one()
-
+
# PersistentGisElements work directly
r3 = session.query(Road).filter(Road.road_geom == r1.road_geom).one()
-
+
assert r1 is r2 is r3
# illustrate the "intersects" operator
@@ -256,7 +256,7 @@ if __name__ == '__main__':
# illustrate usage of the "wkt" accessor. this requires a DB
# execution to call the AsText() function so we keep this explicit.
assert session.scalar(r1.road_geom.wkt) == 'LINESTRING(189412 252431,189631 259122)'
-
+
session.rollback()
-
+
metadata.drop_all()