[GRASS-SVN] r58586 - grass/trunk/lib/python/temporal

svn_grass at osgeo.org svn_grass at osgeo.org
Thu Jan 2 19:34:42 PST 2014


Author: huhabla
Date: 2014-01-02 19:34:41 -0800 (Thu, 02 Jan 2014)
New Revision: 58586

Modified:
   grass/trunk/lib/python/temporal/abstract_space_time_dataset.py
   grass/trunk/lib/python/temporal/base.py
   grass/trunk/lib/python/temporal/core.py
   grass/trunk/lib/python/temporal/gui_support.py
Log:
Better performance of tgis.init() and code cleanup. Reduced number of external module calls.


Modified: grass/trunk/lib/python/temporal/abstract_space_time_dataset.py
===================================================================
--- grass/trunk/lib/python/temporal/abstract_space_time_dataset.py	2014-01-02 21:54:35 UTC (rev 58585)
+++ grass/trunk/lib/python/temporal/abstract_space_time_dataset.py	2014-01-03 03:34:41 UTC (rev 58586)
@@ -477,7 +477,7 @@
             maps = self.get_registered_maps_as_objects(
                 where=None, order="start_time", dbif=dbif)
 
-        return count_temporal_topology_relationships(maps)
+        return count_temporal_topology_relationships(maps1=maps, dbif=dbif)
 
     def check_temporal_topology(self, maps=None, dbif=None):
         """!Check the temporal topology of all maps of the current space time
@@ -516,7 +516,7 @@
             maps = self.get_registered_maps_as_objects(
                 where=None, order="start_time", dbif=dbif)
 
-        relations = count_temporal_topology_relationships(maps)
+        relations = count_temporal_topology_relationships(maps1=maps, dbif=dbif)
 
         if relations == None:
             return False
@@ -2272,7 +2272,7 @@
         dbif.execute_transaction(sql_script)
 
         # Read and validate the selected end time
-        self.select()
+        self.select(dbif)
 
         if self.is_time_absolute():
             start_time, end_time = self.get_absolute_time()

Modified: grass/trunk/lib/python/temporal/base.py
===================================================================
--- grass/trunk/lib/python/temporal/base.py	2014-01-02 21:54:35 UTC (rev 58585)
+++ grass/trunk/lib/python/temporal/base.py	2014-01-03 03:34:41 UTC (rev 58586)
@@ -37,10 +37,10 @@
 
 ###############################################################################
 
-
 class DictSQLSerializer(object):
     def __init__(self):
         self.D = {}
+        self.dbmi_paramstyle = get_tgis_dbmi_paramstyle()
 
     def serialize(self, type, table, where=None):
         """!Convert the internal dictionary into a string of semicolon
@@ -75,7 +75,6 @@
             \endcode
         """
 
-        dbif =  SQLDatabaseInterfaceConnection()
 
         sql = ""
         args = []
@@ -110,12 +109,12 @@
             sql += ') VALUES ('
             for key in self.D.keys():
                 if count == 0:
-                    if dbif.dbmi.paramstyle == "qmark":
+                    if self.dbmi_paramstyle == "qmark":
                         sql += '?'
                     else:
                         sql += '%s'
                 else:
-                    if dbif.dbmi.paramstyle == "qmark":
+                    if self.dbmi_paramstyle == "qmark":
                         sql += ' ,?'
                     else:
                         sql += ' ,%s'
@@ -135,13 +134,13 @@
                 # Update only entries which are not None
                 if self.D[key] is not None:
                     if count == 0:
-                        if dbif.dbmi.paramstyle == "qmark":
+                        if self.dbmi_paramstyle == "qmark":
                             sql += ' %s = ? ' % key
                         else:
                             sql += ' %s ' % key
                             sql += '= %s '
                     else:
-                        if dbif.dbmi.paramstyle == "qmark":
+                        if self.dbmi_paramstyle == "qmark":
                             sql += ' ,%s = ? ' % key
                         else:
                             sql += ' ,%s ' % key
@@ -158,13 +157,13 @@
             sql += 'UPDATE ' + table + ' SET '
             for key in self.D.keys():
                 if count == 0:
-                    if dbif.dbmi.paramstyle == "qmark":
+                    if self.dbmi_paramstyle == "qmark":
                         sql += ' %s = ? ' % key
                     else:
                         sql += ' %s ' % key
                         sql += '= %s '
                 else:
-                    if dbif.dbmi.paramstyle == "qmark":
+                    if self.dbmi_paramstyle == "qmark":
                         sql += ' ,%s = ? ' % key
                     else:
                         sql += ' ,%s ' % key

Modified: grass/trunk/lib/python/temporal/core.py
===================================================================
--- grass/trunk/lib/python/temporal/core.py	2014-01-02 21:54:35 UTC (rev 58585)
+++ grass/trunk/lib/python/temporal/core.py	2014-01-03 03:34:41 UTC (rev 58586)
@@ -27,7 +27,7 @@
 
 @endcode
 
-(C) 2011-2013 by the GRASS Development Team
+(C) 2011-2014 by the GRASS Development Team
 This program is free software under the GNU General Public
 License (>=v2). Read the file COPYING that comes with GRASS
 for details.
@@ -83,7 +83,23 @@
 # of the temporal GIS
 # It can either be "sqlite" or "pg"
 tgis_backend = None
+def get_tgis_backend():
+    """!Return the temporal GIS backend as string
+    
+       return either "sqlite" or "pg"
+    """
+    global tgis_backend
+    return tgis_backend
 
+# Global variable that defines the database string
+# of the temporal GIS
+tgis_database = None
+def get_tgis_database():
+    """!Return the temporal database string specified with t.connect
+    """
+    global tgis_database
+    return tgis_database
+
 # The version of the temporal framework
 # this value must be an integer larger than 0
 # Increase this value in case of backward incompatible changes in the TGIS API
@@ -94,9 +110,22 @@
 # temporal database SQL layout
 tgis_db_version=2
 
+# We need to know the parameter style of the database backend
+tgis_dbmi_paramstyle = None
+
+def get_tgis_dbmi_paramstyle():
+    """!Return the temporal database backend parameter style
+    
+       @return "qmark" or ""
+    """
+    global tgis_dbmi_paramstyle
+    return tgis_dbmi_paramstyle
+
 # We need to access the current mapset quite often in the framework, so we make
-# global variable that will be initiated when init() is called
-current_mapset=None
+# a global variable that will be initiated when init() is called
+current_mapset = None
+current_location = None
+current_gisdbase = None
 
 ###############################################################################
 
@@ -110,19 +139,29 @@
     global current_mapset
     return current_mapset
 
-def _set_current_mapset(mapset=None):
-    """!This functions set the global current mapset variable to
-       the current mapset by calling g.gisenv.
+###############################################################################
 
-       @param mapset The current mapset, g.gisenv will be called
-                     if this variable is set to None
+def get_current_location():
+    """!Return the current location
+
+       This is the fastest way to receive the current location.
+       The current location is set by init() and stored in a global variable.
+       This function provides access to this global variable.
     """
-    global current_mapset
+    global current_location
+    return current_location
+    
+###############################################################################
 
-    if mapset == None:
-        mapset = core.gisenv()["MAPSET"]
+def get_current_gisdbase():
+    """!Return the current gis database (gisdbase)
 
-    current_mapset = mapset
+       This is the fastest way to receive the current gisdbase.
+       The current gisdbase is set by init() and stored in a global variable.
+       This function provides access to this global variable.
+    """
+    global current_gisdbase
+    return current_gisdbase
 
 ###############################################################################
 
@@ -266,48 +305,20 @@
 
 ###############################################################################
 
-def get_temporal_dbmi_init_string(kv=None, grassenv=None):
-    """!Return the database initialization string
+# The temporal database string set with t.connect 
+# with substituted GRASS variables gisdbase, location and mapset
+tgis_database_string = None
 
-       @param kv dictionary generated by grass.script.parse_command("t.connect", flags="pg")
-       @param grassenv Grass environemntal variables created by grass.script.gisenv()
+def get_tgis_database_string():
+    """!Return the preprocessed temporal database string
+       
+       This string is the temporal database string set with t.connect
+       that was processed to substitue location, gisdbase and mapset 
+       varibales.
     """
+    global tgis_database_string
+    return tgis_database_string
 
-    global temporal_dbmi_init_string
-
-    if kv == None:
-        kv = core.parse_command("t.connect", flags="pg")
-    if grassenv == None:
-        grassenv = core.gisenv()
-
-    global tgis_backend
-    msgr = get_tgis_message_interface()
-
-    if tgis_backend == "sqlite":
-        # We substitute GRASS variables if they are located in the database string
-        # This behavior is in conjunction with db.connect
-        if "database" in kv:
-            string = kv["database"]
-            string = string.replace("$GISDBASE", grassenv["GISDBASE"])
-            string = string.replace(
-                "$LOCATION_NAME", grassenv["LOCATION_NAME"])
-            string = string.replace("$MAPSET", grassenv["MAPSET"])
-            temporal_dbmi_init_string = string
-            return string
-        else:
-            msgr.fatal(_("Unable to initialize the temporal GIS DBMI "
-                         "interface. Use t.connect to specify the driver "
-                         "and the database string"))
-    elif tgis_backend == "pg":
-        if "database" in kv:
-            string = kv["database"]
-            temporal_dbmi_init_string = string
-            return string
-    else:
-        msgr.fatal(_("Unable to initialize the temporal GIS DBMI "
-                     "interface. Use t.connect to specify the driver "
-                     "and the database string"))
-
 ###############################################################################
 
 def get_sql_template_path():
@@ -319,6 +330,7 @@
 
 def stop_subprocesses():
     """!Stop the messenger and C-interface subprocesses
+       that are started by tgis.init()
     """
     global message_interface
     global c_library_interface
@@ -327,55 +339,74 @@
     if c_library_interface:
         c_library_interface.stop()
 
+# We register this function to be called at exit
 atexit.register(stop_subprocesses)
 
 ###############################################################################
 
 def init():
     """!This function set the correct database backend from GRASS environmental variables
-       and creates the grass location database structure for raster,
+       and creates the grass temporal database structure for raster,
        vector and raster3d maps as well as for the space-time datasets strds,
        str3ds and stvds in case it does not exists.
-       
+
        Several global variables are initiated and the messenger and C-library interface
        subprocesses are spawned.
-       
-       The following g.gisenv variables are checked:
-        - TGIS_RAISE_ON_ERROR
-        - TGIS_DISABLE_MAPSET_CHECK
-        - TGIS_DISABLE_TIMESTAMP_WRITE
-        
+
+       Re-run this function in case the following GRASS variables change while the process runs:
+       - MAPSET
+       - LOCATION_NAME
+       - GISDBASE
+       - TGIS_RAISE_ON_ERROR
+       - TGIS_DISABLE_MAPSET_CHECK
+       - TGIS_DISABLE_TIMESTAMP_WRITE
+
+       Re-run the script if the following t.connect variables change while the process runs:
+       - temporal GIS driver (set by t.connect driver=)
+       - temporal GIS database (set by t.connect database=)
+
        The following environmental variables are checked:
         - GRASS_TGIS_PROFILE
 
         ATTENTION: This functions must be called before any spatio-temporal processing
                    can be started
     """
-    # We need to set the correct database backend from the environment variables
+    # We need to set the correct database backend and several global variables
+    # from the GRASS mapset specific environment variables of g.gisenv and t.connect
     global tgis_backend
+    global tgis_database
+    global tgis_database_string
+    global tgis_dbmi_paramstyle
     global enable_mapset_check
     global enable_timestamp_write
-    
+    global current_mapset
+    global current_location
+    global current_gisdbase
+
+    # We must run t.connect at first to create the temporal database and to
+    # get the environmental variables
     core.run_command("t.connect", flags="c")
     kv = core.parse_command("t.connect", flags="pg")
     grassenv = core.gisenv()
     raise_on_error = False
 
+    # Set the global variable for faster access
+    current_mapset = grassenv["MAPSET"]
+    current_location = grassenv["LOCATION_NAME"]
+    current_gisdbase = grassenv["GISDBASE"]
+
     # Check the g.gisenv variable TGIS_RAISE_ON_ERROR
     if grassenv.has_key("TGIS_RAISE_ON_ERROR"):
         if grassenv["TGIS_RAISE_ON_ERROR"] == "True" or grassenv["TGIS_RAISE_ON_ERROR"] == "1":
             raise_on_error = True
-            
-    # Set the global variable current_mapset for fast mapset access
-    _set_current_mapset(grassenv["MAPSET"])
+
     # Start the GRASS message interface server
     _init_tgis_message_interface(raise_on_error)
     # Start the C-library interface server
     _init_tgis_c_library_interface()
-    
     msgr = get_tgis_message_interface()
     msgr.debug(1, "Inititate the temporal database")
-    
+
     if raise_on_error is True:
         msgr.warning("TGIS_RAISE_ON_ERROR is True")
 
@@ -414,15 +445,33 @@
     else:
         # Set the default sqlite3 connection in case nothing was defined
         core.run_command("t.connect", flags="d")
+        kv = core.parse_command("t.connect", flags="pg")
+        tgis_backend = kv["driver"]
 
+    # Database string from t.connect -pg
+    tgis_database = kv["database"]
+    # Set the parameter style
+    tgis_dbmi_paramstyle = dbmi.paramstyle
+
+    # Create the temporal database string
+    if tgis_backend == "sqlite":
+        # We substitute GRASS variables if they are located in the database string
+        # This behavior is in conjunction with db.connect
+        tgis_database_string = tgis_database
+        tgis_database_string = tgis_database_string.replace("$GISDBASE", current_gisdbase)
+        tgis_database_string = tgis_database_string.replace("$LOCATION_NAME", current_location)
+        tgis_database_string = tgis_database_string.replace("$MAPSET", current_mapset)
+    elif tgis_backend == "pg":
+        tgis_database_string = tgis_database
+
+    # We do not know if the database already exists
     db_exists = False
-    database = get_temporal_dbmi_init_string(kv=kv, grassenv=grassenv)
     dbif = SQLDatabaseInterfaceConnection()
 
     # Check if the database already exists
     if tgis_backend == "sqlite":
         # Check path of the sqlite database
-        if os.path.exists(database):
+        if os.path.exists(tgis_database_string):
             dbif.connect()
             # Check for raster_base table
             dbif.cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='raster_base';")
@@ -441,7 +490,6 @@
             db_exists = True
 
     if db_exists == True:
-        
         # Check the version of the temporal database
         # This version works only with database of version 2
         dbif.close()
@@ -450,7 +498,7 @@
         dbif.close()
         if metadata is None:
             msgr.fatal(_("Unable to receiving temporal database metadata. Your temporal database is not supported."))
-        
+
         for entry in metadata:
             if "tgis_version" in entry and entry[1] != str(get_tgis_version()):
                 msgr.fatal(_("Unsupported temporal database. Version mismatch.\n"
@@ -460,11 +508,11 @@
                 "Supported temporal database version is: %(tdb)i")%( {"tdb":get_tgis_db_version()}))
         return
 
-    create_temporal_database(dbif, database)
+    create_temporal_database(dbif)
 
 ###############################################################################
 
-def create_temporal_database(dbif, database):
+def create_temporal_database(dbif):
     """!This function will create the temporal database
 
        It will create all tables and triggers that are needed to run
@@ -475,6 +523,7 @@
     global tgis_backend
     global tgis_version
     global tgis_db_version
+    global tgis_database_string
 
     template_path = get_sql_template_path()
     msgr = get_tgis_message_interface()
@@ -528,11 +577,11 @@
     stvds_tables_sql = stds_tables_template_sql.replace("STDS", "stvds")
     str3ds_tables_sql = stds_tables_template_sql.replace("STDS", "str3ds")
 
-    msgr.message(_("Create temporal database: %s" % (database)))
+    msgr.message(_("Create temporal database: %s" % (tgis_database_string)))
 
     if tgis_backend == "sqlite":
         # We need to create the sqlite3 database path if it does not exists
-        tgis_dir = os.path.dirname(database)
+        tgis_dir = os.path.dirname(tgis_database_string)
         if not os.path.exists(tgis_dir):
             os.makedirs(tgis_dir)
         # Set up the trigger that takes care of
@@ -633,7 +682,12 @@
             self.dbmi = psycopg2
 
         self.msgr = get_tgis_message_interface()
+        self.msgr.debug(1, "SQLDatabaseInterfaceConnection constructor")
 
+    def __del__(self):
+        if self.connected is True:
+            self.close()
+
     def rollback(self):
         """
             Roll back the last transaction. This must be called
@@ -650,9 +704,10 @@
 
            Supported backends are sqlite3 and postgresql
         """
-        self.database = get_temporal_dbmi_init_string()
+        global tgis_database_string
+        
         if self.dbmi.__name__ == "sqlite3":
-            self.connection = self.dbmi.connect(self.database,
+            self.connection = self.dbmi.connect(tgis_database_string,
                     detect_types = self.dbmi.PARSE_DECLTYPES | self.dbmi.PARSE_COLNAMES)
             self.connection.row_factory = self.dbmi.Row
             self.connection.isolation_level = None
@@ -660,7 +715,7 @@
             self.cursor.execute("PRAGMA synchronous = OFF")
             self.cursor.execute("PRAGMA journal_mode = MEMORY")
         elif self.dbmi.__name__ == "psycopg2":
-            self.connection = self.dbmi.connect(self.database)
+            self.connection = self.dbmi.connect(tgis_database_string)
             #self.connection.set_isolation_level(dbmi.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
             self.cursor = self.connection.cursor(
                 cursor_factory = self.dbmi.extras.DictCursor)
@@ -668,7 +723,6 @@
 
     def close(self):
         """!Close the DBMI connection"""
-        #print "Close connection to",  self.database
         self.connection.commit()
         self.cursor.close()
         self.connected = False
@@ -819,7 +873,10 @@
 
 def init_dbif(dbif):
     """!This method checks if the database interface connection exists,
-        if not a new one will be created, connected and True will be returned
+        if not a new one will be created, connected and True will be returned.
+        If the database interface exists but is connected, the connection will be established.
+        
+        @return the tuple (dbif, True|False)
 
         Usage code sample:
         @code
@@ -839,6 +896,9 @@
         dbif = SQLDatabaseInterfaceConnection()
         dbif.connect()
         return dbif, True
+    elif dbif.connected is False:
+        dbif.connect()
+        return dbif, True
 
     return dbif, False
 

Modified: grass/trunk/lib/python/temporal/gui_support.py
===================================================================
--- grass/trunk/lib/python/temporal/gui_support.py	2014-01-02 21:54:35 UTC (rev 58585)
+++ grass/trunk/lib/python/temporal/gui_support.py	2014-01-03 03:34:41 UTC (rev 58586)
@@ -18,7 +18,7 @@
 
 ###############################################################################
 
-def tlist_grouped(type, group_type = False):
+def tlist_grouped(type, group_type = False, dbif=None):
     """!List of temporal elements grouped by mapsets.
 
     Returns a dictionary where the keys are mapset 
@@ -36,6 +36,7 @@
     @return directory of mapsets/elements
     """
     result = {}
+    dbif, connected = init_dbif(dbif)
     
     mapset = None
     if type == 'stds':
@@ -44,7 +45,7 @@
         types = [type]
     for type in types:
         try:
-            tlist_result = tlist(type)
+            tlist_result = tlist(type=type, dbif=dbif)
         except core.ScriptError, e:
             warning(e)
             continue
@@ -70,11 +71,14 @@
             else:
                 result[mapset].append(name)
 
+    if connected is True:
+        dbif.close()
+
     return result
 
 ###############################################################################
 
-def tlist(type):
+def tlist(type, dbif=None):
     """!Return a list of space time datasets of absolute and relative time
      
     @param type element type (strds, str3ds, stvds)
@@ -83,10 +87,8 @@
     """
     id = None
     sp = dataset_factory(type, id)
+    dbif, connected = init_dbif(dbif)
 
-    dbif = SQLDatabaseInterfaceConnection()
-    dbif.connect()
-
     output = []
     temporal_type = ["absolute", 'relative']
     for type in temporal_type:
@@ -107,6 +109,8 @@
         for row in rows:
             for col in row:
                 output.append(str(col))
-    dbif.close()
 
+    if connected is True:
+        dbif.close()
+
     return output



More information about the grass-commit mailing list