#!/usr/bin/python # -*- coding: utf-8 -*- ################################################################################# # LAYMAN CONFIGURATION ################################################################################# # File: argsparser.py # # Handles layman command line interface configuration # # Copyright: # (c) 2005 - 2009 Gunnar Wrobel # (c) 2009 Sebastian Pipping # (c) 2010 - 2011 Brian Dolbec # Distributed under the terms of the GNU General Public License v2 # # Author(s): # Gunnar Wrobel # Sebastian Pipping # Brian Dolbec # '''Defines the configuration options and provides parsing functionality.''' from __future__ import unicode_literals __version__ = "$Id: config.py 286 2007-01-09 17:48:23Z wrobel $" #=============================================================================== # # Dependencies # #------------------------------------------------------------------------------- import sys from argparse import ArgumentParser from layman.config import BareConfig from layman.constants import OFF from layman.version import VERSION _USAGE = """ layman (-a|-d|-r|-s|-i) (OVERLAY|ALL) # it also supports multiple actions layman (-a|-d|-r|-s|-i) (OVERLAY|ALL) [ [(-a|-d|-r|-s|-i) (OVERLAY)] ...] layman -f [-o URL] layman (-l|-L|-S)""" class ArgsParser(BareConfig): '''Handles the configuration and option parser.''' def __init__(self, args=None, stdout=None, stdin=None, stderr=None, root=None ): ''' Creates and describes all possible polymeraZe options and creates a Message object. ''' BareConfig.__init__(self, stdout=stdout, stderr=stderr, stdin=stdin, root=root) # get a couple BareConfig items self.defaults = self.get_defaults() self.output = self.get_option('output') self.parser = ArgumentParser( usage = _USAGE) self.parser.add_argument('-H', '--setup-help', action = 'store_true', help = 'Print the NEW INSTALL help messages.') self.parser.add_argument('-V', '--version', action = 'version', version = VERSION) #----------------------------------------------------------------- # Main Options actions = self.parser.add_argument_group('') actions.add_argument('-a', '--add', nargs = '+', help = 'Add the given overlay from the cached remote li' 'st to your locally installed overlays.. Specify "ALL" ' 'to add all overlays from the remote list.') actions.add_argument('-d', '--delete', nargs = '+', help = 'Remove the given overlay from your locally inst' 'alled overlays. Specify "ALL" to remove all overlays.') actions.add_argument('-D', '--disable', nargs = '+', help = 'Disable the given overlay from portage. Specify' ' "ALL" to disable all installed overlay.') actions.add_argument('-E', '--enable', nargs = '+', help = 'Re-enable a previously disabled overlay. Specif' 'y "ALL" to enable all installed overlays.') actions.add_argument('-f', '--fetch', action = 'store_true', help = 'Fetch a remote list of overlays. This option is' ' deprecated. The fetch operation will be performed by ' 'default when you run sync, sync-all, or list.') actions.add_argument('-i', '--info', nargs = '+', help = 'Display information about the specified overlay' '.') actions.add_argument('-L', '--list', action = 'store_true', help = 'List the contents of the remote list.') actions.add_argument('-l', '--list-local', action = 'store_true', help = 'List the locally installed overlays.') actions.add_argument('-n', '--nofetch', action = 'store_true', help = 'Do not fetch a remote list of overlays.') actions.add_argument('-p', '--priority', action = 'store', help = 'Use this with the --add switch to set the prior' 'ity of the added overlay. This will influence the sort' 'ing order of the overlays in the PORTDIR_OVERLAY varia' 'ble.') actions.add_argument('-r', '--readd', nargs = '+', help = 'Remove and re-add the given overlay from the cached' ' remote list to your locally installed overlays... Specify' ' "ALL" to re-add all local overlays.') actions.add_argument('-s', '--sync', nargs = '+', help = 'Update the specified overlay. Use "ALL" as para' 'meter to synchronize all overlays.') actions.add_argument('-S', '--sync-all', action = 'store_true', help = 'Update all overlays.') #----------------------------------------------------------------- # Path Options path_opts = self.parser.add_argument_group('') path_opts.add_argument('-c', '--config', action = 'store', default = self.defaults['config'], # Force interpolation (to prevent argparse tracebacks) help = 'Path to the config file [default: ' '%s].' % (self.defaults['config'] %self.defaults)) path_opts.add_argument('-C', '--configdir', action = 'store', default = self.defaults['configdir'], help = 'Directory path to user for all layman ' 'configuration information [default:'\ + self.defaults['configdir'] + '].') path_opts.add_argument('-o', '--overlays', nargs = '+', help = 'The list of overlays [default: ' \ + self.defaults['overlays'] + '].') path_opts.add_argument('-O', '--overlay_defs', action = 'store', default = self.defaults['overlay_defs'], # Force interpolation (to prevent argparse tracebacks) help = 'Path to aditional overlay.xml files [default: ' '%s].' % (self.defaults['overlay_defs'] %self.defaults)) path_opts.add_argument('-z', '--storage', action = 'store', default = self.defaults['storage'], help = 'Directory path to user for layman overlay inst' 'allation location [default: /var/lib/layman].') #----------------------------------------------------------------- # Output Options out_opts = self.parser.add_argument_group('') out_opts.add_argument('--debug-level', action = 'store', type = int, help = 'A value between 0 and 10. 0 means no debugging ' 'messages will be selected, 10 selects all debugging me' 'ssages. Default is "4".') out_opts.add_argument('-k', '--nocheck', action = 'store_true', help = 'Do not check overlay definitions and do not i' 'ssue a warning if description or contact information' ' are missing.') out_opts.add_argument('-N', '--nocolor', action = 'store_true', help = 'Remove color codes from the layman output.') out_opts.add_argument('-q', '--quiet', action = 'store_true', help = 'Yield no output. Please be careful with this op' 'tion: If the processes spawned by layman when adding o' 'r synchronizing overlays require any input layman will' ' hang without telling you why. This might happen for e' 'xample if your overlay resides in subversion and the S' 'SL certificate of the server needs acceptance.') out_opts.add_argument('-Q', '--quietness', action = 'store', type = int, default = 4, help = 'Set the level of output (0-4). Default: 4. Once' ' you set this below 2 the same warning as given for --' 'quiet applies!') out_opts.add_argument('-v', '--verbose', action = 'store_true', help = 'Increase the amount of output and describe the ' 'overlays.') out_opts.add_argument('-W', '--width', action = 'store', type = int, default = 0, help = 'Sets the screen width. This setting is usually ' 'not required as layman is capable of detecting the ' 'available number of columns automatically.') #----------------------------------------------------------------- # Additional Options etc_opts = self.parser.add_argument_group('') etc_opts.add_argument('--protocol_filter', nargs = '+', help = 'Sets the protocol filter that determines ' 'which protocols will be used when adding ' 'overlays or updating their source URLs.') #----------------------------------------------------------------- # Debug Options #self.output.cli_opts(self.parser) # Parse the command line first since we need to get the config # file option. # If no flags are present print out usage if len(sys.argv) == 1: self.output.notice('usage:%s' % _USAGE) sys.exit(0) self.options = self.parser.parse_args() self.options = vars(self.options) # Applying interpolation of values for v in ['configdir', 'config']: self.options[v] = self.options[v] % self.options self.defaults[v] = self.options[v] if ('debug_level' in self.options and self.options['debug_level']): dbglvl = int(self.options['debug_level']) if dbglvl < 0: dbglvl = 0 if dbglvl > 10: dbglvl = 10 self.output.set_debug_level(dbglvl) if self.options['nocolor']: self.output.set_colorize(OFF) # Set only alternate config settings from the options if self.options['config'] is not None: self.defaults['config'] = self.options['config'] self.output.debug('ARGSPARSER: Got config file at ' + \ self.defaults['config'], 8) else: # fix the config path self.defaults['config'] = self.defaults['config'] \ % {'configdir': self.defaults['configdir']} self._options['setup_help'] = self.options['setup_help'] # Now parse the config file self.output.debug('ARGSPARSER: Reading config file at ' + \ self.defaults['config'], 8) self.read_config(self.defaults) # Handle the overlay_defs option: if ('%(configdir)s' in self.options['overlay_defs'] and self.config.has_option('MAIN', 'overlay_defs')): # If it hasn't been interpolated then it's not being set as a # command line argument. So we first try to set it to the config # value. self.options['overlay_defs'] = self.config.get('MAIN', 'overlay_defs') elif self.defaults['overlay_defs'] == self.options['overlay_defs']: # If it isn't a command line argument and no config option then # set it to the default. self.defaults['overlay_defs'] = self.defaults['overlay_defs'] % self.options self.options['overlay_defs'] = self.defaults['overlay_defs'] # handle quietness if self.options['quiet']: self.set_option('quiet', True) elif self.options['quietness']: self.set_option('quietness', self.options['quietness']) def __getitem__(self, key): if key == 'storage': storage = '' if (key in self.options.keys() and not self.options[key] is None): storage = self.options[key] if self.config.has_option('MAIN', 'storage'): storage = self.config.get('MAIN', 'storage') # Set the value to the command line value if and only # if it isn't the same as the default. if self.options[key] != self.defaults[key]: storage = self.options[key] if storage: return storage if key == 'protocol_filter': protocol_filter = [] if (key in self.options.keys() and not self.options[key] is None): protocol_filter = self.options[key] if self.config.has_option('MAIN', 'protocol_filter'): protocol_filter = self.config.get('MAIN', 'protocol_filter') if protocol_filter: if not isinstance(protocol_filter, list): protocol_filter = [e.strip() for e in protocol_filter.split(',')] return protocol_filter if key == 'overlays': overlays = '' if (key in self.options.keys() and not self.options[key] is None): overlays = '\n'.join(self.options[key]) if self.config.has_option('MAIN', 'overlays'): overlays += '\n' + self.config.get('MAIN', 'overlays') if len(overlays): return overlays self.output.debug('ARGSPARSER: Retrieving options option: %s' % key, 9) if (key in self.options.keys() and not self.options[key] is False): return self.options[key] self.output.debug('ARGSPARSER: Retrieving config option: %s' % key, 9) if self.config.has_option('MAIN', key): if key in self._defaults['t/f_options']: return self.t_f_check(self.config.get('MAIN', key)) return self.config.get('MAIN', key) self.output.debug('ARGSPARSER: Retrieving option: %s' % key, 9) if key in self._options.keys(): return self._options[key] if key in self.defaults.keys(): return self.defaults[key] self.output.debug('ARGSPARSER: Retrieving option failed. returning None', 9) return None def keys(self): '''Special handler for the configuration keys.''' self.output.debug('ARGSPARSER: Retrieving keys', 9) keys = [i for i in self.options if not self.options[i] is False and not self.options[i] is None] self.output.debug('ARGSPARSER: Retrieving keys 2', 9) keys += [name for name, _ in self.config.items('MAIN') if not name in keys] self.output.debug('ARGSPARSER: Retrieving keys 3', 9) keys += [i for i in self.defaults.keys() if not i in keys] self.output.debug('ARGSPARSER: Returning keys', 9) return keys