commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] [gnuradio] 11/18: grc-refactor: move gui prefs to gui


From: git
Subject: [Commit-gnuradio] [gnuradio] 11/18: grc-refactor: move gui prefs to gui
Date: Sun, 24 Apr 2016 19:19:37 +0000 (UTC)

This is an automated email from the git hooks/post-receive script.

jcorgan pushed a commit to branch master
in repository gnuradio.

commit 3201557bfbed7ad81e0e5a34ece48bbd93ad709b
Author: Sebastian Koslowski <address@hidden>
Date:   Tue Feb 23 21:47:52 2016 +0100

    grc-refactor: move gui prefs to gui
---
 grc/core/Constants.py           |  25 +-------
 grc/core/Messages.py            |  20 ++-----
 grc/core/Platform.py            |  13 +----
 grc/core/generator/Generator.py |  89 ++++++-----------------------
 grc/core/utils/epy_block_io.py  |   2 +-
 grc/gui/ActionHandler.py        |  59 ++-----------------
 grc/gui/CMakeLists.txt          |   1 +
 grc/gui/Constants.py            |  10 ++++
 grc/gui/Executor.py             | 123 ++++++++++++++++++++++++++++++++++++++++
 grc/gui/Platform.py             |  12 ++--
 10 files changed, 176 insertions(+), 178 deletions(-)

diff --git a/grc/core/Constants.py b/grc/core/Constants.py
index b067886..9fe805f 100644
--- a/grc/core/Constants.py
+++ b/grc/core/Constants.py
@@ -18,28 +18,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
MA  02110-1301, USA
 """
 
 import os
-from os.path import expanduser
 import numpy
 import stat
-from gnuradio import gr
-
-_gr_prefs = gr.prefs()
-
-# Setup paths
-PATH_SEP = {'/': ':', '\\': ';'}[os.path.sep]
-
-HIER_BLOCKS_LIB_DIR = os.environ.get('GRC_HIER_PATH', 
expanduser('~/.grc_gnuradio'))
-
-PREFS_FILE = os.environ.get('GRC_PREFS_PATH', 
expanduser('~/.gnuradio/grc.conf'))
-PREFS_FILE_OLD = os.environ.get('GRC_PREFS_PATH', expanduser('~/.grc'))
-
-BLOCKS_DIRS = filter(  # filter blank strings
-    lambda x: x, PATH_SEP.join([
-        os.environ.get('GRC_BLOCKS_PATH', ''),
-        _gr_prefs.get_string('grc', 'local_blocks_path', ''),
-        _gr_prefs.get_string('grc', 'global_blocks_path', ''),
-    ]).split(PATH_SEP),
-) + [HIER_BLOCKS_LIB_DIR]
 
 # Data files
 DATA_DIR = os.path.dirname(__file__)
@@ -47,6 +27,7 @@ FLOW_GRAPH_DTD = os.path.join(DATA_DIR, 'flow_graph.dtd')
 BLOCK_TREE_DTD = os.path.join(DATA_DIR, 'block_tree.dtd')
 BLOCK_DTD = os.path.join(DATA_DIR, 'block.dtd')
 DEFAULT_FLOW_GRAPH = os.path.join(DATA_DIR, 'default_flow_graph.grc')
+DOMAIN_DTD = os.path.join(DATA_DIR, 'domain.dtd')
 
 # File format versions:
 #  0: undefined / legacy
@@ -58,7 +39,6 @@ DEFAULT_PARAM_TAB = "General"
 ADVANCED_PARAM_TAB = "Advanced"
 
 # Port domains
-DOMAIN_DTD = os.path.join(DATA_DIR, 'domain.dtd')
 GR_STREAM_DOMAIN = "gr_stream"
 GR_MESSAGE_DOMAIN = "gr_message"
 DEFAULT_DOMAIN = GR_STREAM_DOMAIN
@@ -73,9 +53,6 @@ BLOCK_DISABLED = 0
 BLOCK_ENABLED = 1
 BLOCK_BYPASSED = 2
 
-# User settings
-XTERM_EXECUTABLE = _gr_prefs.get_string('grc', 'xterm_executable', 'xterm')
-
 # File creation modes
 TOP_BLOCK_FILE_MODE = stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | 
stat.S_IRGRP | \
                       stat.S_IWGRP | stat.S_IXGRP | stat.S_IROTH
diff --git a/grc/core/Messages.py b/grc/core/Messages.py
index f794fdb..da50487 100644
--- a/grc/core/Messages.py
+++ b/grc/core/Messages.py
@@ -58,20 +58,12 @@ register_messenger(sys.stdout.write)
 # Special functions for specific program functionalities
 ###########################################################################
 def send_init(platform):
-    p = platform
-
-    def get_paths(x):
-        return os.path.abspath(os.path.expanduser(x)), x
-
-    send('\n'.join([
-        "<<< Welcome to %s %s >>>" % (p.config.name, p.config.version),
-        "",
-        "Preferences file: " + p.get_prefs_file(),
-        "Block paths:"
-    ] + [
-        "\t%s" % path + (" (%s)" % opath if opath != path else "")
-        for path, opath in map(get_paths, p.get_block_paths())
-    ]) + "\n")
+    msg = "<<< Welcome to {config.name} {config.version} >>>\n\n" \
+          "Block paths:\n\t{paths}\n"
+    send(msg.format(
+        config=platform.config,
+        paths="\n\t".join(platform.config.block_paths))
+    )
 
 
 def send_page_switch(file_path):
diff --git a/grc/core/Platform.py b/grc/core/Platform.py
index f6bb756..97e2b38 100644
--- a/grc/core/Platform.py
+++ b/grc/core/Platform.py
@@ -51,11 +51,8 @@ class Config(object):
     def __init__(self):
         self.prefs = self._get_prefs()
 
-        # Ensure hier and conf directories
         if not exists(self.hier_block_lib_dir):
             os.mkdir(self.hier_block_lib_dir)
-        if not exists(dirname(Constants.PREFS_FILE)):
-            os.mkdir(dirname(Constants.PREFS_FILE))
 
     @staticmethod
     def _get_prefs():
@@ -113,7 +110,6 @@ class Platform(Element):
             callback_finished=lambda: self.block_docstrings_loaded_callback()
         )
 
-        self._block_paths = list(set(Constants.BLOCKS_DIRS))
         self._block_dtd = Constants.BLOCK_DTD
         self._default_flow_graph = Constants.DEFAULT_FLOW_GRAPH
 
@@ -124,8 +120,8 @@ class Platform(Element):
         self.blocks = None
         self._blocks_n = None
         self._category_trees_n = None
-        self.domains = dict()
-        self.connection_templates = dict()
+        self.domains = {}
+        self.connection_templates = {}
 
         self._auto_hier_block_generate_chain = set()
 
@@ -215,7 +211,7 @@ class Platform(Element):
 
     def iter_xml_files(self):
         """Iterator for block descriptions and category trees"""
-        for block_path in map(lambda x: 
os.path.abspath(os.path.expanduser(x)), self._block_paths):
+        for block_path in self.config.block_paths:
             if os.path.isfile(block_path):
                 yield block_path
             elif os.path.isdir(block_path):
@@ -371,6 +367,3 @@ class Platform(Element):
 
     def get_colors(self):
         return [(name, color) for name, key, sizeof, color in 
Constants.CORE_TYPES]
-
-    def get_block_paths(self):
-        return self._block_paths
diff --git a/grc/core/generator/Generator.py b/grc/core/generator/Generator.py
index a303a6f..5c2fa6e 100644
--- a/grc/core/generator/Generator.py
+++ b/grc/core/generator/Generator.py
@@ -15,22 +15,18 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
USA
 
-import shlex
-import subprocess
-import sys
-import tempfile
-from distutils.spawn import find_executable
 
 import codecs
 import os
-import re  # for shlex_quote
+import tempfile
+
 from Cheetah.Template import Template
 
 from .FlowGraphProxy import FlowGraphProxy
 from .. import ParseXML, Messages
 from ..Constants import (
     TOP_BLOCK_FILE_MODE, BLOCK_FLAG_NEED_QT_GUI,
-    XTERM_EXECUTABLE, HIER_BLOCK_FILE_MODE, HIER_BLOCKS_LIB_DIR, BLOCK_DTD
+    HIER_BLOCK_FILE_MODE, BLOCK_DTD
 )
 from ..utils import expr_utils, odict
 
@@ -50,19 +46,16 @@ class Generator(object):
             flow_graph: the flow graph object
             file_path: the path to the grc file
         """
-        self._generate_options = flow_graph.get_option('generate_options')
-        if self._generate_options == 'hb':
+        self.generate_options = flow_graph.get_option('generate_options')
+        if self.generate_options == 'hb':
             generator_cls = HierBlockGenerator
-        elif self._generate_options == 'hb_qt_gui':
+        elif self.generate_options == 'hb_qt_gui':
             generator_cls = QtHierBlockGenerator
         else:
             generator_cls = TopBlockGenerator
 
         self._generator = generator_cls(flow_graph, file_path)
 
-    def get_generate_options(self):
-        return self._generate_options
-
     def __getattr__(self, item):
         """get all other attrib from actual generator object"""
         return getattr(self._generator, item)
@@ -87,10 +80,10 @@ class TopBlockGenerator(object):
         if not os.access(dirname, os.W_OK):
             dirname = tempfile.gettempdir()
         filename = self._flow_graph.get_option('id') + '.py'
-        self._file_path = os.path.join(dirname, filename)
+        self.file_path = os.path.join(dirname, filename)
 
     def get_file_path(self):
-        return self._file_path
+        return self.file_path
 
     def write(self):
         """generate output and write it to files"""
@@ -113,44 +106,12 @@ class TopBlockGenerator(object):
         for filename, data in self._build_python_code_from_template():
             with codecs.open(filename, 'w', encoding='utf-8') as fp:
                 fp.write(data)
-            if filename == self.get_file_path():
+            if filename == self.file_path:
                 try:
                     os.chmod(filename, self._mode)
                 except:
                     pass
 
-    def get_popen(self):
-        """
-        Execute this python flow graph.
-
-        Returns:
-            a popen object
-        """
-        run_command = self._flow_graph.get_option('run_command')
-        try:
-            run_command = run_command.format(
-                python=shlex_quote(sys.executable),
-                filename=shlex_quote(self.get_file_path()))
-            run_command_args = shlex.split(run_command)
-        except Exception as e:
-            raise ValueError("Can't parse run command {!r}: 
{}".format(run_command, e))
-
-        # When in no gui mode on linux, use a graphical terminal (looks nice)
-        xterm_executable = find_executable(XTERM_EXECUTABLE)
-        if self._generate_options == 'no_gui' and xterm_executable:
-            run_command_args = [xterm_executable, '-e', run_command]
-
-        # this does not reproduce a shell executable command string, if a 
graphical
-        # terminal is used. Passing run_command though shlex_quote would do it 
but
-        # it looks really ugly and confusing in the console panel.
-        Messages.send_start_exec(' '.join(run_command_args))
-
-        return subprocess.Popen(
-            args=run_command_args,
-            stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
-            shell=False, universal_newlines=True
-        )
-
     def _build_python_code_from_template(self):
         """
         Convert the flow graph to python code.
@@ -280,7 +241,7 @@ class TopBlockGenerator(object):
         }
         # Build the template
         t = Template(open(FLOW_GRAPH_TEMPLATE, 'r').read(), namespace)
-        output.append((self.get_file_path(), str(t)))
+        output.append((self.file_path, str(t)))
         return output
 
 
@@ -296,10 +257,12 @@ class HierBlockGenerator(TopBlockGenerator):
             file_path: where to write the py file (the xml goes into 
HIER_BLOCK_LIB_DIR)
         """
         TopBlockGenerator.__init__(self, flow_graph, file_path)
+        platform = flow_graph.get_parent()
+
         self._mode = HIER_BLOCK_FILE_MODE
-        self._file_path = os.path.join(HIER_BLOCKS_LIB_DIR,
-                                       self._flow_graph.get_option('id') + 
'.py')
-        self._file_path_xml = self._file_path + '.xml'
+        self.file_path = os.path.join(platform.config.hier_block_lib_dir,
+                                      self._flow_graph.get_option('id') + 
'.py')
+        self._file_path_xml = self.file_path + '.xml'
 
     def get_file_path_xml(self):
         return self._file_path_xml
@@ -394,7 +357,7 @@ class HierBlockGenerator(TopBlockGenerator):
         block_n['doc'] = "\n".join(field for field in (
             self._flow_graph.get_option('author'),
             self._flow_graph.get_option('description'),
-            self.get_file_path()
+            self.file_path
         ) if field)
         block_n['grc_source'] = str(self._flow_graph.grc_file_path)
 
@@ -425,22 +388,4 @@ class QtHierBlockGenerator(HierBlockGenerator):
             "\n#set $win = 'self.%s' % $id"
             "\n${gui_hint()($win)}"
         )
-        return n
-
-
-###########################################################
-# back-port from python3
-###########################################################
-_find_unsafe = re.compile(r'address@hidden:,./-]').search
-
-
-def shlex_quote(s):
-    """Return a shell-escaped version of the string *s*."""
-    if not s:
-        return "''"
-    if _find_unsafe(s) is None:
-        return s
-
-    # use single quotes, and put single quotes into double quotes
-    # the string $'b is then quoted as '$'"'"'b'
-    return "'" + s.replace("'", "'\"'\"'") + "'"
+        return n
\ No newline at end of file
diff --git a/grc/core/utils/epy_block_io.py b/grc/core/utils/epy_block_io.py
index e089908..c070e1c 100644
--- a/grc/core/utils/epy_block_io.py
+++ b/grc/core/utils/epy_block_io.py
@@ -38,7 +38,7 @@ def _blk_class(source_code):
     except Exception as e:
         raise ValueError("Can't interpret source code: " + str(e))
     for var in ns.itervalues():
-        if inspect.isclass(var)and issubclass(var, gr.gateway.gateway_block):
+        if inspect.isclass(var) and issubclass(var, gr.gateway.gateway_block):
             return var
     raise ValueError('No python block class found in code')
 
diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py
index 41eb6f1..139bbed 100644
--- a/grc/gui/ActionHandler.py
+++ b/grc/gui/ActionHandler.py
@@ -17,15 +17,14 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
-import os
-import subprocess
-from threading import Thread
 
-import gtk
 import gobject
+import gtk
+import os
+import subprocess
 
-from . import Dialogs, Preferences, Actions
-from .Constants import DEFAULT_CANVAS_SIZE, IMAGE_FILE_EXTENSION, GR_PREFIX
+from . import Dialogs, Preferences, Actions, Executor
+from .Constants import DEFAULT_CANVAS_SIZE, IMAGE_FILE_EXTENSION, GR_PREFIX, 
XTERM_EXECUTABLE
 from .FileDialogs import (OpenFlowGraphFileDialog, SaveFlowGraphFileDialog,
                           SaveReportsFileDialog, SaveScreenShotDialog,
                           OpenQSSFileDialog)
@@ -34,7 +33,6 @@ from .ParserErrorsDialog import ParserErrorsDialog
 from .PropsDialog import PropsDialog
 
 from ..core import Constants, ParseXML
-from ..core.Constants import XTERM_EXECUTABLE
 from ..core import Messages
 
 gobject.threads_init()
@@ -547,7 +545,7 @@ class ActionHandler:
                         Dialogs.MissingXTermDialog(XTERM_EXECUTABLE)
                     Preferences.xterm_missing(XTERM_EXECUTABLE)
                 if self.get_page().get_saved() and 
self.get_page().get_file_path():
-                    ExecFlowGraphThread(self)
+                    Executor.ExecFlowGraphThread(self)
         elif action == Actions.FLOW_GRAPH_KILL:
             if self.get_page().get_proc():
                 try:
@@ -654,48 +652,3 @@ class ActionHandler:
         Actions.FLOW_GRAPH_GEN.set_sensitive(sensitive)
         Actions.FLOW_GRAPH_EXEC.set_sensitive(sensitive)
         Actions.FLOW_GRAPH_KILL.set_sensitive(self.get_page().get_proc() is 
not None)
-
-class ExecFlowGraphThread(Thread):
-    """Execute the flow graph as a new process and wait on it to finish."""
-
-    def __init__ (self, action_handler):
-        """
-        ExecFlowGraphThread constructor.
-
-        Args:
-            action_handler: an instance of an ActionHandler
-        """
-        Thread.__init__(self)
-        self.update_exec_stop = action_handler.update_exec_stop
-        self.flow_graph = action_handler.get_flow_graph()
-        #store page and dont use main window calls in run
-        self.page = action_handler.get_page()
-        #get the popen
-        try:
-            self.p = self.page.get_generator().get_popen()
-            self.page.set_proc(self.p)
-            #update
-            self.update_exec_stop()
-            self.start()
-        except Exception, e:
-            Messages.send_verbose_exec(str(e))
-            Messages.send_end_exec()
-
-    def run(self):
-        """
-        Wait on the executing process by reading from its stdout.
-        Use gobject.idle_add when calling functions that modify gtk objects.
-        """
-        #handle completion
-        r = "\n"
-        while r:
-            gobject.idle_add(Messages.send_verbose_exec, r)
-            r = os.read(self.p.stdout.fileno(), 1024)
-        self.p.poll()
-        gobject.idle_add(self.done)
-
-    def done(self):
-        """Perform end of execution tasks."""
-        Messages.send_end_exec(self.p.returncode)
-        self.page.set_proc(None)
-        self.update_exec_stop()
diff --git a/grc/gui/CMakeLists.txt b/grc/gui/CMakeLists.txt
index 99140df..7e43553 100644
--- a/grc/gui/CMakeLists.txt
+++ b/grc/gui/CMakeLists.txt
@@ -25,6 +25,7 @@ GR_PYTHON_INSTALL(FILES
     Constants.py
     Connection.py
     Element.py
+    Executor.py
     FlowGraph.py
     Param.py
     Platform.py
diff --git a/grc/gui/Constants.py b/grc/gui/Constants.py
index 741c6fd..b891c5b 100644
--- a/grc/gui/Constants.py
+++ b/grc/gui/Constants.py
@@ -29,6 +29,16 @@ from gnuradio import gr
 prefs = gr.prefs()
 GR_PREFIX = gr.prefix()
 EDITOR = prefs.get_string('grc', 'editor', '')
+XTERM_EXECUTABLE = prefs.get_string('grc', 'xterm_executable', 'xterm')
+
+PREFS_FILE = os.environ.get(
+        'GRC_PREFS_PATH',
+        os.path.expanduser('~/.gnuradio/grc.conf')
+)
+PREFS_FILE_OLD = os.environ.get(
+        'GRC_PREFS_PATH',
+        os.path.expanduser('~/.grc')
+)
 
 # default path for the open/save dialogs
 DEFAULT_FILE_PATH = os.getcwd()
diff --git a/grc/gui/Executor.py b/grc/gui/Executor.py
new file mode 100644
index 0000000..96b95f4
--- /dev/null
+++ b/grc/gui/Executor.py
@@ -0,0 +1,123 @@
+# Copyright 2016 Free Software Foundation, Inc.
+# This file is part of GNU Radio
+#
+# GNU Radio Companion is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# GNU Radio Companion is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
USA
+
+import gobject
+import os
+import threading
+import shlex
+import subprocess
+import sys
+import re
+from distutils.spawn import find_executable
+
+from ..core import Messages
+from .Constants import XTERM_EXECUTABLE
+
+
+class ExecFlowGraphThread(threading.Thread):
+    """Execute the flow graph as a new process and wait on it to finish."""
+
+    def __init__(self, action_handler):
+        """
+        ExecFlowGraphThread constructor.
+
+        Args:
+            action_handler: an instance of an ActionHandler
+        """
+        threading.Thread.__init__(self)
+        self.update_exec_stop = action_handler.update_exec_stop
+        self.flow_graph = action_handler.get_flow_graph()
+        #store page and dont use main window calls in run
+        self.page = action_handler.get_page()
+        #get the popen
+        try:
+            self.p = self._popen()
+            self.page.set_proc(self.p)
+            #update
+            self.update_exec_stop()
+            self.start()
+        except Exception, e:
+            Messages.send_verbose_exec(str(e))
+            Messages.send_end_exec()
+
+    def _popen(self):
+        """
+        Execute this python flow graph.
+        """
+        run_command = self.flow_graph.get_option('run_command')
+        generator = self.page.get_generator()
+
+        try:
+            run_command = run_command.format(
+                python=shlex_quote(sys.executable),
+                filename=shlex_quote(generator.file_path))
+            run_command_args = shlex.split(run_command)
+        except Exception as e:
+            raise ValueError("Can't parse run command {!r}: 
{}".format(run_command, e))
+
+        # When in no gui mode on linux, use a graphical terminal (looks nice)
+        xterm_executable = find_executable(XTERM_EXECUTABLE)
+        if generator.generate_options == 'no_gui' and xterm_executable:
+            run_command_args = [xterm_executable, '-e', run_command]
+
+        # this does not reproduce a shell executable command string, if a 
graphical
+        # terminal is used. Passing run_command though shlex_quote would do it 
but
+        # it looks really ugly and confusing in the console panel.
+        Messages.send_start_exec(' '.join(run_command_args))
+
+        return subprocess.Popen(
+            args=run_command_args,
+            stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+            shell=False, universal_newlines=True
+        )
+
+    def run(self):
+        """
+        Wait on the executing process by reading from its stdout.
+        Use gobject.idle_add when calling functions that modify gtk objects.
+        """
+        #handle completion
+        r = "\n"
+        while r:
+            gobject.idle_add(Messages.send_verbose_exec, r)
+            r = os.read(self.p.stdout.fileno(), 1024)
+        self.p.poll()
+        gobject.idle_add(self.done)
+
+    def done(self):
+        """Perform end of execution tasks."""
+        Messages.send_end_exec(self.p.returncode)
+        self.page.set_proc(None)
+        self.update_exec_stop()
+
+
+###########################################################
+# back-port from python3
+###########################################################
+_find_unsafe = re.compile(r'address@hidden:,./-]').search
+
+
+def shlex_quote(s):
+    """Return a shell-escaped version of the string *s*."""
+    if not s:
+        return "''"
+    if _find_unsafe(s) is None:
+        return s
+
+    # use single quotes, and put single quotes into double quotes
+    # the string $'b is then quoted as '$'"'"'b'
+    return "'" + s.replace("'", "'\"'\"'") + "'"
diff --git a/grc/gui/Platform.py b/grc/gui/Platform.py
index 85a6872..cfd5ae3 100644
--- a/grc/gui/Platform.py
+++ b/grc/gui/Platform.py
@@ -20,16 +20,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
MA  02110-1301, USA
 import os
 import sys
 
-from .Element import Element
-
 from ..core.Platform import Platform as _Platform
-from ..core.Constants import PREFS_FILE, PREFS_FILE_OLD
 
 from .Block import Block as _Block
+from .Connection import Connection as _Connection
+from .Constants import PREFS_FILE, PREFS_FILE_OLD
+from .Element import Element
 from .FlowGraph import FlowGraph as _FlowGraph
 from .Param import Param as _Param
 from .Port import Port as _Port
-from .Connection import Connection as _Connection
 
 
 class Platform(Element, _Platform):
@@ -37,6 +36,11 @@ class Platform(Element, _Platform):
     def __init__(self):
         Element.__init__(self)
         _Platform.__init__(self)
+
+        # Ensure conf directories
+        if not os.path.exists(os.path.dirname(PREFS_FILE)):
+            os.mkdir(os.path.dirname(PREFS_FILE))
+
         self._move_old_pref_file()
         self._prefs_file = PREFS_FILE
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]