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
-~----------~----~----~----~------~----~------~--~---

Reply via email to