Author: jbronn
Date: 2007-09-29 23:19:31 -0500 (Sat, 29 Sep 2007)
New Revision: 6439
Modified:
django/branches/gis/django/contrib/gis/db/backend/__init__.py
django/branches/gis/django/contrib/gis/db/backend/postgis/__init__.py
django/branches/gis/django/contrib/gis/db/backend/postgis/creation.py
django/branches/gis/django/contrib/gis/db/backend/postgis/field.py
django/branches/gis/django/contrib/gis/db/backend/postgis/management.py
django/branches/gis/django/contrib/gis/db/backend/postgis/query.py
Log:
gis: PostGIS backend improvements: test spatial databases may now be created on
NT platforms; changed exception style.
Modified: django/branches/gis/django/contrib/gis/db/backend/__init__.py
===================================================================
--- django/branches/gis/django/contrib/gis/db/backend/__init__.py
2007-09-30 04:11:29 UTC (rev 6438)
+++ django/branches/gis/django/contrib/gis/db/backend/__init__.py
2007-09-30 04:19:31 UTC (rev 6439)
@@ -8,8 +8,8 @@
(2) The parse_lookup() function, used for spatial SQL construction by
the GeoQuerySet.
- Currently only PostGIS is supported, but someday backends will be aded for
- additional spatial databases.
+ Currently only PostGIS is supported, but someday backends will be added for
+ additional spatial databases (e.g., Oracle, DB2).
"""
from django.conf import settings
from django.db import connection
@@ -20,11 +20,11 @@
if settings.DATABASE_ENGINE == 'postgresql_psycopg2':
# PostGIS is the spatial database, getting the rquired modules, renaming
as necessary.
from django.contrib.gis.db.backend.postgis import \
- PostGISField as GeoBackendField, \
- POSTGIS_TERMS as GIS_TERMS, \
- create_spatial_db, geo_quotename, get_geo_where_clause
+ PostGISField as GeoBackendField, POSTGIS_TERMS as GIS_TERMS, \
+ create_spatial_db, geo_quotename, get_geo_where_clause, \
+ ASGML, ASKML, UNION
else:
- raise NotImplementedError, 'No Geographic Backend exists for %s' %
settings.DATABASE_NAME
+ raise NotImplementedError('No Geographic Backend exists for %s' %
settings.DATABASE_NAME)
#### query.py overloaded functions ####
# parse_lookup() and lookup_inner() are modified from their
django/db/models/query.py
Modified: django/branches/gis/django/contrib/gis/db/backend/postgis/__init__.py
===================================================================
--- django/branches/gis/django/contrib/gis/db/backend/postgis/__init__.py
2007-09-30 04:11:29 UTC (rev 6438)
+++ django/branches/gis/django/contrib/gis/db/backend/postgis/__init__.py
2007-09-30 04:19:31 UTC (rev 6439)
@@ -8,11 +8,16 @@
from django.contrib.gis.db.backend.postgis.creation import create_spatial_db
from django.contrib.gis.db.backend.postgis.field import PostGISField
-# Whether PostGIS has AsKML() support.
+# Functions used by GeoManager methods, and not via lookup types.
if MAJOR_VERSION == 1:
- # AsKML() only supported in versions 1.2.1+
if MINOR_VERSION1 == 3:
ASKML = 'ST_AsKML'
+ ASGML = 'ST_AsGML'
+ UNION = 'ST_Union'
elif MINOR_VERSION1 == 2 and MINOR_VERSION2 >= 1:
ASKML = 'AsKML'
+ ASGML = 'AsGML'
+ UNION = 'GeomUnion'
+
+
Modified: django/branches/gis/django/contrib/gis/db/backend/postgis/creation.py
===================================================================
--- django/branches/gis/django/contrib/gis/db/backend/postgis/creation.py
2007-09-30 04:11:29 UTC (rev 6438)
+++ django/branches/gis/django/contrib/gis/db/backend/postgis/creation.py
2007-09-30 04:19:31 UTC (rev 6439)
@@ -2,9 +2,16 @@
from django.core.management import call_command
from django.db import connection
from django.test.utils import _set_autocommit, TEST_DATABASE_PREFIX
-from commands import getstatusoutput
import os, re, sys
+def getstatusoutput(cmd):
+ "A simpler version of getstatusoutput that works on win32 platforms."
+ stdin, stdout, stderr = os.popen3(cmd)
+ output = stdout.read()
+ if output.endswith('\n'): output = output[:-1]
+ status = stdin.close()
+ return status, output
+
def create_lang(db_name, verbosity=1):
"Sets up the pl/pgsql language on the given database."
@@ -20,8 +27,8 @@
status, output = getstatusoutput(createlang_cmd)
# Checking the status of the command, 0 => execution successful
- if status != 0:
- raise Exception, "Error executing 'plpgsql' command: %s\n" % output
+ if status:
+ raise Exception("Error executing 'plpgsql' command: %s\n" % output)
def _create_with_cursor(db_name, verbosity=1, autoclobber=False):
"Creates database with psycopg2 cursor."
@@ -48,7 +55,7 @@
if verbosity >= 1: print 'Creating new spatial database...'
cursor.execute(create_sql)
else:
- raise Exception, 'Spatial Database Creation canceled.'
+ raise Exception('Spatial Database Creation canceled.')
created_regex = re.compile(r'^createdb: database creation failed: ERROR:
database ".+" already exists')
def _create_with_shell(db_name, verbosity=1, autoclobber=False):
@@ -65,7 +72,8 @@
# Attempting to create the database.
status, output = getstatusoutput(create_cmd)
- if status != 0:
+
+ if status:
if created_regex.match(output):
if not autoclobber:
confirm = raw_input("\nIt appears the database, %s, already
exists. Type 'yes' to delete it, or 'no' to cancel: " % db_name)
@@ -74,28 +82,23 @@
drop_cmd = 'dropdb %s%s' % (options, db_name)
status, output = getstatusoutput(drop_cmd)
if status != 0:
- raise Exception, 'Could not drop database %s: %s' %
(db_name, output)
+ raise Exception('Could not drop database %s: %s' %
(db_name, output))
if verbosity >= 1: print 'Creating new spatial database...'
status, output = getstatusoutput(create_cmd)
if status != 0:
- raise Exception, 'Could not create database after
dropping: %s' % output
+ raise Exception('Could not create database after dropping:
%s' % output)
else:
- raise Exception, 'Spatial Database Creation canceled.'
+ raise Exception('Spatial Database Creation canceled.')
else:
- raise Exception, 'Unknown error occurred in creating database: %s'
% output
+ raise Exception('Unknown error occurred in creating database: %s'
% output)
def create_spatial_db(test=False, verbosity=1, autoclobber=False,
interactive=False):
"Creates a spatial database based on the settings."
# Making sure we're using PostgreSQL and psycopg2
if settings.DATABASE_ENGINE != 'postgresql_psycopg2':
- raise Exception, 'Spatial database creation only supported
postgresql_psycopg2 platform.'
+ raise Exception('Spatial database creation only supported
postgresql_psycopg2 platform.')
- # This routine depends on getstatusoutput(), which does not work on
Windows.
- # TODO: Consider executing shell commands with popen for Windows
compatibility
- if os.name == 'nt':
- raise Exception, 'Automatic spatial database creation only supported
on *NIX platforms.'
-
# Getting the spatial database name
if test:
db_name = get_spatial_db(test=True)
@@ -104,8 +107,10 @@
db_name = get_spatial_db()
_create_with_shell(db_name, verbosity=verbosity,
autoclobber=autoclobber)
- # Creating the db language.
- create_lang(db_name, verbosity=verbosity)
+ # Creating the db language, does not need to be done on NT platforms
+ # since the PostGIS installer enables this capability.
+ if os.name != 'nt':
+ create_lang(db_name, verbosity=verbosity)
# Now adding in the PostGIS routines.
load_postgis_sql(db_name, verbosity=verbosity)
@@ -118,19 +123,15 @@
# Syncing the database
call_command('syncdb', verbosity=verbosity, interactive=interactive)
-
- # Get a cursor (even though we don't need one yet). This has
- # the side effect of initializing the test database.
- cursor = connection.cursor()
def drop_db(db_name=False, test=False):
"""
- Drops the given database (defaults to what is returned from
get_spatial_db().
- All exceptions are propagated up to the caller.
+ Drops the given database (defaults to what is returned from
+ get_spatial_db()). All exceptions are propagated up to the caller.
"""
if not db_name: db_name = get_spatial_db(test=test)
cursor = connection.cursor()
- cursor.execute("DROP DATABASE %s" % connection.ops.quote_name(db_name))
+ cursor.execute('DROP DATABASE %s' % connection.ops.quote_name(db_name))
def get_cmd_options(db_name):
"Obtains the command-line PostgreSQL connection options for shell
commands."
@@ -159,7 +160,7 @@
return test_db_name
else:
if not settings.DATABASE_NAME:
- raise Exception, 'must configure DATABASE_NAME in settings.py'
+ raise Exception('must configure DATABASE_NAME in settings.py')
return settings.DATABASE_NAME
def load_postgis_sql(db_name, verbosity=1):
@@ -171,35 +172,51 @@
# Getting the path to the PostGIS SQL
try:
# POSTGIS_SQL_PATH may be placed in settings to tell GeoDjango where
the
- # PostGIS SQL files are located
+ # PostGIS SQL files are located. This is especially useful on Win32
+ # platforms since the output of pg_config looks like "C:/PROGRA~1/..".
sql_path = settings.POSTGIS_SQL_PATH
except AttributeError:
status, sql_path = getstatusoutput('pg_config --sharedir')
- if status != 0:
+ if status:
sql_path = '/usr/local/share'
# The PostGIS SQL post-creation files.
lwpostgis_file = os.path.join(sql_path, 'lwpostgis.sql')
- srefsys_file = os.path.join(sql_path, 'spatial_ref_sys.sql')
+ srefsys_file = os.path.join(sql_path, 'spatial_ref_sys.sql')
if not os.path.isfile(lwpostgis_file):
- raise Exception, 'Could not find PostGIS function definitions in %s' %
lwpostgis_file
+ raise Exception('Could not find PostGIS function definitions in %s' %
lwpostgis_file)
if not os.path.isfile(srefsys_file):
- raise Exception, 'Could not find PostGIS spatial reference system
definitions in %s' % srefsys_file
+ raise Exception('Could not find PostGIS spatial reference system
definitions in %s' % srefsys_file)
- # Getting the psql command-line options.
+ # Getting the psql command-line options, and command format.
options = get_cmd_options(db_name)
+ cmd_fmt = 'psql %s-f "%%s"' % options
# Now trying to load up the PostGIS functions
- cmd = 'psql %s-f %s' % (options, lwpostgis_file)
+ cmd = cmd_fmt % lwpostgis_file
if verbosity >= 1: print cmd
status, output = getstatusoutput(cmd)
- if status != 0:
- raise Exception, 'Error in loading PostGIS lwgeometry routines.'
+ if status:
+ raise Exception('Error in loading PostGIS lwgeometry routines.')
# Now trying to load up the Spatial Reference System table
- cmd = 'psql %s-f %s' % (options, srefsys_file)
+ cmd = cmd_fmt % srefsys_file
if verbosity >= 1: print cmd
status, output = getstatusoutput(cmd)
- if status !=0:
- raise Exception, 'Error in loading PostGIS spatial_ref_sys table.'
+ if status:
+ raise Exception('Error in loading PostGIS spatial_ref_sys table.')
+
+ # Setting the permissions because on Windows platforms the owner
+ # of the spatial_ref_sys and geometry_columns tables is always
+ # the postgres user, regardless of how the db is created.
+ if os.name == 'nt': set_permissions(db_name)
+def set_permissions(db_name):
+ """
+ Sets the permissions on the given database to that of the user specified
+ in the settings. Needed specifically for PostGIS on Win32 platforms.
+ """
+ cursor = connection.cursor()
+ user = settings.DATABASE_USER
+ cursor.execute('ALTER TABLE geometry_columns OWNER TO %s' % user)
+ cursor.execute('ALTER TABLE spatial_ref_sys OWNER TO %s' % user)
Modified: django/branches/gis/django/contrib/gis/db/backend/postgis/field.py
===================================================================
--- django/branches/gis/django/contrib/gis/db/backend/postgis/field.py
2007-09-30 04:11:29 UTC (rev 6438)
+++ django/branches/gis/django/contrib/gis/db/backend/postgis/field.py
2007-09-30 04:19:31 UTC (rev 6439)
@@ -5,7 +5,8 @@
class PostGISField(Field):
def _add_geom(self, style, db_table):
- """Constructs the addition of the geometry to the table using the
+ """
+ Constructs the addition of the geometry to the table using the
AddGeometryColumn(...) PostGIS (and OGC standard) stored procedure.
Takes the style object (provides syntax highlighting) and the
@@ -98,10 +99,14 @@
if isinstance(value, GEOSGeometry):
return value
else:
- return ("SRID=%d;%s" % (self._srid, wkt))
+ raise TypeError('Geometry Proxy should only return GEOSGeometry
objects.')
def get_placeholder(self, value):
- "Provides a proper substitution value for "
+ """
+ Provides a proper substitution value for Geometries that are not in the
+ SRID of the field. Specifically, this routine will substitute in the
+ ST_Transform() function call.
+ """
if isinstance(value, GEOSGeometry) and value.srid != self._srid:
# Adding Transform() to the SQL placeholder.
return 'ST_Transform(%%s, %s)' % self._srid
Modified:
django/branches/gis/django/contrib/gis/db/backend/postgis/management.py
===================================================================
--- django/branches/gis/django/contrib/gis/db/backend/postgis/management.py
2007-09-30 04:11:29 UTC (rev 6438)
+++ django/branches/gis/django/contrib/gis/db/backend/postgis/management.py
2007-09-30 04:19:31 UTC (rev 6439)
@@ -1,5 +1,6 @@
"""
- This utility module is for obtaining information about the PostGIS
installation.
+ This utility module is for obtaining information about the PostGIS
+ installation.
See PostGIS docs at Ch. 6.2.1 for more information on these functions.
"""
@@ -48,9 +49,6 @@
minor1 = int(m.group('minor1'))
minor2 = int(m.group('minor2'))
else:
- raise Exception, 'Could not parse PostGIS version string: %s' % version
+ raise Exception('Could not parse PostGIS version string: %s' % version)
return (version, major, minor1, minor2)
-
-
-
Modified: django/branches/gis/django/contrib/gis/db/backend/postgis/query.py
===================================================================
--- django/branches/gis/django/contrib/gis/db/backend/postgis/query.py
2007-09-30 04:11:29 UTC (rev 6438)
+++ django/branches/gis/django/contrib/gis/db/backend/postgis/query.py
2007-09-30 04:19:31 UTC (rev 6439)
@@ -14,7 +14,7 @@
# TODO: Confirm tests with PostGIS versions 1.1.x -- should work.
# Versions <= 1.0.x do not use GEOS C API, and will not be supported.
if MAJOR_VERSION != 1 or (MAJOR_VERSION == 1 and MINOR_VERSION1 < 1):
- raise Exception, 'PostGIS version %s not supported.' % POSTGIS_VERSION
+ raise Exception('PostGIS version %s not supported.' % POSTGIS_VERSION)
# PostGIS-specific operators. The commented descriptions of these
# operators come from Section 6.2.2 of the official PostGIS documentation.
@@ -145,11 +145,11 @@
# Ensuring that a tuple _value_ was passed in from the user
if not isinstance(value, tuple) or len(value) != 2:
- raise TypeError, '2-element tuple required for %s lookup
type.' % lookup_type
+ raise TypeError('2-element tuple required for %s lookup type.'
% lookup_type)
# Ensuring the argument type matches what we expect.
if not isinstance(value[1], arg_type):
- raise TypeError, 'Argument type should be %s, got %s instead.'
% (arg_type, type(value[1]))
+ raise TypeError('Argument type should be %s, got %s instead.'
% (arg_type, type(value[1])))
return "%s(%s%s, %%s, %%s)" % (func, table_prefix, field_name)
else:
@@ -161,7 +161,7 @@
if lookup_type == 'isnull':
return "%s%s IS %sNULL" % (table_prefix, field_name, (not value and
'NOT ' or ''))
- raise TypeError, "Got invalid lookup_type: %s" % repr(lookup_type)
+ raise TypeError("Got invalid lookup_type: %s" % repr(lookup_type))
def geo_quotename(value, dbl=False):
"Returns the quotation used for PostGIS on a given value (uses single
quotes by default)."
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---