diff --git a/django/contrib/gis/db/backends/base.py b/django/contrib/gis/db/backends/base.py index 171a304439..7db7ce51ba 100644 --- a/django/contrib/gis/db/backends/base.py +++ b/django/contrib/gis/db/backends/base.py @@ -3,10 +3,12 @@ Base/mixin classes for the spatial backend database operations and the `SpatialRefSys` model the backend. """ import re + from django.contrib.gis import gdal from django.utils import six from django.utils.encoding import python_2_unicode_compatible + class BaseSpatialOperations(object): """ This module holds the base `BaseSpatialBackend` object, which is @@ -18,7 +20,7 @@ class BaseSpatialOperations(object): geometry_operators = {} geography_operators = {} geography_functions = {} - gis_terms = {} + gis_terms = set() truncate_params = {} # Quick booleans for the type of this spatial backend, and diff --git a/django/contrib/gis/db/backends/mysql/operations.py b/django/contrib/gis/db/backends/mysql/operations.py index 14402ec0a3..26cec743a9 100644 --- a/django/contrib/gis/db/backends/mysql/operations.py +++ b/django/contrib/gis/db/backends/mysql/operations.py @@ -3,7 +3,6 @@ from django.db.backends.mysql.base import DatabaseOperations from django.contrib.gis.db.backends.adapter import WKTAdapter from django.contrib.gis.db.backends.base import BaseSpatialOperations -from django.utils import six class MySQLOperations(DatabaseOperations, BaseSpatialOperations): @@ -18,21 +17,21 @@ class MySQLOperations(DatabaseOperations, BaseSpatialOperations): Adaptor = Adapter # Backwards-compatibility alias. geometry_functions = { - 'bbcontains' : 'MBRContains', # For consistency w/PostGIS API - 'bboverlaps' : 'MBROverlaps', # .. .. - 'contained' : 'MBRWithin', # .. .. - 'contains' : 'MBRContains', - 'disjoint' : 'MBRDisjoint', - 'equals' : 'MBREqual', - 'exact' : 'MBREqual', - 'intersects' : 'MBRIntersects', - 'overlaps' : 'MBROverlaps', - 'same_as' : 'MBREqual', - 'touches' : 'MBRTouches', - 'within' : 'MBRWithin', - } + 'bbcontains': 'MBRContains', # For consistency w/PostGIS API + 'bboverlaps': 'MBROverlaps', # .. .. + 'contained': 'MBRWithin', # .. .. + 'contains': 'MBRContains', + 'disjoint': 'MBRDisjoint', + 'equals': 'MBREqual', + 'exact': 'MBREqual', + 'intersects': 'MBRIntersects', + 'overlaps': 'MBROverlaps', + 'same_as': 'MBREqual', + 'touches': 'MBRTouches', + 'within': 'MBRWithin', + } - gis_terms = dict([(term, None) for term in list(geometry_functions) + ['isnull']]) + gis_terms = set(geometry_functions) | set(['isnull']) def geo_db_type(self, f): return f.geom_type diff --git a/django/contrib/gis/db/backends/oracle/operations.py b/django/contrib/gis/db/backends/oracle/operations.py index 18697ac8c0..84217c331b 100644 --- a/django/contrib/gis/db/backends/oracle/operations.py +++ b/django/contrib/gis/db/backends/oracle/operations.py @@ -18,6 +18,7 @@ from django.contrib.gis.geometry.backend import Geometry from django.contrib.gis.measure import Distance from django.utils import six + class SDOOperation(SpatialFunction): "Base class for SDO* Oracle operations." sql_template = "%(function)s(%(geo_col)s, %(geometry)s) %(operator)s '%(result)s'" @@ -32,6 +33,7 @@ class SDODistance(SpatialFunction): sql_template = ('%(function)s(%(geo_col)s, %(geometry)s, %(tolerance)s) ' '%(operator)s %(result)s') dist_func = 'SDO_GEOM.SDO_DISTANCE' + def __init__(self, op, tolerance=0.05): super(SDODistance, self).__init__(self.dist_func, tolerance=tolerance, @@ -40,6 +42,7 @@ class SDODistance(SpatialFunction): class SDODWithin(SpatialFunction): dwithin_func = 'SDO_WITHIN_DISTANCE' sql_template = "%(function)s(%(geo_col)s, %(geometry)s, %%s) = 'TRUE'" + def __init__(self): super(SDODWithin, self).__init__(self.dwithin_func) @@ -48,6 +51,7 @@ class SDOGeomRelate(SpatialFunction): relate_func = 'SDO_GEOM.RELATE' sql_template = ("%(function)s(%(geo_col)s, '%(mask)s', %(geometry)s, " "%(tolerance)s) %(operator)s '%(mask)s'") + def __init__(self, mask, tolerance=0.05): # SDO_GEOM.RELATE(...) has a peculiar argument order: column, mask, geom, tolerance. # Moreover, the runction result is the mask (e.g., 'DISJOINT' instead of 'TRUE'). @@ -60,6 +64,7 @@ class SDORelate(SpatialFunction): mask_regex = re.compile(r'^(%s)(\+(%s))*$' % (masks, masks), re.I) sql_template = "%(function)s(%(geo_col)s, %(geometry)s, 'mask=%(mask)s') = 'TRUE'" relate_func = 'SDO_RELATE' + def __init__(self, mask): if not self.mask_regex.match(mask): raise ValueError('Invalid %s mask: "%s"' % (self.relate_func, mask)) @@ -79,12 +84,12 @@ class OracleOperations(DatabaseOperations, BaseSpatialOperations): Adaptor = Adapter # Backwards-compatibility alias. area = 'SDO_GEOM.SDO_AREA' - gml= 'SDO_UTIL.TO_GMLGEOMETRY' + gml = 'SDO_UTIL.TO_GMLGEOMETRY' centroid = 'SDO_GEOM.SDO_CENTROID' difference = 'SDO_GEOM.SDO_DIFFERENCE' distance = 'SDO_GEOM.SDO_DISTANCE' - extent= 'SDO_AGGR_MBR' - intersection= 'SDO_GEOM.SDO_INTERSECTION' + extent = 'SDO_AGGR_MBR' + intersection = 'SDO_GEOM.SDO_INTERSECTION' length = 'SDO_GEOM.SDO_LENGTH' num_geom = 'SDO_UTIL.GETNUMELEM' num_points = 'SDO_UTIL.GETNUMVERTICES' @@ -127,9 +132,8 @@ class OracleOperations(DatabaseOperations, BaseSpatialOperations): } geometry_functions.update(distance_functions) - gis_terms = ['isnull'] - gis_terms += list(geometry_functions) - gis_terms = dict([(term, None) for term in gis_terms]) + gis_terms = set(['isnull']) + gis_terms.update(geometry_functions) truncate_params = {'relate' : None} @@ -272,7 +276,8 @@ class OracleOperations(DatabaseOperations, BaseSpatialOperations): given Aggregate instance. """ agg_name = agg.__class__.__name__.lower() - if agg_name == 'union' : agg_name += 'agg' + if agg_name == 'union': + agg_name += 'agg' if agg.is_extent: sql_template = '%(function)s(%(field)s)' else: @@ -295,5 +300,5 @@ class OracleOperations(DatabaseOperations, BaseSpatialOperations): """ # This code doesn't work for bulk insert cases. assert len(placeholders) == 1 - return [[param for pholder,param + return [[param for pholder, param in six.moves.zip(placeholders[0], params[0]) if pholder != 'NULL'], ] diff --git a/django/contrib/gis/db/backends/postgis/operations.py b/django/contrib/gis/db/backends/postgis/operations.py index 4d31bbb53c..734f39c752 100644 --- a/django/contrib/gis/db/backends/postgis/operations.py +++ b/django/contrib/gis/db/backends/postgis/operations.py @@ -208,23 +208,22 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations): # for the geography type. self.geography_functions = self.distance_functions.copy() self.geography_functions.update({ - 'coveredby' : self.geometry_functions['coveredby'], - 'covers' : self.geometry_functions['covers'], - 'intersects' : self.geometry_functions['intersects'], - }) + 'coveredby': self.geometry_functions['coveredby'], + 'covers': self.geometry_functions['covers'], + 'intersects': self.geometry_functions['intersects'], + }) self.geography_operators = { - 'bboverlaps' : PostGISOperator('&&'), - } + 'bboverlaps': PostGISOperator('&&'), + } # Native geometry type support added in PostGIS 2.0. if version >= (2, 0, 0): self.geometry = True # Creating a dictionary lookup of all GIS terms for PostGIS. - gis_terms = ['isnull'] - gis_terms += list(self.geometry_operators) - gis_terms += list(self.geometry_functions) - self.gis_terms = dict([(term, None) for term in gis_terms]) + self.gis_terms = set(['isnull']) + self.gis_terms.update(self.geometry_operators) + self.gis_terms.update(self.geometry_functions) self.area = prefix + 'Area' self.bounding_circle = BOUNDINGCIRCLE @@ -247,7 +246,7 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations): self.makeline = prefix + 'MakeLine' self.mem_size = prefix + 'mem_size' self.num_geom = prefix + 'NumGeometries' - self.num_points =prefix + 'npoints' + self.num_points = prefix + 'npoints' self.perimeter = prefix + 'Perimeter' self.point_on_surface = prefix + 'PointOnSurface' self.polygonize = prefix + 'Polygonize' @@ -324,7 +323,7 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations): raise NotImplementedError('PostGIS 1.5 supports geography columns ' 'only with an SRID of 4326.') - return 'geography(%s,%d)'% (f.geom_type, f.srid) + return 'geography(%s,%d)' % (f.geom_type, f.srid) elif self.geometry: # Postgis 2.0 supports type-based geometries. # TODO: Support 'M' extension. @@ -565,7 +564,8 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations): if not self.check_aggregate_support(agg): raise NotImplementedError('%s spatial aggregate is not implmented for this backend.' % agg_name) agg_name = agg_name.lower() - if agg_name == 'union': agg_name += 'agg' + if agg_name == 'union': + agg_name += 'agg' sql_template = '%(function)s(%(field)s)' sql_function = getattr(self, agg_name) return sql_template, sql_function diff --git a/django/contrib/gis/db/backends/spatialite/operations.py b/django/contrib/gis/db/backends/spatialite/operations.py index 83745476a0..4281cafa23 100644 --- a/django/contrib/gis/db/backends/spatialite/operations.py +++ b/django/contrib/gis/db/backends/spatialite/operations.py @@ -117,9 +117,8 @@ class SpatiaLiteOperations(DatabaseOperations, BaseSpatialOperations): super(DatabaseOperations, self).__init__(connection) # Creating the GIS terms dictionary. - gis_terms = ['isnull'] - gis_terms += self.geometry_functions.keys() - self.gis_terms = dict([(term, None) for term in gis_terms]) + self.gis_terms = set(['isnull']) + self.gis_terms.update(self.geometry_functions) @cached_property def spatial_version(self):