Changeset 903

Show
Ignore:
Timestamp:
01/25/12 17:57:40 (16 months ago)
Author:
jjr8
Message:

* Incremented build number
* Continuing work on SpatiaLite? support
* Added OSU mesoscale eddies class

Location:
MGET/Branches/Jason/PythonPackage/src/GeoEco
Files:
3 added
7 modified

Legend:

Unmodified
Added
Removed
  • MGET/Branches/Jason/PythonPackage/src/GeoEco/AggregatedModules/pyspatialite/dbapi2.py

    r894 r903  
    6161 
    6262    def convert_date(val): 
    63         return datetime.date(*map(int, val.split("-"))) 
     63        return datetime.date(*map(int, val.split(" ")[0].split("-"))) 
    6464 
    6565    def convert_timestamp(val): 
  • MGET/Branches/Jason/PythonPackage/src/GeoEco/Datasets/ArcGIS.py

    r895 r903  
    2323 
    2424from GeoEco.ArcGIS import GeoprocessorManager 
    25 from GeoEco.Datasets import CollectibleObject, Dataset, DatasetCollection, QueryableAttribute, Grid, Table, Field, SelectCursor, UpdateCursor, InsertCursor 
     25from GeoEco.Datasets import CollectibleObject, Dataset, DatasetCollection, QueryableAttribute, Grid, Database, Table, Field, SelectCursor, UpdateCursor, InsertCursor 
    2626from GeoEco.Datasets.Collections import DatasetCollectionTree 
    2727from GeoEco.Datasets.GDAL import GDALDataset, GDALRasterBand 
     
    377377 
    378378 
    379 class ArcGISWorkspace(DatasetCollectionTree): 
     379class ArcGISWorkspace(DatasetCollectionTree, Database): 
    380380    __doc__ = DynamicDocString() 
    381381 
     
    435435    def _GetDisplayName(self): 
    436436        return self._DisplayName 
     437 
     438    @classmethod 
     439    def _TestCapability(cls, capability): 
     440        if capability in ['createtable', 'deletetable']: 
     441            return None 
     442 
     443        capList = capability.split(' ', 2) 
     444        if len(capList) == 3 and capList[0] == 'geometrytype': 
     445            if capList[1] in ['point', 'point25d', 'linestring', 'linestring25d', 'polygon', 'polygon25d', 'multipoint', 'multipoint25d', 'multilinestring', 'multilinestring25d', 'multipolygon', 'multipolygon25d']: 
     446                return None 
     447            return RuntimeError(_(u'Cannot create table %(table)s with "%(geom)s" geometry in %(dn)s. ArcGIS does not support that geometry type.') % {u'tableName': capList[2], u'geom': capList[1], u'dn': cls._DisplayName}) 
     448         
     449        if isinstance(cls, ArcGISWorkspace): 
     450            return RuntimeError(_(u'The %(cls)s class does not support the "%(cap)s" capability.') % {u'cls': cls.__class__.__name__, u'cap': capability}) 
     451        return RuntimeError(_(u'The %(cls)s class does not support the "%(cap)s" capability.') % {u'cls': cls.__name__, u'cap': capability}) 
    437452 
    438453    def _ListContents(self, pathComponents): 
     
    601616    def _ImportDatasetsToPath(self, pathComponents, sourceDatasets, mode, progressReporter, options): 
    602617        self.DatasetType._ImportDatasetsToPath(os.path.join(self.Path, *pathComponents), sourceDatasets, mode, progressReporter, options) 
     618 
     619    # Overridden methods of Database 
     620 
     621    def ImportTable(self, destTableName, sourceTable, fields=None, where=None, orderBy=None, rowCount=None, reportProgress=True, rowDescriptionSingular=None, rowDescriptionPlural=None, copiedOIDFieldName=None, allowSafeCoercions=True): 
     622 
     623        # First call the base class method to actually do the import. 
     624 
     625        table = super(ArcGISWorkspace, self).ImportTable(destTableName, sourceTable, fields, where, orderBy, rowCount, reportProgress, rowDescriptionSingular, rowDescriptionPlural, copiedOIDFieldName, allowSafeCoercions) 
     626 
     627        # Now, if the resulting table has a geometry column, check 
     628        # whether it has a spatial index. If not, create one. We do 
     629        # this specifically because I have noticed that sometimes for 
     630        # shapefiles, ArcGIS appears to discard the spatial index that 
     631        # was requested in the call to CreateFeatureClass_management. 
     632        # I have not determined whether it is caused by subsequently 
     633        # adding fields, by adding records, or what. 
     634 
     635        if table.GeometryType is not None: 
     636            gp = GeoprocessorManager.GetWrappedGeoprocessor() 
     637            d = gp.Describe(table._GetFullPath()) 
     638 
     639            if hasattr(d, 'HasSpatialIndex') and not d.HasSpatialIndex: 
     640                if reportProgress: 
     641                    self._LogInfo(_(u'Adding a spatial index to %(dn)s.') % {u'dn': table.DisplayName}) 
     642                else: 
     643                    self._LogDebug(_(u'Adding a spatial index to %(dn)s.') % {u'dn': table.DisplayName}) 
     644                     
     645                gp.AddSpatialIndex(table._GetFullPath(), 0, 0, 0) 
     646 
     647        # Return successfully. 
     648 
     649        return table 
     650 
     651    def _TableExists(self, tableName): 
     652        gp = GeoprocessorManager.GetWrappedGeoprocessor() 
     653        return gp.Exists(os.path.join(self._Path, tableName)) 
     654 
     655    def _CreateTable(self, tableName, geometryType, spatialReference, geometryFieldName): 
     656 
     657        # If the caller did not specify a geometryType, create a 
     658        # regular table. 
     659 
     660        gp = GeoprocessorManager.GetWrappedGeoprocessor() 
     661        if geometryType is None: 
     662            gp.CreateTable_management(self._Path, tableName) 
     663 
     664        # Otherwise create a feature class. 
     665 
     666        else: 
     667            geometryType = geometryType.upper() 
     668 
     669            hasZ = {False: 'DISABLED', True: 'ENABLED'}[geometryType[-3:] == u'25D'] 
     670             
     671            if geometryType in [u'POINT', u'POINT25D']: 
     672                geometryType = u'POINT' 
     673            elif geometryType in [u'MULTIPOINT', u'MULTIPOINT25D']: 
     674                geometryType = u'MULTIPOINT' 
     675            elif geometryType in [u'LINESTRING', u'MULTILINESTRING', u'LINESTRING25D', u'MULTILINESTRING25D']: 
     676                geometryType = u'POLYLINE' 
     677            elif geometryType in [u'POLYGON', u'MULTIPOLYGON', u'POLYGON25D', u'MULTIPOLYGON25D']: 
     678                geometryType = u'POLYGON' 
     679 
     680            srString = Dataset.ConvertSpatialReference('Obj', spatialReference, 'ArcGIS') 
     681 
     682            gp.CreateFeatureClass_management(self._Path, tableName, geometryType, None, 'DISABLED', hasZ, srString, None, 0, 0, 0) 
     683 
     684        # Return an ArcGISTable instance for the new table. 
     685 
     686        return ArcGISTable(os.path.join(self._Path, tableName)) 
     687 
     688    def _DeleteTable(self, tableName): 
     689        gp = GeoprocessorManager.GetWrappedGeoprocessor() 
     690        return gp.Delete_management(os.path.join(self._Path, tableName)) 
    603691     
    604692 
     
    15351623 
    15361624 
    1537 class ArcGISTable(Table): 
     1625class ArcGISTable(Table, ArcGISCopyableTable): 
    15381626    __doc__ = DynamicDocString() 
    15391627  
     
    17921880        GeoprocessorManager.GetWrappedGeoprocessor().DefineProjection_management(self._GetFullPath(), sr) 
    17931881 
     1882    def GetArcGISCopyablePath(self): 
     1883        return self._GetFullPath() 
     1884 
    17941885    def _AddField(self, name, dataType, length, precision, isNullable): 
    17951886        if dataType == 'int16': 
     
    18661957            raise ValueError(_(u'Cannot import %(count)i datasets into ArcGIS table or feature class "%(path)s". Importing of multiple datasets into a single table or feature class is not currently supported. If you are receiving this error from a tool that has a parameter that is a list of expressions that define the output dataset namen, you may have made a mistake in your expressions that caused the same output dataset name to be generated for multiple input datasets. If that is the problem, you can fix it by modifying the expressions to generate a unique output dataset name for each input dataset.') % {u'count': len(sourceDatasets), u'path': path}) 
    18671958 
    1868         # Validate that the source dataset is importable. 
    1869         # 
    1870         # TODO: Implement support for Table instances that are not 
    1871         # ArcGISCopyableTable instances. (That is a lot of work 
    1872         # because we have to create the destination table and its 
    1873         # fields and then copy each row one at a time.) 
    1874          
    1875         if not isinstance(sourceDatasets[0], ArcGISCopyableTable): 
    1876             raise TypeError(_(u'Cannot import %(dn)s into ArcGIS table or feature class "%(path)s" because it is a %(type)s, which is not an ArcGISCopyableTable. At this time, only ArcGISCopyableTable can be imported.') % {u'dn': sourceDatasets[0].DisplayName, u'path': path, u'type': dataset.__class__.__name__}) 
    1877  
    18781959        # If the mode is 'replace' and the destination dataset exists, 
    18791960        # delete it. 
     
    19652046                raise NotImplementedError(_(u'Cannot import %(dn)s into destination ArcGIS table or feature class "%(path)s" because that destination is not a folder, personal geodatabase, or file geodatabase. Other destinations (e.g. ArcSDE geodatabases) are not fully supported. Please contact the author of this tool for assistance.') % {u'dn': sourceDatasets[0].DisplayName, u'path': path}) 
    19662047 
    1967         # Import the dataset. 
     2048        # At this point, the parent workspace of the destination 
     2049        # dataset exists, and the destination dataset does not exist. 
     2050        # If the source dataset is copyable with ArcGIS's 
     2051        # Copy_management tool, use it because it will be much faster 
     2052        # than manually copying each row. 
    19682053 
    19692054        if isinstance(sourceDatasets[0], ArcGISCopyableTable): 
     
    19742059            finally: 
    19752060                sourceDatasets[0].Close()       # This will make sure it deletes temporary files, if it had to create any in order to make itself ArcGIS-copyable. 
     2061 
     2062        # Otherwise copy the rows manually. This will work with any 
     2063        # Table instance. 
     2064 
     2065        else: 
     2066            workspace = ArcGISWorkspace(os.path.dirname(path), ArcGISTable, pathParsingExpressions=[r'(?P<TableName>.+)'], queryableAttributes=(QueryableAttribute(u'TableName', _(u'Table name'), UnicodeStringTypeMetadata()),)) 
     2067            workspace.ImportTable(os.path.basename(path), sourceDatasets[0], reportProgress=False) 
     2068 
     2069        # Report progress. 
    19762070             
    1977             if progressReporter is not None: 
    1978                 progressReporter.ReportProgress() 
    1979  
    1980         else: 
    1981             raise TypeError(_(u'Cannot import %(dn)s into ArcGIS table or feature class "%(path)s" because it is a %(type)s, which is not an ArcGISCopyableTable. At this time, only ArcGISCopyableTable can be imported.') % {u'dn': sourceDatasets[0].DisplayName, u'path': path, u'type': dataset.__class__.__name__}) 
     2071        if progressReporter is not None: 
     2072            progressReporter.ReportProgress() 
    19822073 
    19832074 
  • MGET/Branches/Jason/PythonPackage/src/GeoEco/Datasets/Collections.py

    r836 r903  
    809809            localPath = None 
    810810 
    811         if localPath is not None and not os.path.splitext(localPath)[1] in [u'.bz2', u'.gz', u'.tar', u'.z', u'.zip'] and os.path.exists(localPath): 
     811        if localPath is not None and os.path.splitext(localPath)[1] not in [u'.bz2', u'.gz', u'.tar', u'.z', u'.zip'] and os.path.exists(localPath): 
    812812            return localPath, True 
    813813 
  • MGET/Branches/Jason/PythonPackage/src/GeoEco/Datasets/SpatiaLite.py

    r897 r903  
    6565        super(PySpatiaLiteDependency, self).Initialize() 
    6666 
     67        # Log a message giving version numbers. 
     68 
     69        from GeoEco.Logging import Logger 
     70        from pyspatialite import dbapi2 as spatialite 
     71 
     72        conn = spatialite.connect(':memory:') 
     73        try: 
     74            row = conn.execute('SELECT sqlite_version(), spatialite_version();').fetchone() 
     75            Logger.Debug(_(u'Initialized SQLite version %(v1)s and SpatiaLite version %(v2)s.') % {u'v1': row[0], u'v2': row[1]}) 
     76        finally: 
     77            conn.close() 
     78 
    6779 
    6880class SpatiaLiteDatabase(FileDatasetCollection, Database): 
    6981    __doc__ = DynamicDocString() 
     82 
     83    def _GetConnection(self): 
     84        self._Open() 
     85        return self._Connection 
     86 
     87    Connection = property(_GetConnection, doc=DynamicDocString()) 
    7088 
    7189    def __init__(self, path, timeout=5., isolation_level=None, detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES, decompressedFileToReturn=None, displayName=None, parentCollection=None, queryableAttributes=None, queryableAttributeValues=None, lazyPropertyValues=None, cacheDirectory=None): 
     
    162180 
    163181        self._Open() 
    164         tableNames = [row['name'] for row in self._Connection.execute("SELECT name FROM sqlite_master WHERE type='table' AND name NOT IN ('spatial_ref_sys', 'spatialite_history', 'sqlite_sequence', 'geometry_columns', 'views_geometry_columns', 'virts_geometry_columns', 'geometry_columns_auth', 'SpatialIndex')")] 
     182        tableNames = [row['name'] for row in self._Connection.execute("SELECT name FROM sqlite_master WHERE type='table' AND name NOT GLOB 'idx_?*_?*' AND name NOT IN ('spatial_ref_sys', 'spatialite_history', 'sqlite_sequence', 'geometry_columns', 'views_geometry_columns', 'virts_geometry_columns', 'geometry_columns_auth', 'SpatialIndex')")] 
    165183        datasetsFound = [] 
    166184 
     
    180198 
    181199            if result: 
    182                 datasetsFound.append(SpatiaLiteTable(self, tableName[i])) 
     200                datasetsFound.append(SpatiaLiteTable(self, tableNames[i])) 
    183201                if progressReporter is not None: 
    184202                    progressReporter.ReportProgress() 
     
    192210        return self._Connection.execute("SELECT COUNT(*) FROM sqlite_master WHERE name=?;", (tableName,)).fetchone()[0] > 0 
    193211 
    194     def _CreateTable(self, tableName, geometryType=None, spatialReference=None, geometryFieldName=u'geometry'): 
     212    def _CreateTable(self, tableName, geometryType, spatialReference, geometryFieldName): 
    195213 
    196214        # Create the table. The CREATE TABLE statement requires at 
     
    316334 
    317335    def _DeleteTable(self, tableName): 
     336 
     337        # Disable the SpatiaLite spatial index and geometry columns, 
     338        # if they exist. We have to do this explicitly first because 
     339        # the DROP TABLE statement does not accomplish it. 
     340         
    318341        self._Open() 
     342 
     343        for row in self._Connection.execute("SELECT f_geometry_column, spatial_index_enabled FROM geometry_columns WHERE f_table_name = '%s';" % tableName): 
     344            if bool(row['spatial_index_enabled']): 
     345                sql = "SELECT DisableSpatialIndex('%s', '%s');" % (tableName, row['f_geometry_column']) 
     346                self._LogDebug(_(u'%(class)s 0x%(id)08X: Executing: %(sql)s'), {u'class': self.__class__.__name__, u'id': id(self), u'sql': sql}) 
     347                self._Connection.execute(sql) 
     348 
     349                sql = "DROP TABLE idx_%s_%s;" % (tableName, row['f_geometry_column']) 
     350                self._LogDebug(_(u'%(class)s 0x%(id)08X: Executing: %(sql)s'), {u'class': self.__class__.__name__, u'id': id(self), u'sql': sql}) 
     351                self._Connection.execute(sql) 
     352                 
     353            sql = "SELECT DiscardGeometryColumn('%s', '%s');" % (tableName, row['f_geometry_column']) 
     354            self._LogDebug(_(u'%(class)s 0x%(id)08X: Executing: %(sql)s'), {u'class': self.__class__.__name__, u'id': id(self), u'sql': sql}) 
     355            self._Connection.execute(sql) 
     356 
     357        # Drop the table. 
     358         
    319359        sql = "DROP TABLE %s;" % tableName 
    320360        self._LogDebug(_(u'%(class)s 0x%(id)08X: Executing: %(sql)s'), {u'class': self.__class__.__name__, u'id': id(self), u'sql': sql}) 
     
    333373            # downloaded and/or decompressed. 
    334374 
    335             if self.Path == u':memory:': 
     375            if self.Path == u':memory:' or not os.path.exists(self.Path): 
    336376                path = self.Path 
    337377                isOriginalFile = True 
     
    364404 
    365405            if self.Path == u':memory:': 
    366                 self._DisplayName = _(u'SpatiaLite in-memory database 0x%(id)08X') % {u'path': path, u'oldpath': self.Path, u'id': id(self._Connection)} 
    367                 self._LogDebug(_(u'%(class)s 0x%(id)08X: Created new %(dn)s.'), {u'class': self.__class__.__name__, u'id': id(self), u'dn': self._DisplayName}) 
     406                if not self._CallerProvidedDisplayName: 
     407                    self._DisplayName = _(u'SpatiaLite in-memory database 0x%(id)08X') % {u'id': id(self._Connection)} 
     408                    self._LogDebug(_(u'%(class)s 0x%(id)08X: Created new %(dn)s.'), {u'class': self.__class__.__name__, u'id': id(self), u'dn': self._DisplayName}) 
     409                else: 
     410                    self._LogDebug(_(u'%(class)s 0x%(id)08X: Created new SpatiaLite in-memory database 0x%(id2)08X, hereafter referred to as "%(dn)s".'), {u'class': self.__class__.__name__, u'id': id(self), u'id2': id(self._Connection), u'dn': self._DisplayName}) 
    368411 
    369412            # If this database does not have a table named 
     
    387430    ######################### TODO: All methods below here need to be checked ######################### 
    388431 
     432##    @classmethod 
     433##    def _RemoveExistingDatasetsFromList(cls, path, datasets, progressReporter): 
     434##        numDatasets = len(datasets) 
     435## 
     436##        if path != ':memory:' and not os.path.exists(path): 
     437##            cls._LogDebug(_(u'%(class)s: SpatiaLite database "%(path)s" does not exist.'), {u'class': cls.__name__, u'path': path}) 
     438##            while len(datasets) > 0: 
     439##                del datasets[0] 
     440##        else: 
     441##            from pyspatialite import dbapi2 as spatialite 
     442## 
     443##            try: 
     444##                conn = pyspatialite.connect(path) 
     445##            except Exception, e: 
     446##                raise RuntimeError(_(u'The file %(path)s exists but it could not be opened as a SpatiaLite database. Detailed error information: pyspatialite.connect failed with %(e)s: %(msg)s.') % {u'path': path, u'e': e.__class__.__name__, u'msg': self._Str(e)}) 
     447## 
     448##            try: 
     449##                i = 0 
     450##                while i < len(datasets): 
     451##                    tableName = datasets[i].GetQueryableAttributeValue(u'TableName') 
     452##                    if tableName is None: 
     453##                        if path == ':memory:': 
     454##                            raise RuntimeError(_(u'Cannot import %(dn)s into a SpatiaLite in-memory database because that dataset does not have a value for the TableName queryable attribute. In order to import a dataset into a SpatiaLite database, the dataset must have a value for that queryable attribute.') % {u'dn': datasets[i].DisplayName}) 
     455##                        raise RuntimeError(_(u'Cannot import %(dn)s into SpatiaLite database %(path)s because that dataset does not have a value for the TableName queryable attribute. In order to import a dataset into a SpatiaLite database, the dataset must have a value for that queryable attribute.') % {u'dn': datasets[i].DisplayName, u'path': path}) 
     456##                     
     457##                    if conn.execute("SELECT COUNT(*) FROM sqlite_master WHERE name=?;", (tableName,)).fetchone()[0] > 0: 
     458##                        if path != ':memory:': 
     459##                            cls._LogDebug(_(u'%(class)s: Table %(table)s exists in SpatiaLite database %(path)s.'), {u'class': cls.__name__, u'table': tableName, u'path': path}) 
     460##                        del datasets[i] 
     461##                    else: 
     462##                        i += 1 
     463##            finally: 
     464##                conn.close() 
     465## 
     466##        if progressReporter is not None: 
     467##            progressReporter.ReportProgress(numDatasets) 
     468## 
     469##    @classmethod 
     470##    def _ImportDatasetsToPath(cls, path, sourceDatasets, mode, progressReporter, options): 
     471## 
     472##        # If path is not ":memory:" it is a file. If that file does 
     473##        # not exist, create the parent directories, if they do not 
     474##        # exist already. 
     475## 
     476##        if path != ':memory:' and not os.path.isfile(path) and (path[0] in ['/', '\\'] or hasattr(os.path, 'splitdrive') and os.path.splitdrive(path)[0] != '' or hasattr(os.path, 'splitunc') and os.path.splitunc(path)[0] != '') and not os.path.isdir(os.path.dirname(path)): 
     477##            cls._LogDebug(_(u'%(class)s: Creating directory "%(path)s".'), {u'class': cls.__name__, u'path': os.path.dirname(path)}) 
     478##            try: 
     479##                os.makedirs(os.path.dirname(path)) 
     480##            except Exception, e: 
     481##                raise RuntimeError(_(u'Failed to create directory "%(path)s". Python\'s os.makedirs function failed and reported %(e)s: %(msg)s') % {u'path': os.path.dirname(path), u'e': e.__class__.__name__, u'msg': cls._Unicode(e)}) 
     482## 
     483##        # Open the SpatiaLite database. This will create it if it doesn't 
     484##        # exist already. Then import each dataset into it. 
     485## 
     486##        database = SpatiaLiteDatabase(path) 
     487##        try: 
     488##            for dataset in sourceDatasets: 
     489##                cls._ImportTableToDatabase(dataset, database, mode, progressReporter) 
     490##        finally: 
     491##            db.Close() 
     492## 
     493##    @classmethod 
     494##    def _ImportTableToDatabase(cls, dataset, database, mode, progressReporter): 
     495## 
     496##        # Perform additional validation. 
     497## 
     498##        if not isinstance(dataset, Table): 
     499##            raise ValueError(_(u'Cannot import %(dn1)s into %(dn2)s because the former is not a Table instance. Only Tables can be imported into SpatiaLite databases.') % {u'dn1': dataset.DisplayName, u'dn2': database.DisplayName}) 
     500## 
     501##        tableName = dataset.GetQueryableAttributeValue(u'TableName') 
     502##        if tableName is None: 
     503##            raise RuntimeError(_(u'Cannot import %(dn1)s into %(dn2)s because the former does not have a value for the TableName queryable attribute. In order to import a dataset into a SpatiaLite database, the dataset must have a value for that queryable attribute.') % {u'dn1': dataset.DisplayName, u'dn2': database.DisplayName}) 
     504## 
     505##        # If the table already exists and the mode is 'replace', 
     506##        # delete it (otherwise raise an error). 
     507## 
     508##        if database._Connection.execute("SELECT COUNT(*) FROM sqlite_master WHERE name=?;", (tableName,)).fetchone()[0] > 0: 
     509##            if mode != u'replace': 
     510##                raise RuntimeError(_(u'Cannot import %(dn1)s into %(dn2)s because that database already has a table named %(table)s.') % {u'dn1': dataset.DisplayName, u'dn2': database.DisplayName, u'table': tableName}) 
     511## 
     512##            cls._LogDebug(_(u'%(class)s: Deleting existing table %(table)s from %(dn)s.'), {u'class': cls.__name__, u'table': tableName, u'dn': database.DisplayName}) 
     513##            try: 
     514##                database._Connection.execute("DROP TABLE %s;" % tableName) 
     515##            except Exception, e: 
     516##                raise RuntimeError(_(u'Failed to delete existing table %(table)s from %(dn)s. SpatiaLite reported %(e)s: %(msg)s') % {u'table': tableName, u'dn': database.DisplayName, u'e': e.__class__.__name__, u'msg': cls._Unicode(e)}) 
     517## 
     518##        # Create the table. 
     519## 
     520##        if dataset.GeometryType is not None: 
     521##            self._LogWarning(_(u'When %(dn1)s is imported to %(dn2)s as table %(table)s, the geometry field will be lost because SpatiaLite does not support geometry ')) 
     522 
     523    ######################### TODO: All methods above here need to be checked ######################### 
     524 
    389525    @classmethod 
    390     def _RemoveExistingDatasetsFromList(cls, path, datasets, progressReporter): 
    391         numDatasets = len(datasets) 
    392  
    393         if path != ':memory:' and not os.path.exists(path): 
    394             cls._LogDebug(_(u'%(class)s: SpatiaLite database "%(path)s" does not exist.'), {u'class': cls.__name__, u'path': path}) 
    395             while len(datasets) > 0: 
    396                 del datasets[0] 
     526    def ExportToArcGISWorkspace(cls, spatiaLiteDB, arcGISWorkspace, tableNames=None, skipExisting=False, overwriteExisting=False): 
     527        cls.__doc__.Obj.ValidateMethodInvocation() 
     528 
     529        # Create the ArcGIS workspace, if it does not exist already. 
     530        # The validation code above should have already created the 
     531        # parent directories, if they did not exist. 
     532 
     533        from GeoEco.ArcGIS import GeoprocessorManager, ArcGISDependency 
     534        gp = GeoprocessorManager.GetWrappedGeoprocessor() 
     535        outputTypeSingular = _(u'feature class') 
     536        outputTypePlural = _(u'feature classes') 
     537 
     538        if not gp.Exists(arcGISWorkspace): 
     539            if os.path.splitext(arcGISWorkspace)[1].lower() == u'.mdb': 
     540                cls._LogInfo(_(u'Creating personal geodatabase %s.') % arcGISWorkspace) 
     541                gp.CreatePersonalGDB_management(os.path.dirname(arcGISWorkspace), os.path.basename(arcGISWorkspace)) 
     542 
     543            elif os.path.splitext(arcGISWorkspace)[1].lower() == u'.gdb': 
     544                cls._LogInfo(_(u'Creating file geodatabase %s.') % arcGISWorkspace) 
     545                d = ArcGISDependency(9,2) 
     546                d.Initialize() 
     547                gp.CreateFileGDB_management(os.path.dirname(arcGISWorkspace), os.path.basename(arcGISWorkspace)) 
     548 
     549            else: 
     550                cls._LogInfo(_(u'Creating directory %s.') % arcGISWorkspace) 
     551                gp.CreateFolder_management(os.path.dirname(arcGISWorkspace), os.path.basename(arcGISWorkspace)) 
     552                outputTypeSingular = _(u'shapefile') 
     553                outputTypePlural = _(u'shapefiles') 
     554 
     555        elif os.path.isdir(arcGISWorkspace) and os.path.splitext(arcGISWorkspace)[1].lower() != '.gdb': 
     556            outputTypeSingular = _(u'shapefile') 
     557            outputTypePlural = _(u'shapefiles') 
     558                 
     559        # Enumerate the SpatiaLite tables we will copy, and if the 
     560        # caller has requested that we skip existing outputs or not 
     561        # overwrite them, check whether they exist. 
     562 
     563        from GeoEco.Datasets.ArcGIS import ArcGISWorkspace, ArcGISTable 
     564 
     565        db = SpatiaLiteDatabase(spatiaLiteDB) 
     566        workspace = ArcGISWorkspace(arcGISWorkspace, ArcGISTable, pathParsingExpressions=[u'(?P<TableName>.+)'], queryableAttributes=(QueryableAttribute(u'TableName', _(u'Table name'), UnicodeStringTypeMetadata()),)) 
     567         
     568        if tableNames is None: 
     569            tables = db.QueryDatasets(reportProgress=False) 
    397570        else: 
    398             from pyspatialite import dbapi2 as spatialite 
    399  
    400             try: 
    401                 conn = pyspatialite.connect(path) 
    402             except Exception, e: 
    403                 raise RuntimeError(_(u'The file %(path)s exists but it could not be opened as a SpatiaLite database. Detailed error information: pyspatialite.connect failed with %(e)s: %(msg)s.') % {u'path': path, u'e': e.__class__.__name__, u'msg': self._Str(e)}) 
    404  
    405             try: 
    406                 i = 0 
    407                 while i < len(datasets): 
    408                     tableName = datasets[i].GetQueryableAttributeValue(u'TableName') 
    409                     if tableName is None: 
    410                         if path == ':memory:': 
    411                             raise RuntimeError(_(u'Cannot import %(dn)s into a SpatiaLite in-memory database because that dataset does not have a value for the TableName queryable attribute. In order to import a dataset into a SpatiaLite database, the dataset must have a value for that queryable attribute.') % {u'dn': datasets[i].DisplayName}) 
    412                         raise RuntimeError(_(u'Cannot import %(dn)s into SpatiaLite database %(path)s because that dataset does not have a value for the TableName queryable attribute. In order to import a dataset into a SpatiaLite database, the dataset must have a value for that queryable attribute.') % {u'dn': datasets[i].DisplayName, u'path': path}) 
     571            tables = db.QueryDatasets(expression='TableName IN (%s)' % ', '.join(["'" + name.replace("'", "''") + "'" for name in tableNames]), reportProgress=False) 
     572 
     573        if len(tables) <= 0: 
     574            if tableNames is None: 
     575                cls._LogInfo(_(u'There are no tables in %(spatiaLiteDB)s to copy.') % {u'spatiaLiteDB': db.DisplayName}) 
     576            else: 
     577                cls._LogInfo(_(u'None of the requested tables exist in %(spatiaLiteDB)s.') % {u'spatiaLiteDB': db.DisplayName}) 
     578            return 
     579 
     580        outputTableNames = [] 
     581        for table in tables: 
     582            tableName = table.GetQueryableAttributeValue(u'TableName') 
     583            if outputTypeSingular == _(u'shapefile'): 
     584                if table.GeometryType is not None: 
     585                    outputTableNames.append(tableName + '.shp') 
     586                else: 
     587                    outputTableNames.append(tableName + '.dbf') 
     588            else: 
     589                outputTableNames.append(tableName) 
     590 
     591        numSkipped = 0 
     592        if skipExisting or not overwriteExisting: 
     593            cls._LogInfo(_(u'Checking %(arcGISWorkspace)s for existing tables and %(outputTypePlural)s...') % {u'arcGISWorkspace': arcGISWorkspace, u'outputTypePlural': outputTypePlural}) 
     594            i = 0 
     595            while i < len(tables): 
     596                if gp.Exists(os.path.join(arcGISWorkspace, outputTableNames[i])): 
     597                    if not overwriteExisting: 
     598                        raise ValueError(_(u'Cannot copy %(input)s to %(outputTypeSingular)s %(output)s. The %(outputTypeSingular)s already exists.') % {u'input': table.DisplayName, u'outputTypeSingular': outputTypeSingular, u'output': os.path.join(arcGISWorkspace, outputTableNames[i])}) 
     599 
     600                    cls._LogDebug(_(u'Skipping %(input)s; the %(outputTypeSingular)s %(output)s already exists.') % {u'input': table.DisplayName, u'outputTypeSingular': outputTypeSingular, u'output': os.path.join(arcGISWorkspace, outputTableNames[i])}) 
    413601                     
    414                     if conn.execute("SELECT COUNT(*) FROM sqlite_master WHERE name=?;", (tableName,)).fetchone()[0] > 0: 
    415                         if path != ':memory:': 
    416                             cls._LogDebug(_(u'%(class)s: Table %(table)s exists in SpatiaLite database %(path)s.'), {u'class': cls.__name__, u'table': tableName, u'path': path}) 
    417                         del datasets[i] 
    418                     else: 
    419                         i += 1 
    420             finally: 
    421                 conn.close() 
    422  
    423         if progressReporter is not None: 
    424             progressReporter.ReportProgress(numDatasets) 
     602                    del tables[i] 
     603                    del outputTableNames [i] 
     604                    numSkipped += 1 
     605                else: 
     606                    i += 1 
     607 
     608        if numSkipped > 0: 
     609            if len(tables) <= 0: 
     610                cls._LogInfo(_(u'Skipping all %(numSkipped)i tables in %(spatiaLiteDB)s. All of the corresponding tables and %(outputTypePlural)s already exist.') % {u'numSkipped': numSkipped, u'spatiaLiteDB': db.DisplayName, u'outputTypePlural': outputTypePlural}) 
     611                return 
     612            else: 
     613                cls._LogInfo(_(u'Skipping %(numSkipped)i tables in %(spatiaLiteDB)s because the corresponding tables and %(outputTypePlural)s already exist.') % {u'numSkipped': numSkipped, u'spatiaLiteDB': db.DisplayName, u'outputTypePlural': outputTypePlural}) 
     614 
     615        # Copy the tables. 
     616 
     617        cls._LogInfo(_(u'Copying %(num)i tables from %(spatiaLiteDB)s to %(arcGISWorkspace)s.') % {u'num': len(tables), u'spatiaLiteDB': db.DisplayName, u'arcGISWorkspace': arcGISWorkspace}) 
     618 
     619        for i in range(len(tables)): 
     620            if overwriteExisting and workspace.TableExists(outputTableNames[i]): 
     621                workspace.DeleteTable(outputTableNames[i]) 
     622            workspace.ImportTable(outputTableNames[i], tables[i]) 
     623 
     624            # Explicitly add a spatial index. 
     625            # CreateFeatureClass_management is supposed to do that 
     626            # automatically if you pass 0, 0, 0 for the Spatial Grid 
     627            # parameters, but that does not seem to work, at least for 
     628            # shapfiles on ArcGIS 10 SP2. 
     629 
     630            #gp.AddSpatialIndex_Management(os.path.join(arcGISWorkspace, outputTableNames[i]), 0, 0, 0) 
     631 
     632        # Return successfully. 
     633 
     634        return arcGISWorkspace 
    425635 
    426636    @classmethod 
    427     def _ImportDatasetsToPath(cls, path, sourceDatasets, mode, progressReporter, options): 
    428  
    429         # If path is not ":memory:" it is a file. If that file does 
    430         # not exist, create the parent directories, if they do not 
    431         # exist already. 
    432  
    433         if path != ':memory:' and not os.path.isfile(path) and (path[0] in ['/', '\\'] or hasattr(os.path, 'splitdrive') and os.path.splitdrive(path)[0] != '' or hasattr(os.path, 'splitunc') and os.path.splitunc(path)[0] != '') and not os.path.isdir(os.path.dirname(path)): 
    434             cls._LogDebug(_(u'%(class)s: Creating directory "%(path)s".'), {u'class': cls.__name__, u'path': os.path.dirname(path)}) 
    435             try: 
    436                 os.makedirs(os.path.dirname(path)) 
    437             except Exception, e: 
    438                 raise RuntimeError(_(u'Failed to create directory "%(path)s". Python\'s os.makedirs function failed and reported %(e)s: %(msg)s') % {u'path': os.path.dirname(path), u'e': e.__class__.__name__, u'msg': cls._Unicode(e)}) 
    439  
    440         # Open the SpatiaLite database. This will create it if it doesn't 
    441         # exist already. Then import each dataset into it. 
    442  
    443         database = SpatiaLiteDatabase(path) 
    444         try: 
    445             for dataset in sourceDatasets: 
    446                 cls._ImportTableToDatabase(dataset, database, mode, progressReporter) 
    447         finally: 
    448             db.Close() 
    449  
    450     @classmethod 
    451     def _ImportTableToDatabase(cls, dataset, database, mode, progressReporter): 
    452  
    453         # Perform additional validation. 
    454  
    455         if not isinstance(dataset, Table): 
    456             raise ValueError(_(u'Cannot import %(dn1)s into %(dn2)s because the former is not a Table instance. Only Tables can be imported into SpatiaLite databases.') % {u'dn1': dataset.DisplayName, u'dn2': database.DisplayName}) 
    457  
    458         tableName = dataset.GetQueryableAttributeValue(u'TableName') 
    459         if tableName is None: 
    460             raise RuntimeError(_(u'Cannot import %(dn1)s into %(dn2)s because the former does not have a value for the TableName queryable attribute. In order to import a dataset into a SpatiaLite database, the dataset must have a value for that queryable attribute.') % {u'dn1': dataset.DisplayName, u'dn2': database.DisplayName}) 
    461  
    462         # If the table already exists and the mode is 'replace', 
    463         # delete it (otherwise raise an error). 
    464  
    465         if database._Connection.execute("SELECT COUNT(*) FROM sqlite_master WHERE name=?;", (tableName,)).fetchone()[0] > 0: 
    466             if mode != u'replace': 
    467                 raise RuntimeError(_(u'Cannot import %(dn1)s into %(dn2)s because that database already has a table named %(table)s.') % {u'dn1': dataset.DisplayName, u'dn2': database.DisplayName, u'table': tableName}) 
    468  
    469             cls._LogDebug(_(u'%(class)s: Deleting existing table %(table)s from %(dn)s.'), {u'class': cls.__name__, u'table': tableName, u'dn': database.DisplayName}) 
    470             try: 
    471                 database._Connection.execute("DROP TABLE %s;" % tableName) 
    472             except Exception, e: 
    473                 raise RuntimeError(_(u'Failed to delete existing table %(table)s from %(dn)s. SpatiaLite reported %(e)s: %(msg)s') % {u'table': tableName, u'dn': database.DisplayName, u'e': e.__class__.__name__, u'msg': cls._Unicode(e)}) 
    474  
    475         # Create the table. 
    476  
    477         if dataset.GeometryType is not None: 
    478             self._LogWarning(_(u'When %(dn1)s is imported to %(dn2)s as table %(table)s, the geometry field will be lost because SpatiaLite does not support geometry ')) 
     637    def ImportFromArcGISWorkspace(cls, arcGISWorkspace, spatiaLiteDB, tableNames=None, skipExisting=False, overwriteExisting=False): 
     638        cls.__doc__.Obj.ValidateMethodInvocation() 
     639 
     640        # Create the SpatialLite database, if it does not exist 
     641        # already. The validation code above should have already 
     642        # created the parent directories, if they did not exist. 
     643        # Calling _Open creates the database if it does not exist 
     644        # already. 
     645 
     646        if not os.path.exists(spatiaLiteDB): 
     647            cls._LogInfo(_(u'Creating SpatiaLite database %s.') % spatiaLiteDB) 
     648 
     649        db = SpatiaLiteDatabase(spatiaLiteDB, isolation_level='DEFERRED') 
     650        db._Open() 
     651 
     652        # Enumerate the ArcGIS tables and features classes we will 
     653        # copy, and if the caller has requested that we skip existing 
     654        # outputs or not overwrite them, check whether they exist. 
     655 
     656        from GeoEco.Datasets.ArcGIS import ArcGISWorkspace, ArcGISTable 
     657 
     658        workspace = ArcGISWorkspace(arcGISWorkspace, ArcGISTable, pathParsingExpressions=[u'(?P<TableName>.+)'], queryableAttributes=(QueryableAttribute(u'TableName', _(u'Table name'), UnicodeStringTypeMetadata()),)) 
     659         
     660        if tableNames is None: 
     661            tables = workspace.QueryDatasets(reportProgress=False) 
     662        else: 
     663            tables = workspace.QueryDatasets(expression='TableName IN (%s)' % ', '.join(["'" + name.replace("'", "''") + "'" for name in tableNames]), reportProgress=False) 
     664 
     665        if os.path.isdir(arcGISWorkspace) and os.path.splitext(arcGISWorkspace)[1].lower() != '.gdb': 
     666            inputTypePlural = _(u'shapefiles') 
     667        else: 
     668            inputTypePlural = _(u'feature classes') 
     669 
     670        if len(tables) <= 0: 
     671            if tableNames is None: 
     672                cls._LogInfo(_(u'There are no tables or %(inputTypePlural)s in %(arcGISWorkspace)s to copy.') % {u'inputTypePlural': inputTypePlural, u'arcGISWorkspace': arcGISWorkspace}) 
     673            else: 
     674                cls._LogInfo(_(u'None of the requested tables or %(inputTypePlural)s exist in %(arcGISWorkspace)s.') % {u'inputTypePlural': inputTypePlural, u'arcGISWorkspace': arcGISWorkspace}) 
     675            return 
     676 
     677        outputTableNames = [] 
     678        for table in tables: 
     679            tableName = table.GetQueryableAttributeValue(u'TableName') 
     680            if inputTypePlural == _(u'shapefiles'): 
     681                outputTableNames.append(os.path.splitext(tableName)[0]) 
     682            else: 
     683                outputTableNames.append(tableName) 
     684 
     685        numSkipped = 0 
     686        if skipExisting or not overwriteExisting: 
     687            cls._LogInfo(_(u'Checking %(spatiaLiteDB)s for existing tables...') % {u'spatiaLiteDB': db.DisplayName}) 
     688            i = 0 
     689            while i < len(tables): 
     690                if db.TableExists(outputTableNames[i]): 
     691                    if not overwriteExisting: 
     692                        raise ValueError(_(u'Cannot copy %(input)s to table %(output)s in %(spatiaLiteDB)s. The SpatiaLite table already exists.') % {u'input': table.DisplayName, u'output': outputTableNames[i], u'spatiaLiteDB': db.DisplayName}) 
     693 
     694                    cls._LogDebug(_(u'Skipping %(input)s; the table %(output)s already exists in %(spatiaLiteDB)s.') % {u'input': table.DisplayName, u'output': outputTableNames[i], u'spatiaLiteDB': db.DisplayName}) 
     695                     
     696                    del tables[i] 
     697                    del outputTableNames [i] 
     698                    numSkipped += 1 
     699                else: 
     700                    i += 1 
     701 
     702        if numSkipped > 0: 
     703            if len(tables) <= 0: 
     704                cls._LogInfo(_(u'Skipping all %(numSkipped)i tables and %(inputTypePlural)s in %(arcGISWorkspace)s. All of the corresponding tables already exist.') % {u'numSkipped': numSkipped, u'inputTypePlural': inputTypePlural, u'arcGISWorkspace': arcGISWorkspace}) 
     705                return 
     706            else: 
     707                cls._LogInfo(_(u'Skipping %(numSkipped)i tables and %(inputTypePlural)s in %(arcGISWorkspace)s because the corresponding tables already exist.') % {u'numSkipped': numSkipped, u'inputTypePlural': inputTypePlural, u'arcGISWorkspace': arcGISWorkspace}) 
     708 
     709        # Copy the tables. 
     710 
     711        cls._LogInfo(_(u'Copying %(num)i tables and %(inputTypePlural)s from %(arcGISWorkspace)s to %(spatiaLiteDB)s.') % {u'num': len(tables), u'inputTypePlural': inputTypePlural, u'arcGISWorkspace': arcGISWorkspace, u'spatiaLiteDB': db.DisplayName}) 
     712 
     713        for i in range(len(tables)): 
     714            if overwriteExisting and db.TableExists(outputTableNames[i]): 
     715                db.DeleteTable(outputTableNames[i]) 
     716            db.ImportTable(outputTableNames[i], tables[i]) 
    479717 
    480718 
     
    514752        # If it is not a known lazy property, return None. 
    515753 
    516         if name not in ['SpatialReference', 'HasOID', 'OIDFieldName', 'GeometryType', 'GeometryFieldName', 'Fields']: 
     754        if name not in ['SpatialReference', 'HasOID', 'OIDFieldName', 'GeometryType', 'GeometryFieldName', 'SpatiaLiteSRID', 'Fields']: 
    517755            return None 
    518756 
     
    569807 
    570808        if geometryType is not None: 
    571             wkt = self.ParentCollection._Connection.execute("SELECT srs_wkt FROM spatial_ref_sys WHERE srid IN (SELECT srid FROM geometry_columns WHERE f_table_name=? AND f_geometry_column=?);", (self._TableName, field.Name)).fetchone()[0] 
     809            self.SetLazyPropertyValue('SpatiaLiteSRID', self.ParentCollection._Connection.execute("SELECT srid FROM geometry_columns WHERE f_table_name=? AND f_geometry_column=?;", (self._TableName, geometryFieldName)).fetchone()[0]) 
     810 
     811            wkt = self.ParentCollection._Connection.execute("SELECT srs_wkt FROM spatial_ref_sys WHERE srid IN (SELECT srid FROM geometry_columns WHERE f_table_name=? AND f_geometry_column=?);", (self._TableName, geometryFieldName)).fetchone()[0] 
    572812            if isinstance(wkt, basestring) and len(wkt) > 0: 
    573813                self.SetLazyPropertyValue('SpatialReference', Dataset.ConvertSpatialReference('WKT', wkt, 'Obj')) 
     
    575815                self.SetLazyPropertyValue('SpatialReference', None) 
    576816        else: 
     817            self.SetLazyPropertyValue('SpatiaLiteSRID', None) 
    577818            self.SetLazyPropertyValue('SpatialReference', None) 
    578819 
     
    633874    @classmethod 
    634875    def _TestCapability(cls, capability): 
    635         if capability in ['addfield', 'selectcursor', 'updatecursor', 'insertcursor', 'updaterow', 'deleterow']: 
     876        if capability in ['addfield', 'createindex', 'deleteindex', 'selectcursor', 'updatecursor', 'insertcursor', 'updaterow', 'deleterow']: 
    636877            return None 
    637878 
     
    686927        return Field(name, dataType, None, None, isNullable, True) 
    687928 
     929    def _CreateIndex(self, fields, indexName, unique, ascending): 
     930 
     931        # Make sure the caller specified an index name. 
     932 
     933        if indexName is None: 
     934            raise ValueError(_(u'The index name must be provided.')) 
     935 
     936        # Drop the existing index, if it exists. 
     937         
     938        self.ParentCollection._Open() 
     939        self.ParentCollection._Connection.execute("DROP INDEX IF EXISTS %s;" % (indexName)) 
     940 
     941        # Create the new index. 
     942 
     943        self.ParentCollection._Connection.execute("CREATE %s INDEX %s ON %s (%s);" % ({False: '', True: 'UNIQUE'}[unique], indexName, self._TableName, ', '.join([field + {False: ' DESC', True: ' ASC'}[ascending] for field in fields]))) 
     944 
     945    def _DeleteIndex(self, indexName): 
     946 
     947        # Make sure the caller specified an index name. 
     948 
     949        if indexName is None: 
     950            raise ValueError(_(u'The index name must be provided.')) 
     951 
     952        # Drop the existing index, if it exists. 
     953         
     954        self.ParentCollection._Open() 
     955        self.ParentCollection._Connection.execute("DROP INDEX IF EXISTS %s;" % (indexName)) 
     956 
    688957    def _GetRowCount(self): 
    689958        self.ParentCollection._Open() 
     
    712981    def _GetValue(self, field): 
    713982        if field not in self._RowValues: 
    714             self._RowValues[field] = self._Row[field] 
     983            value = self._Row[str(field)] 
     984            if isinstance(value, datetime.date): 
     985                value = datetime.datetime(value.year, value.month, value.day, 0, 0, 0) 
     986            self._RowValues[field] = value 
    715987        return self._RowValues[field] 
    716988 
     
    720992    def _GetGeometry(self): 
    721993        if self._Table.GeometryFieldName not in self._RowValues: 
    722             geometry = self._Row[self._Table.GeometryFieldName + '_WKB'] 
     994            geometry = self._Row[str(self._Table.GeometryFieldName + '_WKB')] 
    723995            if geometry is not None: 
    724996                ogr = self._Table._ogr() 
     
    7381010        if geometry is not None and geometry.IsEmpty(): 
    7391011            geometry = None 
     1012        elif geometry.GetGeometryName() == 'POINT' and self._Table.GeometryType == 'MultiPoint': 
     1013            geometry = self._Table._ogr().ForceToMultiPoint(geometry) 
     1014        elif geometry.GetGeometryName() == 'LINESTRING' and self._Table.GeometryType == 'MultiLineString': 
     1015            geometry = self._Table._ogr().ForceToMultiLineString(geometry) 
     1016        elif geometry.GetGeometryName() == 'POLYGON' and self._Table.GeometryType == 'MultiPolygon': 
     1017            geometry = self._Table._ogr().ForceToMultiPolygon(geometry) 
     1018             
    7401019        self._RowValues[self._Table.GeometryFieldName] = geometry 
    7411020        self._SetFields.add(self._Table.GeometryFieldName) 
     
    7591038        if fields is None: 
    7601039            if self._Table.GeometryType is not None: 
    761                 sql += 'SELECT *, ST_AsBinary(%(field)s) AS %(field)s_WKB ' % {'field': self._Table.GeometryFieldName} 
     1040                sql = 'SELECT *, ST_AsBinary(%(field)s) AS %(field)s_WKB ' % {'field': self._Table.GeometryFieldName} 
    7621041            else: 
    763                 sql += 'SELECT *' 
     1042                sql = 'SELECT *' 
    7641043        else: 
    7651044            if self._Table.GeometryType is not None and self._Table.GeometryFieldName in fields: 
     
    7681047                        fields[i] = 'ST_AsBinary(%(field)s) AS %(field)s_WKB' % {'field': self._Table.GeometryFieldName} 
    7691048                        break 
    770             sql += 'SELECT %s' % ', '.join(fields) 
     1049            sql = 'SELECT %s' % ', '.join(fields) 
    7711050 
    7721051        sql += ' FROM %s' % self._Table.TableName 
     
    7991078    def _Open(self, fields, where, orderBy): 
    8001079        self._Cursor = None 
     1080        self._InTransaction = False 
    8011081        self._Row = None 
    8021082        self._RowValues = None 
    803         self._SetFields = set() 
     1083        self._SetFields = None 
    8041084 
    8051085        # Build the SQL SELECT statement from the caller's parameters. 
     
    8181098        if fields is None: 
    8191099            if self._Table.GeometryType is not None: 
    820                 sql += 'SELECT *, ST_AsBinary(%(field)s) AS %(field)s_WKB ' % {'field': self._Table.GeometryFieldName} 
     1100                sql = 'SELECT *, ST_AsBinary(%(field)s) AS %(field)s_WKB ' % {'field': self._Table.GeometryFieldName} 
    8211101            else: 
    822                 sql += 'SELECT *' 
     1102                sql = 'SELECT *' 
    8231103        else: 
    8241104            if self._Table.OIDFieldName not in fields: 
     
    8311111                        break 
    8321112                     
    833             sql += 'SELECT %s' % ', '.join(fields) 
     1113            sql = 'SELECT %s' % ', '.join(fields) 
    8341114 
    8351115        sql += ' FROM %s' % self._Table.TableName 
     
    8431123        # Open the cursor. 
    8441124 
    845         self._Cursor = self._Table.ParentCollection._Connection.execute(sql) 
     1125        try: 
     1126            self._Cursor = self._Table.ParentCollection._Connection.execute(sql) 
     1127        except: 
     1128            self._Table.ParentCollection._Connection.rollback() 
     1129            self._InTransaction = False 
     1130            raise 
     1131 
     1132        self._InTransaction = True 
    8461133 
    8471134    def _Close(self): 
     
    8501137        self._SetFields = None 
    8511138        if hasattr(self, '_Cursor') and self._Cursor is not None: 
     1139            if self._InTransaction: 
     1140                try: 
     1141                    self._Table.ParentCollection._Connection.commit() 
     1142                except: 
     1143                    pass 
    8521144            try: 
    8531145                self._Cursor.close() 
     
    8591151    def _UpdateRow(self): 
    8601152 
     1153        # Fail if we are not in a transaction. The only way this can 
     1154        # happen is if an error occurred with a previous call to this 
     1155        # cursor. That will cause the transaction to be rolled back. 
     1156        # The cursor can no longer be used after that point. 
     1157 
     1158        if not self._InTransaction: 
     1159            raise RuntimeError(_(u'Due to the previous error, no more updates can be performed with this cursor. To perform updates, close this cursor and open a new one.')) 
     1160 
    8611161        # Only execute the UPDATE statement some fields have been set. 
    8621162 
     
    8661166            # instance that is currently in self._RowValues with a buffer 
    8671167            # containing the WKB representation of it. 
     1168            # 
     1169            # Note that the Spatialite documentation contains the 
     1170            # note: 
     1171            # 
     1172            #     both ST_GeomFromText() and ST_GeomFromWKB() accept 
     1173            #     an optional SRID argument. If the SRID is 
     1174            #     unspecified (not at all a good practice), then -1 is 
     1175            #     assumed. 
     1176            # 
     1177            # It looks like if the SRID argument is not provided (and 
     1178            # -1 is presumably used) then INSERTs or UPDATEs of the 
     1179            # geometry column will consistently fail with: 
     1180            # 
     1181            #     IntegrityError: ... violates Geometry constraint 
     1182            #     [geom-type or SRID not allowed] 
     1183            # 
     1184            # To work around that, we always specify the SRID. 
    8681185 
    8691186            fieldsToSet = list(self._SetFields) 
     
    8741191                for i in range(len(fieldsToSet)): 
    8751192                    if fieldsToSet[i] == self._Table.GeometryFieldName: 
    876                         valueStrings[i] = 'ST_GeomFromWKB(?)' 
     1193                        srid = self._Table.GetLazyPropertyValue('SpatiaLiteSRID') 
     1194                        if srid is not None: 
     1195                            valueStrings[i] = 'ST_GeomFromWKB(?, %i)' % srid 
     1196                        else: 
     1197                            valueStrings[i] = 'ST_GeomFromWKB(?)' 
    8771198                        break 
    8781199 
     
    8831204            # Update the row. 
    8841205 
    885             self._Table.ParentCollection._Connection.execute(sql, [self._RowValues[field] for field in fieldsToSet]) 
     1206            try: 
     1207                self._Table.ParentCollection._Connection.execute(sql, [self._RowValues[field] for field in fieldsToSet]) 
     1208            except: 
     1209                self._Table.ParentCollection._Connection.rollback() 
     1210                self._InTransaction = False 
     1211                raise 
    8861212 
    8871213        self._Row = None 
    8881214 
    8891215    def _DeleteRow(self): 
    890         self._Table.ParentCollection._Connection.execute('DELETE %s WHERE ObjectID = %s' % (self._Table.TableName, self._GetValue(self._Table.OIDFieldName))) 
     1216        if not self._InTransaction: 
     1217            raise RuntimeError(_(u'Due to the previous error, no more deletes can be performed with this cursor. To perform deletes, close this cursor and open a new one.')) 
     1218        try: 
     1219            self._Table.ParentCollection._Connection.execute('DELETE %s WHERE ObjectID = %s' % (self._Table.TableName, self._GetValue(self._Table.OIDFieldName))) 
     1220        except: 
     1221            self._Table.ParentCollection._Connection.rollback() 
     1222            self._InTransaction = False 
     1223            raise 
    8911224        self._Row = None 
    8921225 
     
    8951228    __doc__ = DynamicDocString() 
    8961229 
    897     def _Open(self, fields, where, orderBy): 
    898         self._RowValues = None 
     1230    def _Open(self): 
     1231        self._RowValues = {} 
    8991232        self._SetFields = set() 
     1233        self._InTransaction = None 
    9001234 
    9011235    def _Close(self): 
    9021236        self._RowValues = None 
    9031237        self._SetFields = None 
    904         super(SpatiaLiteSelectCursor, self)._Close() 
    905  
    906     def _UpdateRow(self): 
     1238        if self._InTransaction: 
     1239            try: 
     1240                self._Table.ParentCollection._Connection.commit() 
     1241            except: 
     1242                pass 
     1243        super(SpatiaLiteInsertCursor, self)._Close() 
     1244 
     1245    def _InsertRow(self): 
     1246 
     1247        # Fail if we are not in a transaction. The only way this can 
     1248        # happen is if an error occurred with a previous call to this 
     1249        # cursor. That will cause the transaction to be rolled back. 
     1250        # The cursor can no longer be used after that point. 
     1251 
     1252        if self._InTransaction is not None and not self._InTransaction: 
     1253            raise RuntimeError(_(u'Due to the previous error, no more inserts can be performed with this cursor. To perform inserts, close this cursor and open a new one.')) 
    9071254 
    9081255        # Build the SQL INSERT statement. If no fields have been set, 
    9091256        # try the DEFAULT VALUES syntax. This will succeed if all of 
    9101257        # the fields are nullable. 
    911  
     1258         
    9121259        if len(self._SetFields) <= 0: 
    9131260            sql = 'INSERT INTO %s DEFAULT VALUES' % self._Table.TableName 
     
    9241271            valueStrings = ['?'] * len(self._SetFields) 
    9251272 
    926             if self._Table.GeometryType is not None and self._Table.GeometryFieldName in self._SetFields and self._RowValues[self._Table.GeometryType] is not None: 
    927                 self._RowValues[self._Table.GeometryType] = buffer(self._RowValues[self._Table.GeometryType].ExportToWKB) 
     1273            if self._Table.GeometryType is not None and self._Table.GeometryFieldName in self._SetFields and self._RowValues[self._Table.GeometryFieldName] is not None: 
     1274                self._RowValues[self._Table.GeometryFieldName] = buffer(self._RowValues[self._Table.GeometryFieldName].ExportToWkb()) 
    9281275                for i in range(len(fieldsToSet)): 
    9291276                    if fieldsToSet[i] == self._Table.GeometryFieldName: 
    930                         valueStrings[i] = 'ST_GeomFromWKB(?)' 
     1277                        srid = self._Table.GetLazyPropertyValue('SpatiaLiteSRID') 
     1278                        if srid is not None: 
     1279                            valueStrings[i] = 'ST_GeomFromWKB(?, %i)' % srid 
     1280                        else: 
     1281                            valueStrings[i] = 'ST_GeomFromWKB(?)' 
    9311282                        break 
    9321283 
    933             # Build the SQL INSERT statement. 
    934  
    935             sql = 'INSERT INTO %s (%s) VALUES %s' % (self._Table.TableName, ', '.join(fieldsToSet), ', '.join(valueStrings[i])) 
    936  
    937             # Insert the row. 
    938  
     1284        # Build the SQL INSERT statement. 
     1285 
     1286        sql = 'INSERT INTO %s (%s) VALUES (%s)' % (self._Table.TableName, ', '.join(fieldsToSet), ', '.join(valueStrings)) 
     1287 
     1288        # Insert the row. 
     1289         
     1290        try: 
    9391291            self._Table.ParentCollection._Connection.execute(sql, [self._RowValues[field] for field in fieldsToSet]) 
    940  
    941         self._RowValues = None 
     1292        except: 
     1293            self._Table.ParentCollection._Connection.rollback() 
     1294            self._InTransaction = False 
     1295            raise 
     1296 
     1297        self._InTransaction = True 
     1298        self._RowValues = {} 
    9421299        self._SetFields = set() 
    9431300 
     
    9471304############################################################################### 
    9481305 
     1306from GeoEco.ArcGIS import ArcGISDependency 
    9491307from GeoEco.Dependencies import PythonDependency 
    9501308from GeoEco.Metadata import * 
     
    10501408    description=_(u'%s instance.') % SpatiaLiteDatabase.__name__) 
    10511409 
     1410# Public method: SpatiaLiteDatabase.ExportToArcGISWorkspace 
     1411 
     1412AddMethodMetadata(SpatiaLiteDatabase.ExportToArcGISWorkspace, 
     1413    shortDescription=_(u'Converts tables in a SpatiaLite database to ArcGIS tables, shapefiles, and feature classes.'), 
     1414    isExposedToPythonCallers=True, 
     1415    isExposedByCOM=True, 
     1416    isExposedAsArcGISTool=True, 
     1417    arcGISDisplayName=_(u'Convert SpatiaLite Tables to ArcGIS Geodatasets'), 
     1418    arcGISToolCategory=_(u'Conversion\\To Table, Shapefile, or Feature Class'), 
     1419    dependencies=[ArcGISDependency(9, 1), PySpatiaLiteDependency()]) 
     1420 
     1421AddArgumentMetadata(SpatiaLiteDatabase.ExportToArcGISWorkspace, u'cls', 
     1422    typeMetadata=ClassOrClassInstanceTypeMetadata(cls=SpatiaLiteDatabase), 
     1423    description=_(u'SpatiaLiteDatabase class or instance.')) 
     1424 
     1425AddArgumentMetadata(SpatiaLiteDatabase.ExportToArcGISWorkspace, u'spatiaLiteDB', 
     1426    typeMetadata=FileTypeMetadata(mustExist=True), 
     1427    description=_( 
     1428u"""SpatiaLite database containing the tables to convert. 
     1429 
     1430The tables may have, at most, one geometry column."""), 
     1431    arcGISDisplayName=_(u'SpatiaLite database')) 
     1432 
     1433AddArgumentMetadata(SpatiaLiteDatabase.ExportToArcGISWorkspace, u'arcGISWorkspace', 
     1434    typeMetadata=ArcGISWorkspaceTypeMetadata(createParentDirectories=True, mustBeDifferentThanArguments=[u'spatiaLiteDB']), 
     1435    description=_( 
     1436u"""Directory or geodatabase to receive the geodatasets. 
     1437 
     1438If a directory is specified, SpatiaLite tables without geometry will 
     1439be converted to dBASE tables (.dbf files) and SpatiaLite tables with 
     1440geometry will be converted to shapefiles. 
     1441 
     1442If a geodatabase is specified, SpatiaLite tables without geometry will 
     1443be converted to geodatabase tables and SpatiaLite tables with geometry 
     1444will be converted to feature classes."""), 
     1445    arcGISDisplayName=_(u'Workspace')) 
     1446 
     1447AddArgumentMetadata(SpatiaLiteDatabase.ExportToArcGISWorkspace, u'tableNames', 
     1448    typeMetadata=ListTypeMetadata(elementType=UnicodeStringTypeMetadata(), canBeNone=True), 
     1449    description=_( 
     1450u"""Names of the SpatiaLite tables to convert. 
     1451 
     1452Table names are case-sensitive. If this parameter is omitted, all 
     1453tables in the database will be converted."""), 
     1454    arcGISDisplayName=_(u'Tables to convert')) 
     1455 
     1456AddArgumentMetadata(SpatiaLiteDatabase.ExportToArcGISWorkspace, u'skipExisting', 
     1457    typeMetadata=BooleanTypeMetadata(), 
     1458    description=_( 
     1459u"""If True, existing geodatasets will be skipped."""), 
     1460    arcGISDisplayName=_(u'Skip existing geodatasets')) 
     1461 
     1462AddArgumentMetadata(SpatiaLiteDatabase.ExportToArcGISWorkspace, u'overwriteExisting', 
     1463    typeMetadata=BooleanTypeMetadata(), 
     1464    description=_( 
     1465u"""If True, existing geodatasets will be overwritten. If False, a 
     1466ValueError will be raised if a geodataset already exists."""), 
     1467    initializeToArcGISGeoprocessorVariable=u'OverwriteOutput') 
     1468 
     1469AddResultMetadata(SpatiaLiteDatabase.ExportToArcGISWorkspace, u'updatedArcGISWorkspace', 
     1470    typeMetadata=ArcGISWorkspaceTypeMetadata(), 
     1471    description=_(u'Updated workspace.'), 
     1472    arcGISDisplayName=_(u'Updated workspace'), 
     1473    arcGISParameterDependencies=[u'ArcGISWorkspace']) 
     1474 
     1475# Public method: SpatiaLiteDatabase.ImportFromArcGISWorkspace 
     1476 
     1477AddMethodMetadata(SpatiaLiteDatabase.ImportFromArcGISWorkspace, 
     1478    shortDescription=_(u'Converts ArcGIS tables, shapefiles, and feature classes to tables in a SpatiaLite database.'), 
     1479    isExposedToPythonCallers=True, 
     1480    isExposedByCOM=True, 
     1481    isExposedAsArcGISTool=True, 
     1482    arcGISDisplayName=_(u'Convert ArcGIS Geodatasets to SpatiaLite Tables'), 
     1483    arcGISToolCategory=_(u'Conversion\\To SpatiaLite Database'), 
     1484    dependencies=[ArcGISDependency(9, 1), PySpatiaLiteDependency()]) 
     1485 
     1486CopyArgumentMetadata(SpatiaLiteDatabase.ExportToArcGISWorkspace, u'cls', SpatiaLiteDatabase.ImportFromArcGISWorkspace, u'cls') 
     1487 
     1488AddArgumentMetadata(SpatiaLiteDatabase.ImportFromArcGISWorkspace, u'arcGISWorkspace', 
     1489    typeMetadata=ArcGISWorkspaceTypeMetadata(mustExist=True), 
     1490    description=_( 
     1491u"""ArcGIS database containing tables, shapefiles, and feature classes 
     1492to convert."""), 
     1493    arcGISDisplayName=_(u'Workspace')) 
     1494 
     1495AddArgumentMetadata(SpatiaLiteDatabase.ImportFromArcGISWorkspace, u'spatiaLiteDB', 
     1496    typeMetadata=FileTypeMetadata(createParentDirectories=True, mustBeDifferentThanArguments=[u'arcGISWorkspace']), 
     1497    description=_( 
     1498u"""SpatiaLite database to receive the geodatasets."""), 
     1499    direction=u'Output', 
     1500    arcGISDisplayName=_(u'SpatiaLite database')) 
     1501 
     1502AddArgumentMetadata(SpatiaLiteDatabase.ImportFromArcGISWorkspace, u'tableNames', 
     1503    typeMetadata=ListTypeMetadata(elementType=UnicodeStringTypeMetadata(), canBeNone=True), 
     1504    description=_( 
     1505u"""Names of the tables, shapefiles, and feature classes to convert. 
     1506 
     1507The names may be case-sensitive, depending on the type of workspace. 
     1508dBASE tables and shapefiles should be specified with their file 
     1509extensions (.dbf and .shp, respectively). 
     1510 
     1511If this parameter is omitted, all vector geodatasets in the workspace 
     1512will be converted."""), 
     1513    arcGISDisplayName=_(u'Tables to convert')) 
     1514 
     1515AddArgumentMetadata(SpatiaLiteDatabase.ImportFromArcGISWorkspace, u'skipExisting', 
     1516    typeMetadata=BooleanTypeMetadata(), 
     1517    description=_( 
     1518u"""If True, existing tables will be skipped.""")) 
     1519 
     1520AddArgumentMetadata(SpatiaLiteDatabase.ImportFromArcGISWorkspace, u'overwriteExisting', 
     1521    typeMetadata=BooleanTypeMetadata(), 
     1522    description=_( 
     1523u"""If True, existing tables will be overwritten. If False, a 
     1524ValueError will be raised if a table already exists."""), 
     1525    initializeToArcGISGeoprocessorVariable=u'OverwriteOutput') 
     1526 
    10521527############################################################################### 
    10531528# Metadata: SpatiaLiteTable class 
  • MGET/Branches/Jason/PythonPackage/src/GeoEco/Datasets/Virtual.py

    r873 r903  
    16061606                    regionToRead.append(remainingRegion[i]) 
    16071607                else: 
    1608                     regionToRead.append(slice(max(0, remainingRegion[i].start - int(math.floor((self._MinBlockSize[i] - cellsRemaining) / 2.))), min(self.Shape[i], int(math.ceil(remainingRegion[i].stop + (self._MinBlockSize[i] - cellsRemaining) / 2.))))) 
    1609              
     1608                    maxIndex = self.Shape[self.Dimensions.index(self.GetLazyPropertyValue('PhysicalDimensions')[i])] 
     1609                    regionToRead.append(slice(max(0, remainingRegion[i].start - int(math.floor((self._MinBlockSize[i] - cellsRemaining) / 2.))), min(maxIndex, int(math.ceil(remainingRegion[i].stop + (self._MinBlockSize[i] - cellsRemaining) / 2.))))) 
     1610 
    16101611            self._Cache.insert(0, [regionToRead, self._Grid._ReadNumpyArray(regionToRead)[0]]) 
    16111612 
  • MGET/Branches/Jason/PythonPackage/src/GeoEco/Datasets/__init__.py

    r897 r903  
    11821182        if geometryType is not None: 
    11831183            self._RequireCapability('GeometryType %s %s' % (geometryType, tableName)) 
    1184             if geometryType is not None: 
     1184            if geometryFieldName is not None: 
    11851185                self._RequireCapability('GeometryFieldName') 
    11861186         
     
    12421242 
    12431243        if createGeometryField: 
    1244             table = self.CreateTable(tableName, templateTable.GeometryType, templateTable.GetSpatialReference('Obj'), templateTable.GeometryFieldName) 
     1244 
     1245            # If we support assigning the name of the geometry field, 
     1246            # try to use the same name as the template table. If not, 
     1247            # do not try to assign the geometry field name (it will 
     1248            # likely fail). 
     1249             
     1250            if self._TestCapability('GeometryFieldName') is None: 
     1251                geometryFieldName = templateTable.GeometryFieldName 
     1252            else: 
     1253                geometryFieldName = None 
     1254                 
     1255            table = self.CreateTable(tableName, templateTable.GeometryType, templateTable.GetSpatialReference('Obj'), geometryFieldName) 
    12451256        else: 
    12461257            table = self.CreateTable(tableName) 
     
    12841295        else: 
    12851296            fields = [field.Name for field in sourceTable.Fields] 
    1286             if copiedOIDFieldName is None: 
     1297            if copiedOIDFieldName is None and sourceTable.OIDFieldName is not None: 
    12871298                fields.remove(sourceTable.OIDFieldName) 
    1288             if destTable.GeometryType is None: 
     1299            if destTable.GeometryType is None and sourceTable.GeometryFieldName is not None: 
    12891300                fields.remove(sourceTable.GeometryFieldName) 
    12901301 
     
    12961307            insertCursor = destTable.OpenInsertCursor(rowCount, reportProgress, rowDescriptionSingular, rowDescriptionPlural) 
    12971308            try: 
     1309                if rowCount is not None: 
     1310                    message = _(u'Copying %(rowCount)i %(desc)s from %(dn1)s to %(dn2)s.') % {u'rowCount': rowCount, u'desc': selectCursor.RowDescriptionPlural, u'dn1': sourceTable.DisplayName, u'dn2': destTable.DisplayName} 
     1311                else: 
     1312                    message = _(u'Copying %(desc)s from %(dn1)s to %(dn2)s.') % {u'desc': selectCursor.RowDescriptionPlural, u'dn1': sourceTable.DisplayName, u'dn2': destTable.DisplayName} 
     1313                if reportProgress: 
     1314                    self._LogInfo(message) 
     1315                else: 
     1316                    self._LogDebug(message) 
     1317                 
    12981318                while selectCursor.NextRow(): 
    12991319                    for field in fields: 
     
    13031323                            insertCursor.SetGeometry(selectCursor.GetGeometry()) 
    13041324                        else: 
    1305                             insertCursor.SetValue(field, selectCursor.GetValue(value)) 
     1325                            insertCursor.SetValue(field, selectCursor.GetValue(field)) 
     1326                    insertCursor.InsertRow() 
    13061327            finally: 
    13071328                del insertCursor 
     
    13091330            del selectCursor 
    13101331 
     1332        # Return successfully. 
     1333 
     1334        return destTable 
    13111335 
    13121336    def DeleteTable(self, tableName, failIfNotExists=False): 
     
    13271351        except Exception, e: 
    13281352            raise RuntimeError(_(u'Failed to delete %(objectType)s %(tableName)s from %(dn)s due to %(e)s: %(msg)s.') % {u'objectType': self._GetObjectTypeDisplayName(tableName), u'tableName': tableName, u'dn': self._DisplayName, u'e': e.__class__.__name__, u'msg': self._Str(e)}) 
    1329              
    13301353 
    13311354    # Private members that the derived class should override. 
     
    13371360        raise RuntimeError(_(u'Programming error in this tool: The %(cls)s class does not define the Database._TableExists method. Please contact the author of this tool for assistance.') % {u'cls': self.__class__.__name__}) 
    13381361 
    1339     def _CreateTable(self, tableName, geometryType=None, spatialReference=None, geometryFieldName=u'geometry'): 
     1362    def _CreateTable(self, tableName, geometryType, spatialReference, geometryFieldName): 
    13401363        raise RuntimeError(_(u'Programming error in this tool: The %(cls)s class does not define the Database._CreateTable method. Please contact the author of this tool for assistance.') % {u'cls': self.__class__.__name__}) 
    13411364 
     
    14261449            self._RequireCapability(dataType + ' IsNullable') 
    14271450 
    1428         # If the data type is 'string', verify that the length 
    1429         # parameter was supplied and that it does not exceed the 
    1430         # maximum allowed length. 
    1431  
    1432         if dataType == 'string': 
    1433             if length is None: 
    1434                 raise ValueError(_(u'Cannot add string field %(name)s to %(dn)s because the field length was not specified. When adding a string field, you must specify the field length.') % {u'name': name, u'dn': self.DisplayName}) 
    1435             if self.MaxStringLength is not None and length > self.MaxStringLength: 
    1436                 raise ValueError(_(u'Cannot add string field %(name)s to %(dn)s because the field length (%(length)i) exceeds the maximum allowed for this dataset (%(max)i).') % {u'name': name, u'length': length, u'dn': self.DisplayName, u'max': self.MaxStringLength}) 
     1451        # If the data type is 'string' and length was supplied, verify 
     1452        # that it does not exceed the maximum allowed length. 
     1453 
     1454        if dataType == 'string' and length is not None and self.MaxStringLength is not None and length > self.MaxStringLength: 
     1455            raise ValueError(_(u'Cannot add string field %(name)s to %(dn)s because the field length (%(length)i) exceeds the maximum allowed for this dataset (%(max)i).') % {u'name': name, u'length': length, u'dn': self.DisplayName, u'max': self.MaxStringLength}) 
    14371456 
    14381457        # If the field already exists with the exact parameters 
     
    14621481        # dictionary of fields. 
    14631482 
    1464         self.Fields.append(field) 
     1483        fields = list(self.GetLazyPropertyValue('Fields')) 
     1484        fields.append(field) 
     1485        self.SetLazyPropertyValue('Fields', tuple(fields)) 
     1486 
    14651487        self._FieldsDict[name.upper()] = field 
    14661488 
     
    14801502                self._LogDebug(_(u'%(class)s 0x%(id)08X: Not deleting field with name %(Name)s because it does not exist.'), {u'class': self.__class__.__name__, u'id': id(self), u'Name': name}) 
    14811503                return 
    1482             raise ValueError(_(u'Cannot delete field %(name)s from %(dn)s because a field with that name does not exist.') % {u'name': name, u'dn': self.DisplayName}) 
     1504            raise ValueError(_(u'Cannot delete field %(name)s from %(dn)s because that field does not exist.') % {u'name': name, u'dn': self.DisplayName}) 
    14831505 
    14841506        # Call the derived class to delete the field. 
     
    14991521        # fields. 
    15001522 
    1501         del self.Fields[i] 
     1523        fields = list(self.GetLazyPropertyValue('Fields')) 
     1524        del fields[i] 
     1525        self.SetLazyPropertyValue('Fields', tuple(fields)) 
     1526 
    15021527        del self._FieldsDict[existingField.Name.upper()] 
     1528 
     1529    def CreateIndex(self, fields, indexName, unique=False, ascending=True): 
     1530        # TODO: self.__class__.__doc__.Obj.ValidateMethodInvocation() 
     1531 
     1532        # Verify that we have the required capabilities. 
     1533 
     1534        self._RequireCapability('CreateIndex') 
     1535 
     1536        # Verify that all of the fields exist and that they are not 
     1537        # trying to create an index on the geometry field. 
     1538 
     1539        for name in fields: 
     1540            field = self.GetFieldByName(name) 
     1541            if field is None: 
     1542                raise ValueError(_(u'Cannot create an index on field %(name)s of %(dn)s because that field does not exist.') % {u'name': name, u'dn': self.DisplayName}) 
     1543            if field.DataType == u'geometry': 
     1544                raise ValueError(_(u'Cannot create a non-spatial index on field %(name)s of %(dn)s because that is the geometry field. Only spatial indexes can be created on the geometry field.') % {u'name': name, u'dn': self.DisplayName}) 
     1545 
     1546        # Call the derived class to create the index. 
     1547 
     1548        if indexName is None: 
     1549            name = '' 
     1550        else: 
     1551            name = ' ' + indexName 
     1552             
     1553        self._LogDebug(_(u'%(class)s 0x%(id)08X: Creating %(unique)s %(ascending)s index%(name)s on fields [%(fields)s] of %(dn)s.'), 
     1554                       {u'class': self.__class__.__name__, u'id': id(self), u'unique': {False: _(u'non-unique'), True: _(u'unique')}[unique], u'ascending': {False: _(u'descending'), True: _(u'ascending')}[ascending], u'name': name, u'fields': u', '.join(fields), u'dn': self.DisplayName}) 
     1555 
     1556        try: 
     1557            self._CreateIndex(fields, indexName, unique, ascending) 
     1558        except Exception, e: 
     1559            raise RuntimeError(_(u'Failed to create %(unique)s %(ascending)s index%(name)s on fields [%(fields)s] of %(dn)s due to %(e)s: %(msg)s') % {u'unique': {False: _(u'non-unique'), True: _(u'unique')}[unique], u'ascending': {False: _(u'descending'), True: _(u'ascending')}[ascending], u'name': name, u'fields': u', '.join(fields), u'dn': self.DisplayName, u'e': e.__class__.__name__, u'msg': self._Unicode(e)}) 
     1560 
     1561    def DeleteIndex(self, indexName): 
     1562 
     1563        # Verify that we have the required capabilities. 
     1564 
     1565        self._RequireCapability('DeleteIndex') 
     1566 
     1567        # Call the derived class to delete the index. 
     1568 
     1569        if indexName is None: 
     1570            name = '' 
     1571        else: 
     1572            name = ' ' + indexName 
     1573             
     1574        self._LogDebug(_(u'%(class)s 0x%(id)08X: Deleting index%(name)s.'), {u'class': self.__class__.__name__, u'id': id(self), u'name': name}) 
     1575 
     1576        try: 
     1577            self._DeleteIndex(indexName) 
     1578        except Exception, e: 
     1579            raise RuntimeError(_(u'Failed to delete index%(name)s of %(dn)s due to %(e)s: %(msg)s') % {u'name': name, u'dn': self.DisplayName, u'e': e.__class__.__name__, u'msg': self._Unicode(e)}) 
    15031580 
    15041581    def GetRowCount(self): 
     
    15351612    def _DeleteField(self, name): 
    15361613        raise NotImplementedError(_(u'The _DeleteField method of class %s has not been implemented.') % self.__class__.__name__) 
     1614 
     1615    def _CreateIndex(self, fields, indexName, unique, ascending): 
     1616        raise NotImplementedError(_(u'The _CreateIndex method of class %s has not been implemented.') % self.__class__.__name__) 
     1617 
     1618    def _DeleteIndex(self, indexName): 
     1619        raise NotImplementedError(_(u'The _DeleteIndex method of class %s has not been implemented.') % self.__class__.__name__) 
    15371620 
    15381621    def _GetRowCount(self): 
  • MGET/Branches/Jason/PythonPackage/src/GeoEco/__init__.py

    r891 r903  
    1 __version__ = u'0.8a32' 
     1__version__ = u'0.8a33'