Django

Code

Changeset 6508

Show
Ignore:
Timestamp:
10/14/07 15:13:11 (1 year ago)
Author:
jbronn
Message:

gis: spatial-backend enhancements:

(1) GEOS no longer has psycopg2-specific routines, functionality now part of PostGIS adaptor in the spatial backend.
(2) ST_GeomFromWKB() now used to enhance performance.
(3) Moved GeometryProxy? back to its original location.
(4) Should resolve #5498, but not yet confirmed.
(5) Test-sql files are now backend-specific.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/gis/django/contrib/gis/db/backend/__init__.py

    r6467 r6508  
    1212 (4) The `parse_lookup` function, used for spatial SQL construction by 
    1313     the GeoQuerySet. 
    14  (5) The `create_spatial_db`, `geo_quotename`, and `get_geo_where_clause` 
    15      routines (needed by `parse_lookup`
     14 (5) The `create_spatial_db`, and `get_geo_where_clause` 
     15     routines (needed by `parse_lookup`)
    1616 
    1717 Currently only PostGIS is supported, but someday backends will be added for 
    1818 additional spatial databases (e.g., Oracle, DB2). 
    1919""" 
     20from types import StringType, UnicodeType 
    2021from django.conf import settings 
    2122from django.db import connection 
     
    2324    FieldFound, LOOKUP_SEPARATOR, QUERY_TERMS 
    2425from django.utils.datastructures import SortedDict 
    25  
    26 # These routines default to False 
    27 ASGML, ASKML, UNION = (False, False, False) 
     26from django.contrib.gis.geos import GEOSGeometry 
     27 
     28# These routines (needed by GeoManager), default to False. 
     29ASGML, ASKML, TRANSFORM, UNION= (False, False, False, False) 
    2830 
    2931if settings.DATABASE_ENGINE == 'postgresql_psycopg2': 
     
    3234    from django.contrib.gis.db.backend.postgis import \ 
    3335        PostGISField as GeoBackendField, POSTGIS_TERMS as GIS_TERMS, \ 
    34         PostGISProxy as GeometryProxy, \ 
    35         create_spatial_db, geo_quotename, get_geo_where_clause, \ 
    36         ASGML, ASKML, UNION 
     36        create_spatial_db, get_geo_where_clause, gqn, \ 
     37        ASGML, ASKML, GEOM_SELECT, TRANSFORM, UNION 
    3738else: 
    3839    raise NotImplementedError('No Geographic Backend exists for %s' % settings.DATABASE_NAME) 
     40 
     41def geo_quotename(value): 
     42    """ 
     43    Returns the quotation used on a given Geometry value using the geometry 
     44    quoting from the backend (the `gqn` function). 
     45    """ 
     46    if isinstance(value, (StringType, UnicodeType)): return gqn(value) 
     47    else: return str(value) 
    3948 
    4049####    query.py overloaded functions    #### 
     
    264273        # with the get_geo_where_clause() 
    265274        if hasattr(field, '_geom'): 
    266             # Do we have multiple arguments, e.g., ST_Relate, ST_DWithin lookup types 
    267             # need more than argument. 
     275            # Do we have multiple arguments, e.g., `relate`, `dwithin` lookup types 
     276            # need more than argument. 
    268277            multiple_args = isinstance(value, tuple) 
    269278 
    270             # Getting the geographic where clause. 
     279            # Getting the preparation SQL object from the field. 
     280            if multiple_args: 
     281                geo_prep = field.get_db_prep_lookup(lookup_type, value[0]) 
     282            else: 
     283                geo_prep = field.get_db_prep_lookup(lookup_type, value) 
     284 
     285            # Getting the adapted geometry from the field. 
    271286            gwc = get_geo_where_clause(lookup_type, current_table + '.', column, value) 
    272  
    273             # Getting the geographic parameters from the field. 
    274             if multiple_args: 
    275                 geo_params = field.get_db_prep_lookup(lookup_type, value[0]) 
    276             else: 
    277                 geo_params = field.get_db_prep_lookup(lookup_type, value) 
    278       
    279             # If a dictionary was passed back from the field modify the where clause. 
    280             param_dict = isinstance(geo_params, dict) 
    281             if param_dict: 
    282                 subst_list = geo_params['where'] 
    283                 if multiple_args: subst_list += map(geo_quotename, value[1:]) 
    284                 geo_params = geo_params['params']   
    285                 gwc = gwc % tuple(subst_list) 
    286             elif multiple_args: 
    287                 # Modify the where clause if we have multiple arguments -- the  
    288                 #  first substitution will be for another placeholder (for the  
    289                 #  geometry) since it is already apart of geo_params. 
    290                 subst_list = ['%s'] 
    291                 subst_list += map(geo_quotename, value[1:]) 
    292                 gwc = gwc % tuple(subst_list) 
    293                  
    294             # Finally, appending onto the WHERE clause, and extending with any  
    295             #  additional parameters. 
     287             
     288            # A GeoFieldSQL object is returned by `get_db_prep_lookup` --  
     289            # getting the substitution list and the geographic parameters. 
     290            subst_list = geo_prep.where 
     291            if multiple_args: subst_list += map(geo_quotename, value[1:]) 
     292            gwc = gwc % tuple(subst_list) 
     293             
     294            # Finally, appending onto the WHERE clause, and extending with 
     295            # the additional parameters. 
    296296            where.append(gwc) 
    297             params.extend(geo_params) 
     297            params.extend(geo_prep.params) 
    298298        else: 
    299299            where.append(get_where_clause(lookup_type, current_table + '.', column, value, db_type)) 
  • django/branches/gis/django/contrib/gis/db/backend/postgis/field.py

    r6467 r6508  
     1from types import StringType, UnicodeType 
     2from django.db import connection 
    13from django.db.models.fields import Field # Django base Field class 
    24from django.contrib.gis.geos import GEOSGeometry, GEOSException  
    3 from django.contrib.gis.db.backend.postgis.query import POSTGIS_TERMS, geo_quotename as quotename 
    4 from types import StringType 
     5from django.contrib.gis.db.backend.util import GeoFieldSQL 
     6from django.contrib.gis.db.backend.postgis.adaptor import PostGISAdaptor 
     7from django.contrib.gis.db.backend.postgis.query import POSTGIS_TERMS, TRANSFORM 
     8from psycopg2 import Binary 
     9 
     10# Quotename & geographic quotename, respectively 
     11qn = connection.ops.quote_name 
     12def gqn(value): 
     13    if isinstance(value, UnicodeType): value = value.encode('ascii') 
     14    return "'%s'" % value 
    515 
    616class PostGISField(Field): 
     
    1121 
    1222        Takes the style object (provides syntax highlighting) and the 
    13         database table as parameters. 
     23        database table as parameters. 
    1424        """ 
    1525        sql = style.SQL_KEYWORD('SELECT ') + \ 
    1626              style.SQL_TABLE('AddGeometryColumn') + '(' + \ 
    17               style.SQL_TABLE(quotename(db_table)) + ', ' + \ 
    18               style.SQL_FIELD(quotename(self.column)) + ', ' + \ 
     27              style.SQL_TABLE(gqn(db_table)) + ', ' + \ 
     28              style.SQL_FIELD(gqn(self.column)) + ', ' + \ 
    1929              style.SQL_FIELD(str(self._srid)) + ', ' + \ 
    20               style.SQL_COLTYPE(quotename(self._geom)) + ', ' + \ 
     30              style.SQL_COLTYPE(gqn(self._geom)) + ', ' + \ 
    2131              style.SQL_KEYWORD(str(self._dim)) + ');' 
    2232 
     
    2535            sql += '\n' + \ 
    2636                   style.SQL_KEYWORD('ALTER TABLE ') + \ 
    27                    style.SQL_TABLE(quotename(db_table, dbl=True)) + \ 
     37                   style.SQL_TABLE(qn(db_table)) + \ 
    2838                   style.SQL_KEYWORD(' ALTER ') + \ 
    29                    style.SQL_FIELD(quotename(self.column, dbl=True)) + \ 
     39                   style.SQL_FIELD(qn(self.column)) + \ 
    3040                   style.SQL_KEYWORD(' SET NOT NULL') + ';' 
    3141        return sql 
     
    3545        "Creates a GiST index for this geometry field." 
    3646        sql = style.SQL_KEYWORD('CREATE INDEX ') + \ 
    37               style.SQL_TABLE(quotename('%s_%s_id' % (db_table, self.column), dbl=True)) + \ 
     47              style.SQL_TABLE(qn('%s_%s_id' % (db_table, self.column))) + \ 
    3848              style.SQL_KEYWORD(' ON ') + \ 
    39               style.SQL_TABLE(quotename(db_table, dbl=True)) + \ 
     49              style.SQL_TABLE(qn(db_table)) + \ 
    4050              style.SQL_KEYWORD(' USING ') + \ 
    4151              style.SQL_COLTYPE(index_type) + ' ( ' + \ 
    42               style.SQL_FIELD(quotename(self.column, dbl=True)) + ' ' + \ 
     52              style.SQL_FIELD(qn(self.column)) + ' ' + \ 
    4353              style.SQL_KEYWORD(index_opts) + ' );' 
    4454        return sql 
     
    6575        sql = style.SQL_KEYWORD('SELECT ') + \ 
    6676            style.SQL_KEYWORD('DropGeometryColumn') + '(' + \ 
    67             style.SQL_TABLE(quotename(db_table)) + ', ' + \ 
    68             style.SQL_FIELD(quotename(self.column)) +  ');' 
     77            style.SQL_TABLE(gqn(db_table)) + ', ' + \ 
     78            style.SQL_FIELD(gqn(self.column)) +  ');' 
    6979        return sql 
    7080 
     
    8292        """ 
    8393        if lookup_type in POSTGIS_TERMS: 
    84             if lookup_type == 'isnull': return [value] # special case for NULL geometries. 
    85             if not bool(value): return [None] # If invalid value passed in. 
     94            # special case for isnull lookup 
     95            if lookup_type == 'isnull': 
     96                return GeoFieldSQL([], [value]) 
     97 
     98            # When the input is not a GEOS geometry, attempt to construct one 
     99            # from the given string input. 
    86100            if isinstance(value, GEOSGeometry): 
    87                 # GEOSGeometry instance passed in. 
    88                 if value.srid != self._srid: 
    89                     # Returning a dictionary instructs the parse_lookup() to add  
    90                     # what's in the 'where' key to the where parameters, since we  
    91                     # need to transform the geometry in the query. 
    92                     return {'where' : ["ST_Transform(%s,%s)"], 
    93                             'params' : [value, self._srid] 
    94                             } 
    95                 else: 
    96                     # Just return the GEOSGeometry, it has its own psycopg2 adaptor. 
    97                     return [value] 
    98             elif isinstance(value, StringType): 
    99                 # String instance passed in, assuming WKT. 
    100                 # TODO: Any validation needed here to prevent SQL injection? 
    101                 return ["SRID=%d;%s" % (self._srid, value)] 
     101                pass 
     102            elif isinstance(value, (StringType, UnicodeType)): 
     103                try: 
     104                    value = GEOSGeometry(value) 
     105                except GEOSException: 
     106                    raise TypeError("Could not create geometry from lookup value: %s" % str(value)) 
    102107            else: 
    103                 raise TypeError("Invalid type (%s) used for field lookup value." % str(type(value))) 
     108                raise TypeError('Cannot use parameter of %s type as lookup parameter.' % type(value)) 
     109 
     110            # Getting the SRID of the geometry, or defaulting to that of the field if 
     111            # it is None. 
     112            if value.srid is None: srid = self._srid 
     113            else: srid = value.srid 
     114 
     115            # The adaptor will be used by psycopg2 for quoting the WKB. 
     116            adapt = PostGISAdaptor(value, srid) 
     117 
     118            if srid != self._srid: 
     119                # Adding the necessary string substitutions and parameters 
     120                # to perform a geometry transformation. 
     121                return GeoFieldSQL(['%s(%%s,%%s)' % TRANSFORM], 
     122                                       [adapt, self._srid]) 
     123            else: 
     124                return GeoFieldSQL(['%s'], [adapt]) 
    104125        else: 
    105126            raise TypeError("Field has invalid lookup: %s" % lookup_type) 
     
    109130        if not bool(value): return None 
    110131        if isinstance(value, GEOSGeometry): 
    111             return value 
     132            return PostGISAdaptor(value, value.srid) 
    112133        else: 
    113134            raise TypeError('Geometry Proxy should only return GEOSGeometry objects.') 
     
    115136    def get_internal_type(self): 
    116137        """ 
    117         Returns NoField because a stored procedure is used by PostGIS to create the 
     138        Returns NoField because a stored procedure is used by PostGIS to create 
     139        the Geometry Fields. 
    118140        """ 
    119141        return 'NoField' 
     
    122144        """ 
    123145        Provides a proper substitution value for Geometries that are not in the 
    124         SRID of the field.  Specifically, this routine will substitute in the 
    125         ST_Transform() function call. 
     146        SRID of the field.  Specifically, this routine will substitute in the 
     147        ST_Transform() function call. 
    126148        """ 
    127149        if isinstance(value, GEOSGeometry) and value.srid != self._srid: 
    128150            # Adding Transform() to the SQL placeholder. 
    129             return 'ST_Transform(%%s, %s)' % self._srid 
     151            return '%s(%%s, %s)' % (TRANSFORM, self._srid) 
    130152        else: 
    131153            return '%s' 
  • django/branches/gis/django/contrib/gis/db/backend/postgis/__init__.py

    r6467 r6508  
    22 The PostGIS spatial database backend module. 
    33""" 
     4from django.contrib.gis.db.backend.postgis.creation import create_spatial_db 
     5from django.contrib.gis.db.backend.postgis.field import PostGISField, gqn 
     6from django.contrib.gis.db.backend.postgis.proxy import PostGISProxy 
    47from django.contrib.gis.db.backend.postgis.query import \ 
    5     get_geo_where_clause, geo_quotename, \ 
    6     GEOM_FUNC_PREFIX, POSTGIS_TERMS, \ 
    7     MAJOR_VERSION, MINOR_VERSION1, MINOR_VERSION2 
    8 from django.contrib.gis.db.backend.postgis.creation import create_spatial_db 
    9 from django.contrib.gis.db.backend.postgis.field import PostGISField 
    10 from django.contrib.gis.db.backend.postgis.proxy import PostGISProxy 
    11  
    12 # Functions used by GeoManager methods, and not via lookup types. 
    13 if MAJOR_VERSION == 1: 
    14     if MINOR_VERSION1 == 3: 
    15         ASKML = 'ST_AsKML' 
    16         ASGML = 'ST_AsGML' 
    17         UNION = 'ST_Union' 
    18     elif MINOR_VERSION1 == 2 and MINOR_VERSION2 >= 1: 
    19         ASKML = 'AsKML' 
    20         ASGML = 'AsGML' 
    21         UNION = 'GeomUnion' 
    22          
    23  
    24      
     8    get_geo_where_clause, GEOM_FUNC_PREFIX, POSTGIS_TERMS, \ 
     9    MAJOR_VERSION, MINOR_VERSION1, MINOR_VERSION2, \ 
     10    ASKML, ASGML, GEOM_FROM_TEXT, UNION, TRANSFORM, GEOM_SELECT 
  • django/branches/gis/django/contrib/gis/db/backend/postgis/query.py

    r6439 r6508  
    11""" 
    2   This module contains the spatial lookup types, and the get_geo_where_clause() 
    3   routine for PostGIS. 
     2 This module contains the spatial lookup types, and the get_geo_where_clause() 
     3 routine for PostGIS. 
    44""" 
    55from django.db import connection 
    66from django.contrib.gis.db.backend.postgis.management import postgis_version_tuple 
    77from types import StringType, UnicodeType 
    8 quote_name = connection.ops.quote_name 
     8qn = connection.ops.quote_name 
    99 
    1010# Getting the PostGIS version information 
     
    122122    "Returns the SQL WHERE clause for use in PostGIS SQL construction." 
    123123    if table_prefix.endswith('.'): 
    124         table_prefix = quote_name(table_prefix[:-1])+'.' 
    125     field_name = quote_name(field_name) 
     124        table_prefix = qn(table_prefix[:-1])+'.' 
     125    field_name = qn(field_name) 
    126126 
    127127    # See if a PostGIS operator matches the lookup type first 
    128     try
     128    if lookup_type in POSTGIS_OPERATORS
    129129        return '%s%s %s %%s' % (table_prefix, field_name, POSTGIS_OPERATORS[lookup_type]) 
    130     except KeyError: 
    131         pass 
    132130 
    133131    # See if a PostGIS Geometry function matches the lookup type next 
    134     try
     132    if lookup_type in POSTGIS_GEOMETRY_FUNCTIONS
    135133        lookup_info = POSTGIS_GEOMETRY_FUNCTIONS[lookup_type] 
    136     except KeyError: 
    137         pass 
    138     else: 
    139134        # Lookup types that are tuples take tuple arguments, e.g., 'relate' and  
    140135        #  'dwithin' lookup types. 
     
    146141            # Ensuring that a tuple _value_ was passed in from the user 
    147142            if not isinstance(value, tuple) or len(value) != 2:  
    148                 raise TypeError('2-element tuple required for %s lookup type.' % lookup_type) 
     143                raise TypeError('2-element tuple required for `%s` lookup type.' % lookup_type) 
    149144             
    150145            # Ensuring the argument type matches what we expect. 
     
    155150        else: 
    156151            # Returning the SQL necessary for the geometry function call. For example:  
    157             #  ST_Contains("geoapp_country"."poly", ST_GeomFromText(..)) 
     152            #  ST_Contains("geoapp_country"."poly", ST_GeomFromWKB(..)) 
    158153            return '%s(%s%s, %%s)' % (lookup_info, table_prefix, field_name) 
    159154     
     
    164159    raise TypeError("Got invalid lookup_type: %s" % repr(lookup_type)) 
    165160 
    166 def geo_quotename(value, dbl=False): 
    167     "Returns the quotation used for PostGIS on a given value (uses single quotes by default)." 
    168     if isinstance(value, (StringType, UnicodeType)): 
    169         if dbl: return '"%s"' % value 
    170         else: return "'%s'" % value 
    171     else: 
    172         return str(value) 
     161# Functions that we define manually. 
     162if MAJOR_VERSION == 1: 
     163    if MINOR_VERSION1 == 3: 
     164        # PostGIS versions 1.3.x 
     165        ASKML = 'ST_AsKML' 
     166        ASGML = 'ST_AsGML' 
     167        GEOM_FROM_TEXT = 'ST_GeomFromText' 
     168        GEOM_FROM_WKB = 'ST_GeomFromWKB' 
     169        UNION = 'ST_Union' 
     170        TRANSFORM = 'ST_Transform' 
     171    elif MINOR_VERSION1 == 2 and MINOR_VERSION2 >= 1: 
     172        # PostGIS versions 1.2.x 
     173        ASKML = 'AsKML' 
     174        ASGML = 'AsGML' 
     175        GEOM_FROM_TEXT = 'GeomFromText' 
     176        GEOM_FROM_WKB = 'GeomFromWKB' 
     177        UNION = 'GeomUnion' 
     178        TRANSFORM = 'Transform' 
     179    elif MINOR_VERSION1 == 1 and MINOR_VERSION2 >= 0: 
     180        # PostGIS versions 1.1.x 
     181        ASKML = False 
     182        ASGML = 'AsGML' 
     183        GEOM_FROM_TEXT = 'GeomFromText' 
     184        GEOM_FROM_WKB = 'GeomFromWKB' 
     185        TRANSFORM = 'Transform' 
     186        UNION = 'GeomUnion' 
     187 
     188# Custom selection not needed for PostGIS since GEOS geometries may be 
     189# instantiated directly from the HEXEWKB returned by default.  If 
     190# WKT is needed for some reason in the future, this value may be changed, 
     191# 'AsText(%s)' 
     192GEOM_SELECT = None 
  • django/branches/gis/django/contrib/gis/db/models/fields/__init__.py

    r6467 r6508  
    11from django.conf import settings 
    2 from django.contrib.gis.db.backend import GeoBackendField, GeometryProxy # these depend on the spatial database backend. 
     2from django.contrib.gis.db.backend import GeoBackendField # these depend on the spatial database backend. 
     3from django.contrib.gis.db.models.proxy import GeometryProxy 
    34from django.contrib.gis.oldforms import WKTField 
    45from django.contrib.gis.geos import GEOSGeometry 
  • django/branches/gis/django/contrib/gis/db/models/__init__.py

    r5657 r6508  
    88from django.contrib.gis.db.models.query import GeoQ 
    99 
    10 # The various PostGIS/OpenGIS enabled fields. 
     10# The geographic-enabled fields. 
    1111from django.contrib.gis.db.models.fields import \ 
    1212     GeometryField, PointField, LineStringField, PolygonField, \ 
  • django/branches/gis/django/contrib/gis/db/models/proxy.py

    r6467 r6508  
    99from types import NoneType, StringType, UnicodeType 
    1010 
    11 class PostGISProxy(object):  
     11class GeometryProxy(object):  
    1212    def __init__(self, klass, field):  
    1313        """ 
  • django/branches/gis/django/contrib/gis/db/models/query.py

    r6441 r6508  
    77from django.contrib.gis.db.models.fields import GeometryField 
    88# parse_lookup depends on the spatial database backend. 
    9 from django.contrib.gis.db.backend import parse_lookup, ASGML, ASKML, UNION 
     9from django.contrib.gis.db.backend import parse_lookup, ASGML, ASKML, GEOM_SELECT, TRANSFORM, UNION 
    1010from django.contrib.gis.geos import GEOSGeometry 
    1111 
     
    2929        # For replacement fields in the SELECT. 
    3030        self._custom_select = {} 
     31 
     32        # If GEOM_SELECT is defined in the backend, then it will be used 
     33        # for the selection format of the geometry column. 
     34        if GEOM_SELECT: self._geo_fmt = GEOM_SELECT 
     35        else: self._geo_fmt = '%s' 
    3136 
    3237    def _filter_or_exclude(self, mapper, *args, **kwargs): 
     
    5863        #  in the SELECT, overriding their values -- this is different from using  
    5964        #  QuerySet.extra(select=foo) because extra() adds an  an _additional_  
    60         #  field to be selected.  Used in returning transformed geometries. 
     65        #  field to be selected.  Used in returning transformed geometries, and 
     66        #  handling the selection of native database geometry formats. 
    6167        for f in opts.fields: 
    62             if f.column in self._custom_select: select.append(self._custom_select[f.column]) 
    63             else: select.append(self._field_column(f)) 
     68            # Getting the selection format string. 
     69            if hasattr(f, '_geom'): sel_fmt = self._geo_fmt 
     70            else: sel_fmt = '%s' 
     71                 
     72            # Getting the field selection substitution string 
     73            if f.column in self._custom_select: 
     74                fld_sel = self._custom_select[f.column] 
     75            else: 
     76                fld_sel = self._field_column(f) 
     77 
     78            # Appending the selection  
     79            select.append(sel_fmt % fld_sel) 
    6480 
    6581        tables = [quote_only_if_word(t) for t in self._tables] 
     
    205221        field = self.model._meta.get_field(field_name) 
    206222        if not isinstance(field, GeometryField): 
    207             raise TypeError('ST_Transform() only available for GeometryFields') 
     223            raise TypeError('%s() only available for GeometryFields' % TRANSFORM) 
     224 
     225        # If there's already custom select SQL. 
     226        col = self._custom_select.get(field.column, self._field_column(field)) 
    208227 
    209228        # Setting the key for the field's column with the custom SELECT SQL to  
    210229        #  override the geometry column returned from the database. 
    211230        self._custom_select[field.column] = \ 
    212             '(ST_Transform(%s, %s)) AS %s' % (self._field_column(field), srid,  
    213                                               connection.ops.quote_name(field.column)) 
     231            '(%s(%s, %s)) AS %s' % (TRANSFORM, col, srid, 
     232                                    connection.ops.quote_name(field.column)) 
    214233        return self._clone() 
    215234 
  • django/branches/gis/django/contrib/gis/geos/base.py

    r6465 r6508  
    1313from django.contrib.gis.geos.coordseq import GEOSCoordSeq, create_cs 
    1414from django.contrib.gis.geos.error import GEOSException, GEOSGeometryIndexError 
    15 from django.contrib.gis.geos.libgeos import lgeos, HAS_NUMPY, ISQLQuote 
     15from django.contrib.gis.geos.libgeos import lgeos, HAS_NUMPY 
    1616from django.contrib.gis.geos.pointer import GEOSPointer, NULL_GEOM 
    1717 
     
    4848        The `srid` keyword is used to specify the Source Reference Identifier 
    4949         (SRID) number for this Geometry.  If not set, the SRID will be None. 
    50         """ 
    51  
     50        """  
     51        from_hex = False 
    5252        if isinstance(geo_input, UnicodeType): 
    5353            # Encoding to ASCII, WKT or HEXEWKB doesn't need any more. 
     
    5656            if hex_regex.match(geo_input): 
    5757                # If the regex matches, the geometry is in HEX form. 
     58                from_hex = True 
    5859                sz = c_size_t(len(geo_input)) 
    5960                buf = create_string_buffer(geo_input) 
     
    6364                g = lgeos.GEOSGeomFromWKT(c_char_p(geo_input)) 
    6465            else: 
    65                 raise GEOSException, 'given string input "%s" unrecognized as WKT or HEXEWKB.' % geo_input 
     66                raise GEOSException('String or unicode input unrecognized as WKT or HEXEWKB.') 
    6667        elif isinstance(geo_input, (IntType, GEOSPointer)): 
    6768            # When the input is either a memory address (an integer), or a  
     
    8687        if srid and isinstance(srid, int): self.srid = srid 
    8788 
     89        # Exported HEX from other GEOS geometries will have -1 SRID --  
     90        # set here to 0, when the SRID is not explicitly given. 
     91        if not srid and from_hex: self.srid = 0 
     92 
    8893        # Setting the class type (e.g., 'Point', 'Polygon', etc.) 
    8994        self.__class__ = GEOS_CLASSES[self.geom_type] 
     
    208213        if isinstance(self, (Polygon, GeometryCollection)): self._populate() 
    209214 
    210     #### Psycopg2 database adaptor routines #### 
    211     def __conform__(self, proto): 
    212         # Does the given protocol conform to what Psycopg2 expects? 
    213         if proto == ISQLQuote:  
    214             return self 
    215         else: 
    216             raise GEOSException, 'Error implementing psycopg2 protocol. Is psycopg2 installed?' 
    217  
    218     def getquoted(self): 
    219         "Returns a properly quoted string for use in PostgreSQL/PostGIS." 
    220         # Using ST_GeomFromText(), corresponds to SQL/MM ISO standard. 
    221         return "ST_GeomFromText('%s', %s)" % (self.wkt, self.srid or -1) 
    222      
    223215    #### Coordinate Sequence Routines #### 
    224216    @property 
     
    426418    @property 
    427419    def hex(self): 
    428         "Returns the HEXEWKB of the Geometry." 
     420        """ 
     421        Returns the HEX of the Geometry -- please note that the SRID is not 
     422        included in this representation, because the GEOS C library uses 
     423        -1 by default, even if the SRID is set. 
     424        """ 
    429425        sz = c_size_t() 
    430426        h = lgeos.GEOSGeomToHEX_buf(self._ptr(), byref(sz)) 
  • django/branches/gis/django/contrib/gis/geos/libgeos.py

    r6314 r6508  
    1818except ImportError: 
    1919    HAS_NUMPY = False 
    20  
    21 # Is psycopg2 available? 
    22 try: 
    23     from psycopg2.extensions import ISQLQuote 
    24 except (ImportError, EnvironmentError): 
    25     ISQLQuote = None 
    2620 
    2721# Setting the appropriate name for the GEOS-C library, depending on which