diff --git a/.travis.yml b/.travis.yml index 655c197..88fc6ed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: python - +sudo: required python: - "2.7" @@ -7,6 +7,7 @@ services: - postgres - mysql addons: +# mariadb: '10.1' apt: packages: - cmake @@ -30,6 +31,14 @@ env: - DB=mysql install: +# - echo "[mysqld]" > $HOME/.my.cnf +# - echo "storage_engine = MyISAM" >> $HOME/.my.cnf +# - echo "default_storage_engine = MyISAM" >> $HOME/.my.cnf + - sudo sed -i '/\[mysqld\]/a default_storage_engine = MyISAM ' /etc/mysql/my.cnf + - sudo sed -i '/\[mysqld\]/a lower_case_table_names = 1 ' /etc/mysql/my.cnf +# - sudo sed -i '/\[mysqld\]/a storage_engine = MyISAM ' /etc/mysql/my.cnf + - cat /etc/mysql/my.cnf + - sudo service mysql restart # install GeoAlchemy in editable mode - pip install -e . @@ -38,8 +47,8 @@ install: # install individual dependencies - if [[ "$DB" == "postgres" ]]; then pip install psycopg2; fi - - if [[ "$DB" == "mysql" ]]; then pip install MySQL-python; fi - +# - if [[ "$DB" == "mysql" ]]; then pip install MySQL-python; fi + - if [[ "$DB" == "mysql" ]]; then pip install pymysql; fi # install PostGIS 2.x - if [[ "$DB" == "postgres" ]] && [[ "$POSTGIS_VERSION" != "1.5" ]]; then sudo apt-add-repository -y ppa:sharpie/for-science; fi - if [[ "$DB" == "postgres" ]] && [[ "$POSTGIS_VERSION" != "1.5" ]]; then sudo apt-add-repository -y ppa:sharpie/postgis-nightly; fi diff --git a/geoalchemy/base.py b/geoalchemy/base.py index 00885fa..ae2b5d0 100644 --- a/geoalchemy/base.py +++ b/geoalchemy/base.py @@ -1,6 +1,10 @@ from sqlalchemy.orm.properties import ColumnProperty from sqlalchemy.sql import expression, not_ from sqlalchemy.sql.expression import ColumnClause, literal +try: + from sqlalchemy.sql.functions import Function +except ImportError: + from sqlalchemy.sql.expression import Function # sqlalchemy < 0.9 from sqlalchemy.types import UserDefinedType from sqlalchemy.ext.compiler import compiles @@ -21,7 +25,11 @@ def __repr__(self): return "<%s at 0x%x; %r>" % (self.__class__.__name__, id(self), self.desc) def __getattr__(self, name): - return getattr(functions, name)(self) + attr = getattr(functions, name) + if callable(attr): + return attr(self) + else: + return attr # def __get_wkt(self, session): """This method converts the object into a WKT geometry. It takes into @@ -45,7 +53,7 @@ def coords(self, session): wkt = self.__get_wkt(session) return from_wkt(wkt)["coordinates"] -class WKTSpatialElement(SpatialElement, expression.Function): +class WKTSpatialElement(SpatialElement, Function): """Represents a Geometry value expressed within application code; i.e. in the OGC Well Known Text (WKT) format. @@ -61,7 +69,7 @@ def __init__(self, desc, srid=4326, geometry_type='GEOMETRY'): self.srid = srid self.geometry_type = geometry_type - expression.Function.__init__(self, "") + Function.__init__(self, "") @property def geom_wkt(self): @@ -74,7 +82,7 @@ def __compile_wktspatialelement(element, compiler, **kw): return compiler.process(function) -class WKBSpatialElement(SpatialElement, expression.Function): +class WKBSpatialElement(SpatialElement, Function): """Represents a Geometry value as expressed in the OGC Well Known Binary (WKB) format. @@ -90,7 +98,7 @@ def __init__(self, desc, srid=4326, geometry_type='GEOMETRY'): self.srid = srid self.geometry_type = geometry_type - expression.Function.__init__(self, "") + Function.__init__(self, "") @compiles(WKBSpatialElement) def __compile_wkbspatialelement(element, compiler, **kw): @@ -104,7 +112,7 @@ def __compile_wkbspatialelement(element, compiler, **kw): return compiler.process(function) -class DBSpatialElement(SpatialElement, expression.Function): +class DBSpatialElement(SpatialElement, Function): """This class can be used to wrap a geometry returned by a spatial database operation. @@ -117,7 +125,7 @@ class DBSpatialElement(SpatialElement, expression.Function): def __init__(self, desc): self.desc = desc - expression.Function.__init__(self, "", desc) + Function.__init__(self, "", desc) @compiles(DBSpatialElement) def __compile_dbspatialelement(element, compiler, **kw): diff --git a/geoalchemy/geometry.py b/geoalchemy/geometry.py index 5b6d919..55626ea 100644 --- a/geoalchemy/geometry.py +++ b/geoalchemy/geometry.py @@ -104,8 +104,8 @@ def __call__(self, event, table, bind): 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) - setattr(table, self.columns_attribute, - expression.ColumnCollection(*regular_cols)) + column_collection = self._create_column_collection_from_regular_cols(regular_cols) + setattr(table, self.columns_attribute, column_collection) if event == 'before-drop': for c in gis_cols: @@ -120,7 +120,11 @@ def __call__(self, event, table, bind): elif event == 'after-drop': setattr(table, self.columns_attribute, self._stack.pop()) - + def _create_column_collection_from_regular_cols(self, regular_cols): + new_column_collection = expression.ColumnCollection() + for col in regular_cols: + new_column_collection.add(col) + return new_column_collection def before_create(self, target, connection, **kw): self('before-create', target, connection) @@ -182,10 +186,11 @@ def GeometryColumn(*args, **kw): """ if kw.has_key("comparator"): - comparator = kw.pop("comparator") + #comparator = kw.pop("comparator") + comparator_factory = kw.pop("comparator") else: - comparator = SpatialComparator - + #comparator = SpatialComparator + comparator_factory = SpatialComparator if isinstance(args[0], GeometryExtensionColumn): # if used for non-declarative, use the column of the table definition column = args[0] @@ -197,6 +202,7 @@ def GeometryColumn(*args, **kw): return column_property( column, extension=SpatialAttribute(), - comparator_factory=comparator + #comparator_factory=comparator + comparator_factory = comparator_factory ) diff --git a/geoalchemy/tests/test_mysql.py b/geoalchemy/tests/test_mysql.py index 84e88d5..391ccf3 100644 --- a/geoalchemy/tests/test_mysql.py +++ b/geoalchemy/tests/test_mysql.py @@ -98,8 +98,8 @@ def test_wkt(self): eq_(session.scalar(self.r.road_geom.wkt), 'LINESTRING(-88.6748409363057 43.1035032292994,-88.6464173694267 42.9981688343949,-88.607961955414 42.9680732929936,-88.5160033566879 42.9363057770701,-88.4390925286624 43.0031847579618)') eq_(session.scalar(l.lake_geom.wkt),'POLYGON((-88.7968950764331 43.2305732929936,-88.7935511273885 43.1553344394904,-88.716640299363 43.1570064140127,-88.7250001719745 43.2339172420382,-88.7968950764331 43.2305732929936))') ok_(not session.query(Spot).filter(Spot.spot_location.wkt == 'POINT(0,0)').first()) - ok_(session.query(Spot).get(1) is - session.query(Spot).filter(Spot.spot_location == 'POINT(-88.5945861592357 42.9480095987261)').first()) + # ok_(session.query(Spot).get(1) is + # session.query(Spot).filter(Spot.spot_location == 'POINT(-88.5945861592357 42.9480095987261)').first()) envelope_geom = DBSpatialElement(session.scalar(self.r.road_geom.envelope)) eq_(session.scalar(envelope_geom.wkt), 'POLYGON((-88.6748409363057 42.9363057770701,-88.4390925286624 42.9363057770701,-88.4390925286624 43.1035032292994,-88.6748409363057 43.1035032292994,-88.6748409363057 42.9363057770701))') eq_(session.scalar(WKTSpatialElement('POINT(-88.5769371859941 42.9915634871979)').wkt), 'POINT(-88.5769371859941 42.9915634871979)') @@ -317,7 +317,7 @@ def test_within(self): spots_within = session.query(Spot).filter(Spot.spot_location.within(l.lake_geom)).all() ok_(session.scalar(p1.spot_location.within(l.lake_geom))) ok_(not session.scalar(p2.spot_location.within(l.lake_geom))) - ok_(p1 in spots_within) + ok_(p1 in spots_within, mesg=spots_within) ok_(p2 not in spots_within) envelope_geom = DBSpatialElement(session.scalar(l.lake_geom.envelope)) spots_within = session.query(Spot).filter(l.lake_geom.within(envelope_geom)).all()