From 5dc2febced71b7fe695560bc23b0f4bcbc534fba Mon Sep 17 00:00:00 2001 From: Serge Rehbinder Date: Thu, 28 Jan 2016 16:40:10 +0100 Subject: [PATCH] add options edit, list, and copy to config command --- data/site.pyconf | 1 + src/common/__init__.py | 10 +++- src/common/fileSystem.py | 46 +++++++++++++++ src/config.py | 118 ++++++++++++++++++++++++++++++++++++--- src/salomeTools.py | 6 +- 5 files changed, 170 insertions(+), 11 deletions(-) create mode 100644 src/common/fileSystem.py diff --git a/data/site.pyconf b/data/site.pyconf index 9a58fcd..97135df 100644 --- a/data/site.pyconf +++ b/data/site.pyconf @@ -6,6 +6,7 @@ SITE : config : { configPath : ["/home/salome/SPN_PRIVATE/sat5dev_Applications"] + copy_prefix : "LOCAL_" } } diff --git a/src/common/__init__.py b/src/common/__init__.py index 3eeca22..3a597b9 100644 --- a/src/common/__init__.py +++ b/src/common/__init__.py @@ -22,10 +22,18 @@ from . import config_pyconf from . import architecture from . import printcolors from . import options +from . import fileSystem class SatException(Exception): pass def ensure_path_exists(p): if not os.path.exists(p): - os.mkdir(p) \ No newline at end of file + os.mkdir(p) + +def check_config_has_application( config, details = None ): + if 'APPLICATION' not in config: + message = _("An APPLICATION is required. Use 'config --list' to get the list of available applications.\n") + if details : + details.append(message) + raise SatException( message ) \ No newline at end of file diff --git a/src/common/fileSystem.py b/src/common/fileSystem.py new file mode 100644 index 0000000..71c0046 --- /dev/null +++ b/src/common/fileSystem.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +#-*- coding:utf-8 -*- +# Copyright (C) 2010-2013 CEA/DEN +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +''' +In this file : all functions that do a system call, like open a browser or an editor, or call a git command +''' + +import sys +import subprocess + + +def show_in_editor(editor, filePath): + '''open filePath using editor. + :param editor str: The editor to use. + :param filePath str: The path to the file to open. + ''' + # default editor is vi + if editor is None or len(editor) == 0: + editor = 'vi' + + if '%s' not in editor: + editor += ' %s' + + try: + # launch cmd using subprocess.Popen + cmd = editor % filePath + p = subprocess.Popen(cmd, shell=True) + p.communicate() + except: + sys.stderr.write("Unable to edit file %s\n" % filePath) + \ No newline at end of file diff --git a/src/config.py b/src/config.py index d62cec1..32dda39 100644 --- a/src/config.py +++ b/src/config.py @@ -23,12 +23,23 @@ import datetime import glob import re import shutil +import gettext import common +# internationalization +srcdir = os.path.dirname(os.path.realpath(__file__)) +gettext.install('salomeTools', os.path.join(srcdir, 'common', 'i18n')) + # Define all possible option for config command : sat config parser = common.options.Options() -parser.add_option('v', 'value', 'string', 'value', "print the value of CONFIG_VARIABLE.") +parser.add_option('v', 'value', 'string', 'value', _("print the value of CONFIG_VARIABLE.")) +parser.add_option('e', 'edit', 'boolean', 'edit', _("edit the product configuration file.")) +parser.add_option('l', 'list', 'boolean', 'list',_("list all available applications.")) +parser.add_option('c', 'copy', 'boolean', 'copy', + _("""copy a config file to the personnal config files directory. +\tWARNING the included files are not copied. +\tIf a name is given the new config file takes the given name.""")) ''' class MergeHandler: @@ -206,7 +217,10 @@ class ConfigManager: if "site.pyconf" in e : e += "\nYou can copy data" + cfg.VARS.sep + "site.template.pyconf to data" + cfg.VARS.sep + "site.pyconf and edit the file" raise common.SatException( e ); - + + # add user local path for configPath + site_cfg.SITE.config.configPath.append(os.path.join(cfg.VARS.personalDir, 'Applications'), "User applications path") + merger.merge(cfg, site_cfg) for rule in self.get_command_line_overrides(options, ["SITE"]): @@ -261,18 +275,17 @@ class ConfigManager: if already_exisiting_pyconf_file: # copy shutil.copyfile( already_exisiting_pyconf_file, self.user_config_file_path ) - cfg = common.config_pyconf.Config(open(self.user_config_file_path)) else: # create from scratch self.createConfigFile(config) - def getAlreadyExistingUserPyconf(self, dir, sat_version ): + def getAlreadyExistingUserPyconf(self, userDir, sat_version ): '''Get a pyconf file younger than the given sat version in the given directory The file basename can be one of salometools-.pyconf or salomeTools.pyconf Returns the file path or None if no file has been found. ''' file_path = None # Get a younger pyconf version - pyconfFiles = glob.glob( os.path.join(dir, 'salomeTools-*.pyconf') ) + pyconfFiles = glob.glob( os.path.join(userDir, 'salomeTools-*.pyconf') ) sExpr = "^salomeTools-(.*)\.pyconf$" oExpr = re.compile(sExpr) younger_version = None @@ -285,9 +298,9 @@ class ConfigManager: # Build the pyconf filepath if younger_version : - file_path = os.path.join( dir, 'salomeTools-%s.pyconf'%younger_version ) - elif os.path.isfile( os.path.join(dir, 'salomeTools.pyconf') ): - file_path = os.path.join( dir, 'salomeTools.pyconf' ) + file_path = os.path.join( userDir, 'salomeTools-%s.pyconf'%younger_version ) + elif os.path.isfile( os.path.join(userDir, 'salomeTools.pyconf') ): + file_path = os.path.join( userDir, 'salomeTools.pyconf' ) return file_path @@ -384,6 +397,95 @@ def description(): def run(args, runner): (options, args) = parser.parse_args(args) + + # case : print a value of the config if options.value: + if options.value == ".": + # if argument is ".", print all the config + for val in sorted(runner.cfg.keys()): + print_value(runner.cfg, val, True) + return print_value(runner.cfg, options.value, True, level=0, show_full_path=False) + return + + # case : edit user pyconf file or application file + elif options.edit: + editor = runner.cfg.USER.editor + if 'APPLICATION' not in runner.cfg: # edit user pyconf + usercfg = os.path.join(runner.cfg.VARS.personalDir, 'salomeTools-%s.pyconf'%runner.cfg.INTERNAL['sat_version']) + common.fileSystem.show_in_editor(editor, usercfg) + else: + # search for file .pyconf and open it + for path in runner.cfg.SITE.config.configPath: + pyconf_path = os.path.join(path, runner.cfg.VARS.application + ".pyconf") + if os.path.exists(pyconf_path): + common.fileSystem.show_in_editor(editor, pyconf_path) + break + + # case : copy an existing .pyconf to ~/.salomeTools/Applications/LOCAL_.pyconf + elif options.copy: + # product is required + common.check_config_has_application( runner.cfg ) + + # get application file path + source = runner.cfg.VARS.application + '.pyconf' + source_full_path = "" + for path in runner.cfg.SITE.config.configPath: + # ignore personal directory + if path == runner.cfg.VARS.personalDir: + continue + # loop on all directories that can have pyconf applications + zz = os.path.join(path, source) + if os.path.exists(zz): + source_full_path = zz + break + + if len(source_full_path) == 0: + raise common.SatException(_("Config file for product %s not found\n") % source) + else: + if len(args) > 0: + # a name is given as parameter, use it + dest = args[0] + elif 'copy_prefix' in runner.cfg.SITE.config: + # use prefix + dest = runner.cfg.SITE.config.copy_prefix + runner.cfg.VARS.application + else: + # use same name as source + dest = runner.cfg.VARS.application + + # the full path + dest_file = os.path.join(runner.cfg.VARS.personalDir, 'Applications', dest + '.pyconf') + if os.path.exists(dest_file): + raise common.SatException(_("A personal application '%s' already exists") % dest) + + # perform the copy + shutil.copyfile(source_full_path, dest_file) + print(_("%s has been created.") % dest_file) + + # case : display all the available pyconf applications + elif options.list: + lproduct = list() + # search in all directories that can have pyconf applications + for path in runner.cfg.SITE.config.configPath: + # print a header + sys.stdout.write("------ %s\n" % common.printcolors.printcHeader(path)) + + if not os.path.exists(path): + sys.stdout.write(common.printcolors.printcError(_("Directory not found")) + "\n") + else: + for f in sorted(os.listdir(path)): + # ignore file that does not ends with .pyconf + if not f.endswith('.pyconf'): + continue + + appliname = f[:-len('.pyconf')] + if appliname not in lproduct: + lproduct.append(appliname) + if path.startswith(runner.cfg.VARS.personalDir): + sys.stdout.write("%s*\n" % appliname) + else: + sys.stdout.write("%s\n" % appliname) + + sys.stdout.write("\n") + \ No newline at end of file diff --git a/src/salomeTools.py b/src/salomeTools.py index ccfa5eb..78dc0af 100755 --- a/src/salomeTools.py +++ b/src/salomeTools.py @@ -34,8 +34,9 @@ import config srcdir = os.path.dirname(os.path.realpath(__file__)) # load resources for internationalization -es = gettext.translation('salomeTools', os.path.join(srcdir, 'common', 'i18n')) -es.install() +#es = gettext.translation('salomeTools', os.path.join(srcdir, 'common', 'i18n')) +#es.install() +gettext.install('salomeTools', os.path.join(srcdir, 'common', 'i18n')) def find_command_list(dirPath): ''' Parse files in dirPath that end with .py : it gives commands list @@ -238,6 +239,7 @@ if __name__ == "__main__": command = args[0] # get dynamically the command function to call fun_command = sat.__getattr__(command) + # call the command with two cases : mode debug or not if options.debug_mode: # call classically the command and if it fails, show exception and stack (usual python mode) code = fun_command(' '.join(args[1:])) -- 2.39.2