Replaced HAS_SPATIAL_DB by testing database feature

Refs #22632. This should be the base for using more database
features to exclude specific backends in GIS tests.
Thanks Tim Graham for the review.
This commit is contained in:
Claude Paroz 2014-08-17 19:06:25 +02:00
parent 3569536491
commit 6295ea0027
20 changed files with 101 additions and 76 deletions

View File

@ -9,6 +9,10 @@ from django.utils import six
from django.utils.encoding import python_2_unicode_compatible
class BaseSpatialFeatures(object):
gis_enabled = True
class BaseSpatialOperations(object):
"""
This module holds the base `BaseSpatialBackend` object, which is

View File

@ -1,12 +1,21 @@
from django.db.backends.mysql.base import DatabaseWrapper as MySQLDatabaseWrapper
from django.db.backends.mysql.base import (
DatabaseWrapper as MySQLDatabaseWrapper,
DatabaseFeatures as MySQLDatabaseFeatures,
)
from django.contrib.gis.db.backends.base import BaseSpatialFeatures
from django.contrib.gis.db.backends.mysql.creation import MySQLCreation
from django.contrib.gis.db.backends.mysql.introspection import MySQLIntrospection
from django.contrib.gis.db.backends.mysql.operations import MySQLOperations
class DatabaseFeatures(BaseSpatialFeatures, MySQLDatabaseFeatures):
pass
class DatabaseWrapper(MySQLDatabaseWrapper):
def __init__(self, *args, **kwargs):
super(DatabaseWrapper, self).__init__(*args, **kwargs)
self.features = DatabaseFeatures(self)
self.creation = MySQLCreation(self)
self.ops = MySQLOperations(self)
self.introspection = MySQLIntrospection(self)

View File

@ -1,12 +1,21 @@
from django.db.backends.oracle.base import DatabaseWrapper as OracleDatabaseWrapper
from django.db.backends.oracle.base import (
DatabaseWrapper as OracleDatabaseWrapper,
DatabaseFeatures as OracleDatabaseFeatures,
)
from django.contrib.gis.db.backends.base import BaseSpatialFeatures
from django.contrib.gis.db.backends.oracle.creation import OracleCreation
from django.contrib.gis.db.backends.oracle.introspection import OracleIntrospection
from django.contrib.gis.db.backends.oracle.operations import OracleOperations
class DatabaseFeatures(BaseSpatialFeatures, OracleDatabaseFeatures):
pass
class DatabaseWrapper(OracleDatabaseWrapper):
def __init__(self, *args, **kwargs):
super(DatabaseWrapper, self).__init__(*args, **kwargs)
self.features = DatabaseFeatures(self)
self.ops = OracleOperations(self)
self.creation = OracleCreation(self)
self.introspection = OracleIntrospection(self)

View File

@ -1,15 +1,24 @@
from django.db.backends.creation import NO_DB_ALIAS
from django.db.backends.postgresql_psycopg2.base import DatabaseWrapper as Psycopg2DatabaseWrapper
from django.db.backends.postgresql_psycopg2.base import (
DatabaseWrapper as Psycopg2DatabaseWrapper,
DatabaseFeatures as Psycopg2DatabaseFeatures
)
from django.contrib.gis.db.backends.base import BaseSpatialFeatures
from django.contrib.gis.db.backends.postgis.creation import PostGISCreation
from django.contrib.gis.db.backends.postgis.introspection import PostGISIntrospection
from django.contrib.gis.db.backends.postgis.operations import PostGISOperations
from django.contrib.gis.db.backends.postgis.schema import PostGISSchemaEditor
class DatabaseFeatures(BaseSpatialFeatures, Psycopg2DatabaseFeatures):
pass
class DatabaseWrapper(Psycopg2DatabaseWrapper):
def __init__(self, *args, **kwargs):
super(DatabaseWrapper, self).__init__(*args, **kwargs)
if kwargs.get('alias', '') != NO_DB_ALIAS:
self.features = DatabaseFeatures(self)
self.creation = PostGISCreation(self)
self.ops = PostGISOperations(self)
self.introspection = PostGISIntrospection(self)

View File

@ -4,7 +4,9 @@ from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.db.backends.sqlite3.base import (Database,
DatabaseWrapper as SQLiteDatabaseWrapper, SQLiteCursorWrapper)
DatabaseWrapper as SQLiteDatabaseWrapper,
DatabaseFeatures as SQLiteDatabaseFeatures, SQLiteCursorWrapper)
from django.contrib.gis.db.backends.base import BaseSpatialFeatures
from django.contrib.gis.db.backends.spatialite.client import SpatiaLiteClient
from django.contrib.gis.db.backends.spatialite.creation import SpatiaLiteCreation
from django.contrib.gis.db.backends.spatialite.introspection import SpatiaLiteIntrospection
@ -13,6 +15,10 @@ from django.contrib.gis.db.backends.spatialite.schema import SpatialiteSchemaEdi
from django.utils import six
class DatabaseFeatures(BaseSpatialFeatures, SQLiteDatabaseFeatures):
pass
class DatabaseWrapper(SQLiteDatabaseWrapper):
def __init__(self, *args, **kwargs):
# Before we get too far, make sure pysqlite 2.5+ is installed.
@ -33,6 +39,7 @@ class DatabaseWrapper(SQLiteDatabaseWrapper):
'SPATIALITE_LIBRARY_PATH in your settings.'
)
super(DatabaseWrapper, self).__init__(*args, **kwargs)
self.features = DatabaseFeatures(self)
self.ops = SpatiaLiteOperations(self)
self.client = SpatiaLiteClient(self)
self.creation = SpatiaLiteCreation(self)

View File

@ -7,23 +7,24 @@ from django.db.models import Q
from django.contrib.gis.geos import HAS_GEOS
from django.contrib.gis.measure import D # alias for Distance
from django.contrib.gis.tests.utils import (
HAS_SPATIAL_DB, mysql, oracle, postgis, spatialite, no_oracle, no_spatialite
mysql, oracle, postgis, spatialite, no_oracle, no_spatialite
)
from django.test import TestCase
from django.test import TestCase, skipUnlessDBFeature
if HAS_GEOS and HAS_SPATIAL_DB:
if HAS_GEOS:
from django.contrib.gis.geos import GEOSGeometry, LineString
from .models import (AustraliaCity, Interstate, SouthTexasInterstate,
SouthTexasCity, SouthTexasCityFt, CensusZipcode, SouthTexasZipcode)
@skipUnless(HAS_GEOS and HAS_SPATIAL_DB and not mysql,
"Geos and spatial db (not mysql) are required.")
@skipUnless(HAS_GEOS and not mysql,
"GEOS and spatial db (not mysql) are required.")
@skipUnlessDBFeature("gis_enabled")
class DistanceTest(TestCase):
fixtures = ['initial']
if HAS_GEOS and HAS_SPATIAL_DB:
if HAS_GEOS:
# A point we are testing distances with -- using a WGS84
# coordinate that'll be implicitly transformed to that to
# the coordinate system of the field, EPSG:32140 (Texas South Central

View File

@ -1,19 +1,16 @@
from __future__ import unicode_literals
from unittest import skipUnless
from django.contrib.gis.geos import HAS_GEOS
from django.contrib.gis.tests.utils import HAS_SPATIAL_DB
from django.test import TestCase, override_settings
from django.test import TestCase, override_settings, skipUnlessDBFeature
if HAS_GEOS and HAS_SPATIAL_DB:
if HAS_GEOS:
from django.contrib.gis import admin
from django.contrib.gis.geos import Point
from .models import City
@skipUnless(HAS_GEOS and HAS_SPATIAL_DB, "Geos and spatial db are required.")
@skipUnlessDBFeature("gis_enabled")
@override_settings(ROOT_URLCONF='django.contrib.gis.tests.geoadmin.urls')
class GeoAdminTest(TestCase):

View File

@ -6,8 +6,9 @@ from xml.dom import minidom
from django.conf import settings
from django.contrib.sites.models import Site
from django.contrib.gis.geos import HAS_GEOS
from django.contrib.gis.tests.utils import HAS_SPATIAL_DB
from django.test import TestCase, modify_settings, override_settings
from django.test import (
TestCase, modify_settings, override_settings, skipUnlessDBFeature
)
if HAS_GEOS:
from .models import City
@ -15,7 +16,7 @@ if HAS_GEOS:
@modify_settings(INSTALLED_APPS={'append': 'django.contrib.sites'})
@override_settings(ROOT_URLCONF='django.contrib.gis.tests.geoapp.urls')
@skipUnless(HAS_GEOS and HAS_SPATIAL_DB, "Geos and spatial db are required.")
@skipUnlessDBFeature("gis_enabled")
class GeoFeedTest(TestCase):
fixtures = ['initial']

View File

@ -7,15 +7,14 @@ from unittest import skipUnless
from django.contrib.gis.geos import HAS_GEOS
from django.contrib.gis.tests.utils import no_mysql, no_spatialite
from django.contrib.gis.shortcuts import render_to_kmz
from django.contrib.gis.tests.utils import HAS_SPATIAL_DB
from django.db.models import Count, Min
from django.test import TestCase
from django.test import TestCase, skipUnlessDBFeature
if HAS_GEOS:
from .models import City, PennsylvaniaCity, State, Truth
@skipUnless(HAS_GEOS and HAS_SPATIAL_DB, "Geos and spatial db are required.")
@skipUnlessDBFeature("gis_enabled")
class GeoRegressionTests(TestCase):
fixtures = ['initial']

View File

@ -8,9 +8,10 @@ import zipfile
from django.conf import settings
from django.contrib.gis.geos import HAS_GEOS
from django.contrib.gis.tests.utils import HAS_SPATIAL_DB
from django.contrib.sites.models import Site
from django.test import TestCase, modify_settings, override_settings
from django.test import (
TestCase, modify_settings, override_settings, skipUnlessDBFeature
)
from django.utils.deprecation import RemovedInDjango20Warning
if HAS_GEOS:
@ -19,7 +20,7 @@ if HAS_GEOS:
@modify_settings(INSTALLED_APPS={'append': ['django.contrib.sites', 'django.contrib.sitemaps']})
@override_settings(ROOT_URLCONF='django.contrib.gis.tests.geoapp.urls')
@skipUnless(HAS_GEOS and HAS_SPATIAL_DB, "Geos and spatial db are required.")
@skipUnlessDBFeature("gis_enabled")
class GeoSitemapTest(TestCase):
def setUp(self):

View File

@ -8,9 +8,8 @@ from django.db import connection
from django.contrib.gis import gdal
from django.contrib.gis.geos import HAS_GEOS
from django.contrib.gis.tests.utils import (
HAS_SPATIAL_DB, no_mysql, no_oracle, no_spatialite,
mysql, oracle, postgis, spatialite)
from django.test import TestCase
no_mysql, no_oracle, no_spatialite, mysql, oracle, postgis, spatialite)
from django.test import TestCase, skipUnlessDBFeature
from django.utils import six
if HAS_GEOS:
@ -28,7 +27,7 @@ def postgis_bug_version():
return spatial_version and (2, 0, 0) <= spatial_version <= (2, 0, 1)
@skipUnless(HAS_GEOS and HAS_SPATIAL_DB, "Geos and spatial db are required.")
@skipUnlessDBFeature("gis_enabled")
class GeoModelTest(TestCase):
fixtures = ['initial']
@ -205,7 +204,7 @@ class GeoModelTest(TestCase):
self.assertIsInstance(cities2[0].point, Point)
@skipUnless(HAS_GEOS and HAS_SPATIAL_DB, "Geos and spatial db are required.")
@skipUnlessDBFeature("gis_enabled")
class GeoLookupTest(TestCase):
fixtures = ['initial']
@ -397,7 +396,7 @@ class GeoLookupTest(TestCase):
self.assertEqual('Lawrence', City.objects.get(point__relate=(ks.poly, intersects_mask)).name)
@skipUnless(HAS_GEOS and HAS_SPATIAL_DB, "Geos and spatial db are required.")
@skipUnlessDBFeature("gis_enabled")
class GeoQuerySetTest(TestCase):
fixtures = ['initial']

View File

@ -1,13 +1,14 @@
from __future__ import unicode_literals
from unittest import skipUnless
from django.contrib.gis.tests.utils import HAS_SPATIAL_DB
from django.core.management import call_command
from django.db import connection
from django.test import override_settings, override_system_checks, TransactionTestCase
from django.test import (
override_settings, override_system_checks, skipUnlessDBFeature,
TransactionTestCase
)
@skipUnlessDBFeature("gis_enabled")
class MigrateTests(TransactionTestCase):
"""
Tests running the migrate command in Geodjango.
@ -26,7 +27,6 @@ class MigrateTests(TransactionTestCase):
with connection.cursor() as cursor:
self.assertNotIn(table, connection.introspection.get_table_list(cursor))
@skipUnless(HAS_SPATIAL_DB, "Spatial db is required.")
@override_system_checks([])
@override_settings(MIGRATION_MODULES={"gis": "django.contrib.gis.tests.gis_migrations.migrations"})
def test_migrate_gis(self):

View File

@ -1,14 +1,11 @@
from __future__ import unicode_literals
from unittest import skipUnless
from django.contrib.gis.tests.utils import HAS_SPATIAL_DB
from django.db import connection, migrations, models
from django.db.migrations.migration import Migration
from django.db.migrations.state import ProjectState
from django.test import TransactionTestCase
from django.test import skipUnlessDBFeature, TransactionTestCase
if HAS_SPATIAL_DB:
if connection.features.gis_enabled:
from django.contrib.gis.db.models import fields
try:
GeometryColumns = connection.ops.geometry_columns()
@ -17,7 +14,7 @@ if HAS_SPATIAL_DB:
HAS_GEOMETRY_COLUMNS = False
@skipUnless(HAS_SPATIAL_DB, "Spatial db is required.")
@skipUnlessDBFeature("gis_enabled")
class OperationTests(TransactionTestCase):
available_apps = ["django.contrib.gis.tests.gis_migrations"]

View File

@ -5,10 +5,9 @@ from unittest import skipUnless
from django.core.management import call_command
from django.db import connections
from django.test import TestCase
from django.test import TestCase, skipUnlessDBFeature
from django.contrib.gis.gdal import HAS_GDAL
from django.contrib.gis.geometry.test_data import TEST_DATA
from django.contrib.gis.tests.utils import HAS_SPATIAL_DB
from django.utils.six import StringIO
if HAS_GDAL:
@ -18,7 +17,8 @@ if HAS_GDAL:
from .models import AllOGRFields
@skipUnless(HAS_GDAL and HAS_SPATIAL_DB, "GDAL and spatial db are required.")
@skipUnless(HAS_GDAL, "InspectDbTests needs GDAL support")
@skipUnlessDBFeature("gis_enabled")
class InspectDbTests(TestCase):
def test_geom_columns(self):
"""
@ -34,7 +34,8 @@ class InspectDbTests(TestCase):
self.assertIn('objects = models.GeoManager()', output)
@skipUnless(HAS_GDAL and HAS_SPATIAL_DB, "GDAL and spatial db are required.")
@skipUnless(HAS_GDAL, "OGRInspectTest needs GDAL support")
@skipUnlessDBFeature("gis_enabled")
class OGRInspectTest(TestCase):
maxDiff = 1024

View File

@ -8,10 +8,10 @@ import unittest
from unittest import skipUnless
from django.contrib.gis.gdal import HAS_GDAL
from django.contrib.gis.tests.utils import HAS_SPATIAL_DB, mysql
from django.contrib.gis.tests.utils import mysql
from django.db import router
from django.conf import settings
from django.test import TestCase
from django.test import TestCase, skipUnlessDBFeature
from django.utils._os import upath
if HAS_GDAL:
@ -36,7 +36,8 @@ NUMS = [1, 2, 1, 19, 1] # Number of polygons for each.
STATES = ['Texas', 'Texas', 'Texas', 'Hawaii', 'Colorado']
@skipUnless(HAS_GDAL and HAS_SPATIAL_DB, "GDAL and spatial db are required.")
@skipUnless(HAS_GDAL, "LayerMapTest needs GDAL support")
@skipUnlessDBFeature("gis_enabled")
class LayerMapTest(TestCase):
def test_init(self):
@ -319,7 +320,8 @@ class OtherRouter(object):
return True
@skipUnless(HAS_GDAL and HAS_SPATIAL_DB, "GDAL and spatial db are required.")
@skipUnless(HAS_GDAL, "LayerMapRouterTest needs GDAL support")
@skipUnlessDBFeature("gis_enabled")
class LayerMapRouterTest(TestCase):
def setUp(self):

View File

@ -1,10 +1,8 @@
from __future__ import unicode_literals
from unittest import skipUnless
from django.contrib.gis.geos import HAS_GEOS
from django.contrib.gis.tests.utils import HAS_SPATIAL_DB, mysql, no_mysql, no_oracle, no_spatialite
from django.test import TestCase
from django.contrib.gis.tests.utils import mysql, no_mysql, no_oracle, no_spatialite
from django.test import TestCase, skipUnlessDBFeature
if HAS_GEOS:
from django.contrib.gis.db.models import Collect, Count, Extent, F, Union
@ -14,7 +12,7 @@ if HAS_GEOS:
from .models import City, Location, DirectoryEntry, Parcel, Book, Author, Article
@skipUnless(HAS_GEOS and HAS_SPATIAL_DB, "Geos and spatial db are required.")
@skipUnlessDBFeature("gis_enabled")
class RelatedGeoModelTest(TestCase):
fixtures = ['initial']

View File

@ -2,17 +2,17 @@ from unittest import skipUnless
from django.forms import ValidationError
from django.contrib.gis.gdal import HAS_GDAL
from django.contrib.gis.tests.utils import HAS_SPATIAL_DB
from django.test import SimpleTestCase
from django.test import SimpleTestCase, skipUnlessDBFeature
from django.utils import six
from django.utils.html import escape
if HAS_SPATIAL_DB:
if HAS_GDAL:
from django.contrib.gis import forms
from django.contrib.gis.geos import GEOSGeometry
@skipUnless(HAS_GDAL and HAS_SPATIAL_DB, "GeometryFieldTest needs gdal support and a spatial database")
@skipUnless(HAS_GDAL, "GeometryFieldTest needs GDAL support")
@skipUnlessDBFeature("gis_enabled")
class GeometryFieldTest(SimpleTestCase):
def test_init(self):
@ -90,8 +90,8 @@ class GeometryFieldTest(SimpleTestCase):
self.assertFalse(form.has_changed())
@skipUnless(HAS_GDAL and HAS_SPATIAL_DB,
"SpecializedFieldTest needs gdal support and a spatial database")
@skipUnless(HAS_GDAL, "SpecializedFieldTest needs GDAL support")
@skipUnlessDBFeature("gis_enabled")
class SpecializedFieldTest(SimpleTestCase):
def setUp(self):
self.geometries = {
@ -258,8 +258,8 @@ class SpecializedFieldTest(SimpleTestCase):
self.assertFalse(GeometryForm(data={'g': invalid.wkt}).is_valid())
@skipUnless(HAS_GDAL and HAS_SPATIAL_DB,
"OSMWidgetTest needs gdal support and a spatial database")
@skipUnless(HAS_GDAL, "OSMWidgetTest needs GDAL support")
@skipUnlessDBFeature("gis_enabled")
class OSMWidgetTest(SimpleTestCase):
def setUp(self):
self.geometries = {
@ -300,8 +300,8 @@ class OSMWidgetTest(SimpleTestCase):
rendered)
@skipUnless(HAS_GDAL and HAS_SPATIAL_DB,
"CustomGeometryWidgetTest needs gdal support and a spatial database")
@skipUnless(HAS_GDAL, "CustomGeometryWidgetTest needs GDAL support")
@skipUnlessDBFeature("gis_enabled")
class CustomGeometryWidgetTest(SimpleTestCase):
def test_custom_serialization_widget(self):

View File

@ -49,12 +49,3 @@ elif spatialite:
else:
HAS_SPATIALREFSYS = False
SpatialRefSys = None
def has_spatial_db():
# All databases must have spatial backends to run GeoDjango tests.
spatial_dbs = [name for name, db_dict in settings.DATABASES.items()
if db_dict['ENGINE'].startswith('django.contrib.gis')]
return len(spatial_dbs) == len(settings.DATABASES)
HAS_SPATIAL_DB = has_spatial_db()

View File

@ -474,6 +474,7 @@ class BaseDatabaseWrapper(object):
class BaseDatabaseFeatures(object):
gis_enabled = False
allows_group_by_pk = False
# True if django.db.backends.utils.typecast_timestamp is used on values
# returned from dates() calls.

View File

@ -60,13 +60,12 @@ ALWAYS_MIDDLEWARE_CLASSES = (
def get_test_modules():
from django.contrib.gis.tests.utils import HAS_SPATIAL_DB
modules = []
discovery_paths = [
(None, RUNTESTS_DIR),
(CONTRIB_MODULE_PATH, CONTRIB_DIR)
]
if HAS_SPATIAL_DB:
if connection.features.gis_enabled:
discovery_paths.append(
('django.contrib.gis.tests', os.path.join(CONTRIB_DIR, 'gis', 'tests'))
)