Fixed postgis test database initialization
Refs #20968. Allow querying template_postgis presence without existing test database. Thanks Tim Graham for the review.
This commit is contained in:
parent
c7a19f4203
commit
df30ae07fc
|
@ -1,5 +1,5 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db.backends.creation import NO_DB_ALIAS
|
from django.db.backends import NO_DB_ALIAS
|
||||||
from django.db.backends.postgresql_psycopg2.base import (
|
from django.db.backends.postgresql_psycopg2.base import (
|
||||||
DatabaseWrapper as Psycopg2DatabaseWrapper,
|
DatabaseWrapper as Psycopg2DatabaseWrapper,
|
||||||
DatabaseFeatures as Psycopg2DatabaseFeatures
|
DatabaseFeatures as Psycopg2DatabaseFeatures
|
||||||
|
@ -31,7 +31,7 @@ class DatabaseWrapper(Psycopg2DatabaseWrapper):
|
||||||
@cached_property
|
@cached_property
|
||||||
def template_postgis(self):
|
def template_postgis(self):
|
||||||
template_postgis = getattr(settings, 'POSTGIS_TEMPLATE', 'template_postgis')
|
template_postgis = getattr(settings, 'POSTGIS_TEMPLATE', 'template_postgis')
|
||||||
with self.cursor() as cursor:
|
with self._nodb_connection.cursor() as cursor:
|
||||||
cursor.execute('SELECT 1 FROM pg_database WHERE datname = %s LIMIT 1;', (template_postgis,))
|
cursor.execute('SELECT 1 FROM pg_database WHERE datname = %s LIMIT 1;', (template_postgis,))
|
||||||
if cursor.fetchone():
|
if cursor.fetchone():
|
||||||
return template_postgis
|
return template_postgis
|
||||||
|
@ -43,4 +43,3 @@ class DatabaseWrapper(Psycopg2DatabaseWrapper):
|
||||||
# Check that postgis extension is installed on PostGIS >= 2
|
# Check that postgis extension is installed on PostGIS >= 2
|
||||||
with self.cursor() as cursor:
|
with self.cursor() as cursor:
|
||||||
cursor.execute("CREATE EXTENSION IF NOT EXISTS postgis")
|
cursor.execute("CREATE EXTENSION IF NOT EXISTS postgis")
|
||||||
cursor.connection.commit()
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ from __future__ import unicode_literals
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from tempfile import NamedTemporaryFile
|
from tempfile import NamedTemporaryFile
|
||||||
import unittest
|
|
||||||
|
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
from django.contrib.gis import gdal
|
from django.contrib.gis import gdal
|
||||||
|
@ -292,6 +291,11 @@ class GeoLookupTest(TestCase):
|
||||||
# Right: A >> B => true if xmin(A) > xmax(B)
|
# Right: A >> B => true if xmin(A) > xmax(B)
|
||||||
# See: BOX2D_left() and BOX2D_right() in lwgeom_box2dfloat4.c in PostGIS source.
|
# See: BOX2D_left() and BOX2D_right() in lwgeom_box2dfloat4.c in PostGIS source.
|
||||||
|
|
||||||
|
# The left/right lookup tests are known failures on PostGIS 2.0/2.0.1
|
||||||
|
# http://trac.osgeo.org/postgis/ticket/2035
|
||||||
|
if postgis_bug_version():
|
||||||
|
self.skipTest("PostGIS 2.0/2.0.1 left and right lookups are known to be buggy.")
|
||||||
|
|
||||||
# Getting the borders for Colorado & Kansas
|
# Getting the borders for Colorado & Kansas
|
||||||
co_border = State.objects.get(name='Colorado').poly
|
co_border = State.objects.get(name='Colorado').poly
|
||||||
ks_border = State.objects.get(name='Kansas').poly
|
ks_border = State.objects.get(name='Kansas').poly
|
||||||
|
@ -325,11 +329,6 @@ class GeoLookupTest(TestCase):
|
||||||
for c in qs:
|
for c in qs:
|
||||||
self.assertIn(c.name, cities)
|
self.assertIn(c.name, cities)
|
||||||
|
|
||||||
# The left/right lookup tests are known failures on PostGIS 2.0/2.0.1
|
|
||||||
# http://trac.osgeo.org/postgis/ticket/2035
|
|
||||||
if postgis_bug_version():
|
|
||||||
test_left_right_lookups = unittest.expectedFailure(test_left_right_lookups)
|
|
||||||
|
|
||||||
def test_equals_lookups(self):
|
def test_equals_lookups(self):
|
||||||
"Testing the 'same_as' and 'equals' lookup types."
|
"Testing the 'same_as' and 'equals' lookup types."
|
||||||
pnt = fromstr('POINT (-95.363151 29.763374)', srid=4326)
|
pnt = fromstr('POINT (-95.363151 29.763374)', srid=4326)
|
||||||
|
|
|
@ -30,6 +30,8 @@ TableInfo = namedtuple('TableInfo', ['name', 'type'])
|
||||||
FieldInfo = namedtuple('FieldInfo',
|
FieldInfo = namedtuple('FieldInfo',
|
||||||
'name type_code display_size internal_size precision scale null_ok')
|
'name type_code display_size internal_size precision scale null_ok')
|
||||||
|
|
||||||
|
NO_DB_ALIAS = '__no_db__'
|
||||||
|
|
||||||
|
|
||||||
class BaseDatabaseWrapper(object):
|
class BaseDatabaseWrapper(object):
|
||||||
"""
|
"""
|
||||||
|
@ -477,6 +479,24 @@ class BaseDatabaseWrapper(object):
|
||||||
if must_close:
|
if must_close:
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def _nodb_connection(self):
|
||||||
|
"""
|
||||||
|
Alternative connection to be used when there is no need to access
|
||||||
|
the main database, specifically for test db creation/deletion.
|
||||||
|
This also prevents the production database from being exposed to
|
||||||
|
potential child threads while (or after) the test database is destroyed.
|
||||||
|
Refs #10868, #17786, #16969.
|
||||||
|
"""
|
||||||
|
settings_dict = self.settings_dict.copy()
|
||||||
|
settings_dict['NAME'] = None
|
||||||
|
#backend = load_backend(settings_dict['ENGINE'])
|
||||||
|
nodb_connection = self.__class__(
|
||||||
|
settings_dict,
|
||||||
|
alias=NO_DB_ALIAS,
|
||||||
|
allow_thread_sharing=False)
|
||||||
|
return nodb_connection
|
||||||
|
|
||||||
def _start_transaction_under_autocommit(self):
|
def _start_transaction_under_autocommit(self):
|
||||||
"""
|
"""
|
||||||
Only required when autocommits_when_autocommit_is_off = True.
|
Only required when autocommits_when_autocommit_is_off = True.
|
||||||
|
|
|
@ -3,9 +3,7 @@ import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db.utils import load_backend
|
|
||||||
from django.utils.encoding import force_bytes
|
from django.utils.encoding import force_bytes
|
||||||
from django.utils.functional import cached_property
|
|
||||||
from django.utils.six.moves import input
|
from django.utils.six.moves import input
|
||||||
from django.utils.six import StringIO
|
from django.utils.six import StringIO
|
||||||
from django.db import router
|
from django.db import router
|
||||||
|
@ -17,7 +15,6 @@ from .utils import truncate_name
|
||||||
# The prefix to put on the default database name when creating
|
# The prefix to put on the default database name when creating
|
||||||
# the test database.
|
# the test database.
|
||||||
TEST_DATABASE_PREFIX = 'test_'
|
TEST_DATABASE_PREFIX = 'test_'
|
||||||
NO_DB_ALIAS = '__no_db__'
|
|
||||||
|
|
||||||
|
|
||||||
class BaseDatabaseCreation(object):
|
class BaseDatabaseCreation(object):
|
||||||
|
@ -34,23 +31,12 @@ class BaseDatabaseCreation(object):
|
||||||
def __init__(self, connection):
|
def __init__(self, connection):
|
||||||
self.connection = connection
|
self.connection = connection
|
||||||
|
|
||||||
@cached_property
|
@property
|
||||||
def _nodb_connection(self):
|
def _nodb_connection(self):
|
||||||
"""
|
"""
|
||||||
Alternative connection to be used when there is no need to access
|
Used to be defined here, now moved to DatabaseWrapper.
|
||||||
the main database, specifically for test db creation/deletion.
|
|
||||||
This also prevents the production database from being exposed to
|
|
||||||
potential child threads while (or after) the test database is destroyed.
|
|
||||||
Refs #10868, #17786, #16969.
|
|
||||||
"""
|
"""
|
||||||
settings_dict = self.connection.settings_dict.copy()
|
return self.connection._nodb_connection
|
||||||
settings_dict['NAME'] = None
|
|
||||||
backend = load_backend(settings_dict['ENGINE'])
|
|
||||||
nodb_connection = backend.DatabaseWrapper(
|
|
||||||
settings_dict,
|
|
||||||
alias=NO_DB_ALIAS,
|
|
||||||
allow_thread_sharing=False)
|
|
||||||
return nodb_connection
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _digest(cls, *args):
|
def _digest(cls, *args):
|
||||||
|
|
Loading…
Reference in New Issue