diff options
author | Sérgio Almeida <mephx.x@gmail.com> | 2009-07-27 18:28:46 +0100 |
---|---|---|
committer | Sérgio Almeida <mephx.x@gmail.com> | 2009-07-27 18:28:46 +0100 |
commit | 2ce51ba0fb303c4c1953559963255125805aefce (patch) | |
tree | fb4ed329765bdbd6ad87b5d4364e6b268babbcfa | |
parent | Changed modules to plain python (diff) | |
download | uselect-2ce51ba0fb303c4c1953559963255125805aefce.tar.gz uselect-2ce51ba0fb303c4c1953559963255125805aefce.tar.bz2 uselect-2ce51ba0fb303c4c1953559963255125805aefce.zip |
Lacked -a on last commit
-rw-r--r-- | install.sh | 5 | ||||
-rw-r--r-- | modules/gcc.py | 4 | ||||
-rw-r--r-- | modules/python.py | 53 | ||||
-rw-r--r-- | uio.py | 79 | ||||
-rw-r--r-- | umodule.py | 497 | ||||
-rwxr-xr-x | uselect.py | 54 |
6 files changed, 447 insertions, 245 deletions
@@ -2,14 +2,15 @@ # # Uselect Temporary Installer # +# if [ "$(id -u)" != "0" ]; then echo "uselect's $0 must be run as root!" exit 1 fi -rm -rf /usr/bin/uselect -rm -rf /usr/share/uselect +rm -f /usr/bin/uselect +rm -f /usr/share/uselect mkdir /usr/share/uselect cp -R * /usr/share/uselect/ ln -s /usr/share/uselect/uselect.py /usr/bin/uselect diff --git a/modules/gcc.py b/modules/gcc.py index ece02f4..fc18cb8 100644 --- a/modules/gcc.py +++ b/modules/gcc.py @@ -9,9 +9,9 @@ module = Module(name = "gcc", description = "Python GCC Version Switcher", versi bin = Action (name = 'bin', description = "Change GCC's Version", type = "sym") # Define a Symlinking Action gcc = Link(alias = "gcc", target = "/usr/bin/gcc", prefix = "/usr/bin/", regexp = "gcc-([0-9]+\.[0-9]+$)") -gcc_config = Link(alias = "gcc-config", target = "/usr/bin/gcc-config", prefix = "/usr/bin/", regexp = "gcc-config([0-9]+\.[0-9]+$)") +#gcc_config = Link(alias = "gcc-config", target = "/usr/bin/gcc-config", prefix = "/usr/bin/", regexp = "gcc-config([0-9]+\.[0-9]+$)") -gcc.add_link(gcc_config) # For inheritance +#gcc.add_link(gcc_config) # For inheritance testing bin.add_link(gcc) # Adding The Link to the action module.add_action(bin) #Adding the action to the module diff --git a/modules/python.py b/modules/python.py index e6115fc..c850505 100644 --- a/modules/python.py +++ b/modules/python.py @@ -6,15 +6,60 @@ from umodule import * module = Module(name = "python", description = "Python Version Switcher", version = "0.1", author ="mephx.x@gmail.com") # We define the module -bin = Action (name = 'bin', description = "Change Python's Version", type = "sym") # Define a Symlinking Action + +bin = Action (name = 'bin', description = "Change Python's Version", type = "sym") # Define a Symlinking Action python = Link(alias = "python", target = "/usr/bin/python", prefix = "/usr/bin/", regexp = "python([0-9]+\.[0-9]+$)") python_config = Link(alias = "python-config", target = "/usr/bin/python-config", prefix = "/usr/bin/", regexp = "python([0-9]+\.[0-9]+)-config$") -python_config2 = Link(alias = "python-config", target = "/usr/bin/python-config", prefix = "/usr/bin/", regexp = "python([0-9]+\.[0-9]+)-config$") - python.add_link(python_config) # For inheritance -#python_config.add_link(python_config2) # For further inheritance test bin.add_link(python) # Adding The Link to the action + module.add_action(bin) #Adding the action to the module +test = Action (name = 'test', description = 'Test Python Environment', type = 'runnable') + +test.add_parameter('<times>') +test.add_parameter('[<what>]') # optional notation + +test.add_usage("""#!/usr/bin/python +print "Python Test will echo <times> * <what>" +print "Usage can be multi-line Yay!" +print "" +for i in range(5): + print "Usage can have dynamic options! " + str(i) +""") + +test.add_code("""#!/usr/bin/python +import sys + +def is_number(s): + try: + int(s) + return True + except ValueError: + return False + +argv = sys.argv[1:] +times = sys.argv[1:][0] +if is_number(times): + times = int(times) + if len(argv) >= 2: + what = sys.argv[1:][1] + else: + what = 'Hello World...' + print str(what) * times +else: + print 'Invalid Option(s)' + exit(1) +exit(0) +""") + + +module.add_action(test) + +env = Action (name = 'env', description = 'Some env test', type = 'env') +path_var = env.get_var(name = 'PATH') + +path_var.add_value(value = '~/.uselect/bin/') +module.add_action(env) @@ -8,6 +8,7 @@ import os import pwd import stat +import subprocess # Aligning space = ' ' @@ -18,7 +19,12 @@ bold = lime = red = reset = yellow = notice = '' error = warning = bullet = ok = highlight = '' verbose = False - +class Counter: + + def __init__(self): + self.count = 0 + self.level = 0 + class FileSystem: """ FileSystem Class """ def __init__(self): @@ -31,7 +37,18 @@ class FileSystem: self.environment += 'bin/' if not os.path.exists(self.environment): os.mkdir(self.environment) - + + def get_env(self): + env = [] + for param in os.environ.keys(): + env.append([param,os.environ[param]]) + return env + + def set_env(self, env): + """ Re-set a environment variable """ + # Only changes uselects environment !BROKEN! + os.environ[env.name] = env.to_string() + def read_file(self, path): """ Reads a File and returns lines[] """ file = open(path,'r') @@ -57,7 +74,8 @@ class FileSystem: return for arg in args: cmd += ' ' + arg - return os.popen(cmd).readlines() + # TODO: change to subprocess.Popen + return os.popen(cmd) def delete_file(self, path): """ Deletes file in "path" """ @@ -86,7 +104,9 @@ class FileSystem: return os.path.exists(path) def real_path(self, path): return os.path.realpath(path) - + + + class PrintSystem: """ PrintSystem Class """ @@ -129,14 +149,18 @@ class PrintSystem: print line return - def print_table(self,list, _verbose = False): - """ Prints Lists of the form list[[a,b]] """ + def print_table(self,list, _verbose = False, level = 0): + """ Prints Lists of the form list[[a,b]]. Can be nested lists.""" global verbose + if _verbose and not verbose: return for item in list: - print(' ' + item[0] + reset + '\r' + 3 * right + item[1]) - return + if isinstance(item[0], basestring): + print ' ', + print(level * ' ' + space + item[0] + reset + '\r' + 3 * right + item[1]) + else: + self.print_table(item, _verbose, level + 1) def print_exception(self, exception, iswarning = False): """ Prints Exceptions in a standart way """ @@ -146,20 +170,36 @@ class PrintSystem: type = error + ' Error! ' self.print_line('\n' + type + str(exception) + '\n') + def format_action(self, action): table = [] - if action.parameters != '': + if action.type in ['sym','path']: + table = self.format_options(action.options) + elif action.type in ['runnable','env']: for line in action.usage: table.append([line,'']) - table.append(['','']) - count = 1 - for option in action.options: - table.append([option[1] + space + \ - eval(option[0]),'']) - count += 1 - return table + + def format_options(self, options, counter = None): + table = [] + for option in options: + if isinstance(option, list) and not isinstance(option[0], int): + sub = self.format_options(option) + table.append(sub) + else: + table.append([str(option[0]) + ' - ' + option[1] + ' - ' + eval(option[2]),'']) + return table + # Screen Functions + + # For debug + def print_nested(self, _list, level = 0): + for item in _list: + if isinstance(item, list): + self.print_nested(item, level + 1) + else: + print level/2 * '*' + ' ' + str(item) + def print_ui(self, module = None, modules = None, \ action = None, args = None): if module == None: @@ -196,7 +236,6 @@ class PrintSystem: def print_module(self, module): self.print_line(bold + lime + 'Module' + space + reset \ + bold +module.name + lime + ':' + reset) - module.get_actions() self.print_line('Author:' + space + module.author + space \ + 'Version:' + space + module.version) @@ -230,16 +269,18 @@ class PrintSystem: def print_usage(self, module = None, action = None): """ General Usage Printer """ + options = '' if module != None: module_name = module.name else: module_name = '<module>' if action != None: action_name = action.name - options = action.parameters + for parameter in action.parameters: + options += parameter + space else: action_name = '<action>' - options = '<options>' + self.print_line(bold + lime + 'Usage:' + reset + ' uselect <options> ' + module_name \ + space + action_name + space + options) @@ -8,106 +8,144 @@ import re import os +from uio import PrintSystem +from uio import FileSystem +from uio import Counter + +filesystem = FileSystem() +printsystem = PrintSystem() + modules_dir = '/usr/share/uselect/modules/' class Action: + def __init__(self, name = None, lines = None, description = None, type = None): - def __init__(self, name, lines, _filesystem): - - self.filesystem = _filesystem + self.description = description self.name = name - self.lines = lines self.output = [] self.usage = [] self.options = [] - - for line in self.lines: - match = re.match('description "(.*)"', line.lstrip()) - if match: - self.description = match.group(1) - continue - match = re.match('type (.*)', line.lstrip()) - if match: - type = match.group(1) - continue - + self.type = type + if type == 'runnable': self.__class__ = Runnable + elif type == 'env': + self.__class__ = Env elif type == 'sym': if filesystem.uid != 'root': self.__class__ = Path else: self.__class__ = Sym - self.build() + else: + raise UserWarning('Action "' + name + '" has no type set!') + + self.setup() class Runnable(Action): def do_action(self, args): - path = '/tmp/' + self.filename - self.filesystem.write_file(path, self.code) - self.filesystem.make_exec_file(path) - for line in self.filesystem.execute_cmd(path,args): - self.output.append(line[:-1]) - self.filesystem.delete_file(path) - for line in self.output: - self.options.append(['bold', line]) - - def get_code(self): - i = 0 - for line in self.lines: - match = re.match('file (.*) {', line.lstrip()) - if match: - ident = 1 - for char in line: - if char == '\t': - ident += 1 - self.filename = match.group(1) - for line in self.lines[i+1:]: - line = line.rstrip() - line = line.replace('\t', '', ident) - match = re.match('} ' + self.filename, line) - if match: - self.code.append('') - break - self.code.append(line) - i += 1 + if len(args) != 0: + path = '/tmp/' + self.name + filesystem.write_file(path, self.code) + filesystem.make_exec_file(path) + for line in filesystem.execute_cmd(path,args).readlines(): + self.output.append(line[:-1]) + filesystem.delete_file(path) - def build(self): + def add_parameter(self, parameter): + """ + Adds Usage Parameters. + """ + self.parameters.append(parameter) + + def add_usage(self, usage): + """ + Adds Usage Code. + """ + usage = usage.split('\n') + args = [] + path = '/tmp/' + self.name + filesystem.write_file(path, usage) + filesystem.make_exec_file(path) + for line in filesystem.execute_cmd(path,args): + self.usage.append(line[:-1]) + filesystem.delete_file(path) + + def add_code(self, lines = None): + """ + Add Code. + """ + lines = lines.split('\n') + self.code = lines + + def setup(self): self.code = [] - self.get_code() - for line in self.lines: - match = re.match('parameters "(.*)"', line.lstrip()) - if match: - self.parameters = match.group(1) - continue - match = re.match('usage "(.*)"', line.lstrip()) - if match: - self.usage.append(match.group(1)) - continue + self.parameters = [] + self.usage = [] + + def build(self): + + return + class Link: - def __init__(self, name, source_dir, source_regexp, source_target, \ - destination, _filesystem): + def add_link(self, link = None): + """ + Add a sub-link. + """ + self.links.append(link) + link.parent = self + + def __init__(self, lines = None, alias = None, target = None, prefix = None, regexp = None, sufix = ''): - self.name = name - self.destination = destination + self.alias = alias + self.target = prefix + alias + self.prefix = prefix + self.sufix = sufix + self.regexp = regexp self.targets = [] self.status = [] - self.filesystem = _filesystem + self.links = [] + self.destination = self.prefix + self.alias + + + def get_links(self, counter = None): + """ + Builds a nested list with the Link's hierarchy. + """ + links = [] + target = [] + if self.links == []: + return + for link in self.links: + if len(link.targets) == 0: + raise UserWarning('Link "' + link.alias \ + + '" has no targets!') + for i in range(len(link.targets)): + target.append([counter.count, link, i]) + counter.count += 1 + sub_links = link.get_links(counter) + if sub_links != None: + target.append(sub_links) + links.append(target) + return links - for dir in self.filesystem.list_dir(source_dir): - match = re.match(source_regexp, dir) + def build(self): + for link in self.links: + link.build() + for dir in filesystem.list_dir(self.prefix): + match = re.match(self.regexp, dir) if match: - source = source_dir + match.group(0) + source_target + source = self.prefix + match.group(0) + self.sufix self.targets.append(source) - if self.filesystem.path_exists(destination): - if self.filesystem.real_path( \ - self.filesystem.environment + self.name) == \ + if filesystem.path_exists(self.destination): + if filesystem.real_path( \ + filesystem.environment + self.alias) == \ source: self.status.append('notice') - elif self.filesystem.real_path(destination) == source: + elif filesystem.real_path(self.destination) == source: self.status.append('ok') else: self.status.append('warning') @@ -118,157 +156,228 @@ class Link: class Sym(Action): + def build_options(self, links): + """ + Builds available options for PrintSystem. + """ + options = [] + for link in links: + if link == []: + options.append([0, 'No Targets Found!', 'error']) + elif isinstance(link, list) and not isinstance(link[0], int): + options.append(self.build_options(link)) + else: + count = link[0] + i = link[2] + link = link[1] + options.append([count, link.targets[i], link.status[i]]) + return options + - def get_links(self): - for line in self.lines: - match = re.match('sym (.*) (.*) (.*) (.*) (.*)', line.lstrip()) - if match: - name = match.group(1) - source_dir = match.group(3) - source_regexp = match.group(4) - if match.group(5) == '*': - source_target = '' + + def get_targets(self, links, option, family = []): + """ + Builds a nested list of targets. + """ + parent = None + for link in links: + if isinstance(link, list) and not isinstance(link[0], int): + if self.get_targets(link, option, family): + if parent != None: + family.append(parent) + return family else: - source_target = match.group(5) - destination = match.group(2) - self.links.append(Link(name, source_dir, source_regexp,\ - source_target, destination, self.filesystem)) - + family = [] + elif isinstance(link, list) and isinstance(link[0], int): + if option == link[0]: + family.append(link) + return True + else: + parent = link + def do_action(self, args): + """ + Implementation of do_action() for Sym. + """ + links = [] + + counter = Counter() + + for link in self.links: + target = [] + if len(link.targets) == 0: + raise UserWarning('Link "' + link.alias \ + + '" has no targets!') + for i in range(len(link.targets)): + target.append([counter.count, link,i]) + counter.count +=1 + sub_links = link.get_links(counter) + if sub_links != None: + target.append(sub_links) + links.append(target) + + self.options = self.build_options(links) + if len(args) != 0: - if args[0] == 'clear': - for link in self.links: - self.filesystem.delete_file(link.destination) - elif len(args) >= 1: - targets = [] - option = int(args[0]) -1 - for link in self.links: - for i in range(len(link.targets)): - targets.append([link.targets[i], \ - link.destination]) - if option >= 0 and option < len(targets): - self.filesystem.create_symlink(targets[option][0], \ - targets[option][1]) - self.output.append('Setting ' + targets[option][0] \ - + ' success!') - else: - raise UserWarning('Invalid Option "' \ - + args[0] + '"!') - else: - raise UserWarning('Invalid Option "' + args[0] \ - + '"!') + if len(args) >= 1: + for arg in args: + + targets = self.get_targets(links, int(arg)) + + print targets + + if targets != None: + for target in targets: + self.do_target(target) + else: + raise UserWarning('Invalid Option "' + args[0] \ + + '"!') else: - for link in self.links: - for i in range(len(link.targets)): - self.options.append([link.status[i],str(i+1) + ' - ' + \ - link.targets[i]]) - self.parameters = '<target>' + self.parameters = ['<target>','...','<target>'] self.usage.append('Available ' + self.name + ' targets:' ) - - def build(self): + + def do_target(self, target, clear = False): + """ + Activate/Deactivate a target. + """ + i = target[2] + link = target[1] + if clear: + filesystem.delete_file(link.destination) + self.output.append('Unsetting ' + link.destination\ + + ' success!') + else: + filesystem.create_symlink(link.targets[i], \ + link.destination) + self.output.append('Setting ' + link.targets[i]\ + + ' success!') + + def add_link(self, link = None): + """ + Add sub-link. + """ + self.links.append(link) + def setup(self): self.links = [] - self.get_links() + + def build(self): + self.parameters = ['<target>', '(...)', '<target>'] + for link in self.links: + link.build() + +class Var(): + def __init__(self, var, filesystem): + filesystem = filesystem + self.name = var + self.values = [] + + def add_values(self, values, separator = ':', active = True): + """ + Parses a line of values and adds the values. + """ + values = values.split(separator) + for value in values: + self.add_value(value, active) + + def add_value(self, value, active = False): + """ + Add a value. + """ + self.values.append([value, active]) + + def export(self): + filesystem.set_env(self) + + def to_string(self, separator = ':'): + """ + Builds a line of values. + """ + string = '' + for value in self.values: + string += value + separator + return string + + +class Env(Action): + + def do_action(self, args):a + for var in self.vars: + for value in var.values: + if not value[1]: + self.usage.append(var.name) + for value in var.values: + self.usage.append(' ' + value[0]) + + def get_var(self, name): + """ + Gets a var by name. Inits the var if not found. + """ + for var in self.vars: + if var.name == name: + return var + var = Var(name, filesystem) + self.vars.append(var) + return var + + def setup(self): + self.vars = [] + + def build(self): + env = filesystem.get_env() + for var in env: + _var = self.get_var(var[0]) + _var.add_values(var[1]) + self.parameters = ['<varname>', '(...)', '<target>'] + + class Path(Action, Sym): - def do_action(self, args): - if len(args) != 0: - if args[0] == 'clear': - home = self.filesystem.get_home() - for link in self.links: - self.filesystem.delete_file(home + '.uselect/bin/' \ - + link.name) - elif len(args) >= 1: - options = [] - choice = int(args[0]) - 1 - for link in self.links: - for i in range(len(link.targets)): - options.append([link.targets[i], \ - link.destination]) - if choice >= 0 and choice < len(options): - self.filesystem.create_symlink( \ - options[choice][0], - self.filesystem.environment + \ - link.name) - self.output.append('Setting ' + options[choice][0] \ - + ' success!') - else: - raise UserWarning('Invalid Option "' \ - + args[0] + '"!') - else: - raise UserWarning('Invalid Option "' + args[0] \ - + '"!') - else: - for link in self.links: - for i in range(len(link.targets)): - self.options.append([link.status[i],str(i+1) + ' - ' + \ - link.targets[i]]) - self.parameters = '<target>' - self.usage.append('Available ' + self.name + ' targets:' ) - return + def do_target(self, target, clear = False): + """ + Implementation of do_target for Path. + Activates/Deactivates targets. + """ + i = target[2] + link = target[1] + filesystem.create_symlink(link.targets[i], \ + filesystem.environment + link.alias) + self.output.append('Setting ' + link.targets[i] \ + + ' success!') class Module(): - def __init__(self, name, _filesystem): + def __init__(self, name = None , description = None , version = 'Undefined', author = 'Undefined'): global filesystem - filesystem = _filesystem self.name = name - self.version = 'Unknown' - self.author = 'Anonymous' - self.description = name + ' has no description! ' - self.path = modules_dir + self.name + '.uselect' - self.lines = filesystem.read_file(self.path) - self.parse_module(name) + filesystem = filesystem + self.description = description + self.version = version + self.author = author self.actions = [] + return + + + def add_action(self, action = None): + """ + Adds an action to the module. + """ + if action != None: + self.actions.append(action) + else: + raise UserWarning('You must not add an empty action!') - def parse_module(self, name): - for line in self.lines: - line = line.lstrip() - match = re.match('description "(.*)"', line) - if match: - self.description = match.group(1) - continue - match = re.match('version "(.*)"', line) - if match: - self.version = match.group(1) - continue - match = re.match('author "(.*)"', line) - if match: - self.author = match.group(1) - continue - match = re.match('} ' + name, line) - if match: - break - def get_action(self, name): + """ + Gets an action by name. + """ i = 0 - self.get_actions() for action in self.actions: if action.name == name: return action raise Exception('No such action "' + name + '"!') - def get_actions(self): - i = 0 - for line in self.lines: - match = re.match('(\w*) action (\w*)', line.lstrip()) - if match: - wideness = match.group(1) - if wideness == "system" and filesystem.uid != "root": - continue - name = match.group(2) - u = 0 - for line in self.lines[i:]: - match = re.match('} ' + name + '\w*', line) - if match: - lines = self.lines[i:i+u+1] - action = Action(name, lines, filesystem) - self.actions.append(action) - break - u += 1 - if name == '(\w*)': - break - i += 1 + @@ -12,38 +12,43 @@ import stat import string import traceback -from umodule import Module -from uio import PrintSystem -from uio import FileSystem - +from umodule import * +from uio import * + verbose = False version = '0.2' modules_dir = '/usr/share/uselect/modules/' + class UniversalSelectTool: - printsystem = PrintSystem() - filesystem = FileSystem() - def __init__(self): + return def get_modules(self): - list = self.filesystem.list_dir(modules_dir) self.modules = [] - for file in list: - match = re.match('(.*).uselect', file) + for module in filesystem.list_dir(modules_dir): + if re.match('__init__.py$', module): + continue + match = re.match('(.*).py$', module) if match: - self.modules.append(Module(match.group(1), self.filesystem)) + import modules + modname = match.group(1) + modpath = 'modules.'+ modname + __import__(modpath) + module = eval(modpath + '.module') + self.modules.append(module) + def get_module(self, name): - if not os.path.exists(modules_dir + name + '.uselect'): - raise Exception('Module ' + name + ' not found!') - return - else: - module = Module(name, self.filesystem) - return module + import modules + modname = name + modpath = 'modules.'+ modname + __import__(modpath) + module = eval(modpath + '.module') + return module def parse_argv(self, argv): global profile, verbose, version @@ -51,17 +56,17 @@ class UniversalSelectTool: modules = None action = None args = None - self.printsystem.use_colors(True) + printsystem.use_colors(True) for arg in argv: if arg == '-v': verbose = True - self.printsystem.verbose() + printsystem.verbose() argv = argv[1:] elif arg == '-nc': - self.printsystem.use_colors(False) + printsystem.use_colors(False) argv = argv[1:] elif arg == '-version': - self.printsystem.print_version(version) + printsystem.print_version(version) argv = argv[1:] if len(argv) < 1: self.get_modules() @@ -71,6 +76,7 @@ class UniversalSelectTool: elif len(argv) >= 2: module = self.get_module(argv[0]) action = module.get_action(argv[1]) + action.build() action.do_action(argv[2:]) if len(argv) == 2: argv = None @@ -84,12 +90,12 @@ def main(): uselect = UniversalSelectTool() try: list = uselect.parse_argv(sys.argv[1:]) - uselect.printsystem.print_ui(module = list[0], \ + printsystem.print_ui(module = list[0], \ modules = list[1], args = list[2], action = list[3]) except UserWarning, warning: - uselect.printsystem.print_exception(warning, True) + printsystem.print_exception(warning, True) except Exception, exception: - uselect.printsystem.print_exception(exception) + printsystem.print_exception(exception) if verbose: traceback.print_exc() printsystem.print_line('') |