[GRASS-SVN] r64677 - grass/trunk/gui/wxpython/core

svn_grass at osgeo.org svn_grass at osgeo.org
Tue Feb 17 19:53:48 PST 2015


Author: wenzeslaus
Date: 2015-02-17 19:53:48 -0800 (Tue, 17 Feb 2015)
New Revision: 64677

Modified:
   grass/trunk/gui/wxpython/core/toolboxes.py
Log:
wxGUI/toolboxes: make tooboxes a little bit more independent from GUI

This uses various workarounds, lazy imports and wrappers to not import anything from wxGUI (and thus wx) or to import it only if it is really needed. This avoids issues when building toolboxes during compilation and the environment is not set correctly and wx (and thus wxGUI) cannot be imported properly. This does not make GUI toolboxes mechanism independent on wxGUI (#2142). It just makes compilation more robust and shows which dependencies must be solved to create standalone toolboxes mechanism. See also #1819.


Modified: grass/trunk/gui/wxpython/core/toolboxes.py
===================================================================
--- grass/trunk/gui/wxpython/core/toolboxes.py	2015-02-18 02:03:07 UTC (rev 64676)
+++ grass/trunk/gui/wxpython/core/toolboxes.py	2015-02-18 03:53:48 UTC (rev 64677)
@@ -30,23 +30,38 @@
 else:
     has_xpath = False
 
-from core.globalvar import WXGUIDIR
-from core.utils import GetSettingsPath, _
-from core.gcmd import GError, RunCommand, EncodeString
-
 import grass.script.task as gtask
 import grass.script.core as gcore
 from grass.script.utils import try_remove
-from grass.script.core import ScriptError
-from core.debug import Debug
+from grass.exceptions import ScriptError, CalledModuleError
 
 
+# duplicating code from core/globalvar.py
+# if this will become part of grass Python library or module, this should be
+# parametrized, so we will get rid of the definition here
+# (GUI will use its definition and build also its own)
+WXGUIDIR = os.path.join(os.getenv("GISBASE"), "gui", "wxpython")
+
+
 # this could be placed to functions
 mainMenuFile    = os.path.join(WXGUIDIR, 'xml', 'main_menu.xml')
 toolboxesFile   = os.path.join(WXGUIDIR, 'xml', 'toolboxes.xml')
 wxguiItemsFile  = os.path.join(WXGUIDIR, 'xml', 'wxgui_items.xml')
 moduleItemsFile = os.path.join(WXGUIDIR, 'xml', 'module_items.xml')
 
+
+def GetSettingsPath():
+    # this is for cases during compilation and it is not possible to import wx
+    # TODO: if the function would be in the grass Python library there would
+    # no need to do this
+    try:
+        from core.utils import GetSettingsPath as actualGetSettingsPath
+        return actualGetSettingsPath()
+    except ImportError:
+        # expecting that there will be no such path
+        # (these files are always check for existence here)
+        return ""
+
 userToolboxesFile = os.path.join(GetSettingsPath(), 'toolboxes', 'toolboxes.xml')
 userMainMenuFile = os.path.join(GetSettingsPath(), 'toolboxes', 'main_menu.xml')
 if not os.path.exists(userToolboxesFile):
@@ -55,6 +70,49 @@
     userMainMenuFile = None
 
 
+def _(string):
+    # is attribute initialized to actual value?
+    if _.translate is None:
+        try:
+            # if not get the translate function named _
+            from core.utils import _ as actual_translate
+            # assign the imported function to translade attribute
+            _.translate = actual_translate
+        except ImportError:
+            # speak English if there is a problem with import of wx
+            def noop_traslate(string):
+                return string
+            _.translate = noop_traslate
+    return _.translate(string)
+
+# attribute translate of function _
+_.translate = None
+
+
+def _warning(message):
+    # TODO: enable choice between GUI and script behavior
+    # import only when really needed
+    from core.gcmd import GError
+    GError(message)
+
+
+def _debug(level, message):
+    # this has interface as originally used GUI Debug but uses grass.script
+    gcore.debug(message, level)
+
+
+def _encode_string(string):
+    try:
+        from core.gcmd import EncodeString
+        return EncodeString(string)
+    except ImportError:
+        # this is the case when we have errors during compilation but
+        # the environment is bad and we cannot import wx correctly
+        # UTF-8 is pretty good guess for most cases (and shoudl work for
+        # Max OS X where wx 32 vs 64 bit issue is happaning)
+        return string.endode('utf-8')
+
+
 def toolboxesOutdated():
     """Removes auto-generated menudata.xml
     to let gui regenerate it next time it starts."""
@@ -72,7 +130,7 @@
     If something goes wrong during building or user doesn't modify menu,
     default file (from distribution) is returned.
     """
-    Debug.msg(1, "toolboxes.getMenudataFile: {userRootFile}, {newFile}, {fallback}".format(**locals()))
+    _debug(1, "toolboxes.getMenudataFile: {userRootFile}, {newFile}, {fallback}".format(**locals()))
 
     distributionRootFile = os.path.join(WXGUIDIR, 'xml', userRootFile)
     userRootFile = os.path.join(GetSettingsPath(), 'toolboxes', userRootFile)
@@ -92,29 +150,29 @@
             # remove menu file when there is no main_menu and toolboxes
             if not userToolboxesFile and not userRootFile:
                 os.remove(menudataFile)
-                Debug.msg(2, "toolboxes.getMenudataFile: no user defined files, menudata deleted")
+                _debug(2, "toolboxes.getMenudataFile: no user defined files, menudata deleted")
                 return fallback
 
             if bool(userToolboxesFile) != bool(userRootFile):
                 # always generate new because we don't know if there has been any change
                 generateNew = True
-                Debug.msg(2, "toolboxes.getMenudataFile: only one of the user defined files")
+                _debug(2, "toolboxes.getMenudataFile: only one of the user defined files")
             else:
                 # if newer files -> generate new
                 menudataTime = os.path.getmtime(menudataFile)
                 if userToolboxesFile:
                     if os.path.getmtime(userToolboxesFile) > menudataTime:
-                        Debug.msg(2, "toolboxes.getMenudataFile: user toolboxes is newer than menudata")
+                        _debug(2, "toolboxes.getMenudataFile: user toolboxes is newer than menudata")
                         generateNew = True
                 if userRootFile:
                     if os.path.getmtime(userRootFile) > menudataTime:
-                        Debug.msg(2, "toolboxes.getMenudataFile: user root file is newer than menudata")
+                        _debug(2, "toolboxes.getMenudataFile: user root file is newer than menudata")
                         generateNew = True
         elif userToolboxesFile or userRootFile:
-            Debug.msg(2, "toolboxes.getMenudataFile: no menudata")
+            _debug(2, "toolboxes.getMenudataFile: no menudata")
             generateNew = True
         else:
-            Debug.msg(2, "toolboxes.getMenudataFile: no user defined files")
+            _debug(2, "toolboxes.getMenudataFile: no user defined files")
             return fallback
 
         if generateNew:
@@ -123,11 +181,11 @@
                 # file but has toolboxes requieres regeneration.
                 # Unfortunately, this is the case can be often: defined
                 # toolboxes but undefined module tree file.
-                Debug.msg(2, "toolboxes.getMenudataFile: creating a tree")
+                _debug(2, "toolboxes.getMenudataFile: creating a tree")
                 tree = createTree(distributionRootFile=distributionRootFile, userRootFile=userRootFile)
             except ETREE_EXCEPTIONS:
-                GError(_("Unable to parse user toolboxes XML files. "
-                         "Default files will be loaded."))
+                _warning(_("Unable to parse user toolboxes XML files. "
+                           "Default files will be loaded."))
                 return fallback
 
             try:
@@ -137,12 +195,12 @@
                 fh.close()
                 return menudataFile
             except:
-                Debug.msg(2, "toolboxes.getMenudataFile: writing menudata failed, returning fallback file")
+                _debug(2, "toolboxes.getMenudataFile: writing menudata failed, returning fallback file")
                 return fallback
         else:
             return menudataFile
     else:
-        Debug.msg(2, "toolboxes.getMenudataFile: returning menudata fallback file")
+        _debug(2, "toolboxes.getMenudataFile: returning menudata fallback file")
         return fallback
 
 
@@ -164,7 +222,7 @@
         try:
             os.mkdir(path)
         except OSError as e:
-            # we cannot use GError or similar because the gui doesn''t start at all
+            # we cannot use GError or similar because the gui doesn't start at all
             gcore.warning('%(reason)s\n%(detail)s' % 
                     ({'reason':_('Unable to create toolboxes directory.'),
                       'detail': str(e)}))
@@ -407,8 +465,13 @@
 
 
 def _getAddons():
-    return sorted(RunCommand('g.extension', quiet=True, read=True,
-                             flags='a').splitlines())
+    try:
+        output = gcore.read_command('g.extension', quiet=True, flags='a')
+    except CalledModuleError:
+        _warning(_("List of addons cannot be obtained"
+                   " because g.extension failed."))
+        return []
+    return sorted(output.splitlines())
 
 
 def _removeAddonsItem(node, addonsNodes):
@@ -557,7 +620,7 @@
     try:
         task = gtask.parse_interface(module)
     except ScriptError as e:
-        e = EncodeString(e.value)
+        e = _encode_string(e.value)
         # for some reason this works well only if it is separate
         sys.stderr.write("%s\n" % module)
         sys.stderr.write("%s\n" % e)



More information about the grass-commit mailing list