diff options
Diffstat (limited to 'Lib/idlelib/configHandler.py')
| -rw-r--r-- | Lib/idlelib/configHandler.py | 488 | 
1 files changed, 233 insertions, 255 deletions
diff --git a/Lib/idlelib/configHandler.py b/Lib/idlelib/configHandler.py index a9957c5..1c347f6 100644 --- a/Lib/idlelib/configHandler.py +++ b/Lib/idlelib/configHandler.py @@ -15,8 +15,9 @@ idle. This is to allow IDLE to continue to function in spite of errors in  the retrieval of config information. When a default is returned instead of  a requested config value, a message is printed to stderr to aid in  configuration problem notification and resolution. -  """ +# TODOs added Oct 2014, tjr +  import os  import sys @@ -35,7 +36,7 @@ class IdleConfParser(ConfigParser):          """          cfgFile - string, fully specified configuration file name          """ -        self.file=cfgFile +        self.file = cfgFile          ConfigParser.__init__(self, defaults=cfgDefaults, strict=False)      def Get(self, section, option, type=None, default=None, raw=False): @@ -45,26 +46,22 @@ class IdleConfParser(ConfigParser):          """          if not self.has_option(section, option):              return default -        if type=='bool': +        if type == 'bool':              return self.getboolean(section, option) -        elif type=='int': +        elif type == 'int':              return self.getint(section, option)          else:              return self.get(section, option, raw=raw) -    def GetOptionList(self,section): -        """ -        Get an option list for given section -        """ +    def GetOptionList(self, section): +        "Return a list of options for given section, else []."          if self.has_section(section):              return self.options(section)          else:  #return a default value              return []      def Load(self): -        """ -        Load the configuration file from disk -        """ +        "Load the configuration file from disk."          self.read(self.file)  class IdleUserConfParser(IdleConfParser): @@ -72,61 +69,50 @@ class IdleUserConfParser(IdleConfParser):      IdleConfigParser specialised for user configuration handling.      """ -    def AddSection(self,section): -        """ -        if section doesn't exist, add it -        """ +    def AddSection(self, section): +        "If section doesn't exist, add it."          if not self.has_section(section):              self.add_section(section)      def RemoveEmptySections(self): -        """ -        remove any sections that have no options -        """ +        "Remove any sections that have no options."          for section in self.sections():              if not self.GetOptionList(section):                  self.remove_section(section)      def IsEmpty(self): -        """ -        Remove empty sections and then return 1 if parser has no sections -        left, else return 0. -        """ +        "Return True if no sections after removing empty sections."          self.RemoveEmptySections() -        if self.sections(): -            return 0 -        else: -            return 1 +        return not self.sections() -    def RemoveOption(self,section,option): -        """ -        If section/option exists, remove it. -        Returns 1 if option was removed, 0 otherwise. +    def RemoveOption(self, section, option): +        """Return True if option is removed from section, else False. + +        False if either section does not exist or did not have option.          """          if self.has_section(section): -            return self.remove_option(section,option) +            return self.remove_option(section, option) +        return False -    def SetOption(self,section,option,value): -        """ -        Sets option to value, adding section if required. -        Returns 1 if option was added or changed, otherwise 0. +    def SetOption(self, section, option, value): +        """Return True if option is added or changed to value, else False. + +        Add section if required.  False means option already had value.          """ -        if self.has_option(section,option): -            if self.get(section,option)==value: -                return 0 +        if self.has_option(section, option): +            if self.get(section, option) == value: +                return False              else: -                self.set(section,option,value) -                return 1 +                self.set(section, option, value) +                return True          else:              if not self.has_section(section):                  self.add_section(section) -            self.set(section,option,value) -            return 1 +            self.set(section, option, value) +            return True      def RemoveFile(self): -        """ -        Removes the user config file from disk if it exists. -        """ +        "Remove user config file self.file from disk if it exists."          if os.path.exists(self.file):              os.remove(self.file) @@ -150,60 +136,57 @@ class IdleUserConfParser(IdleConfParser):              self.RemoveFile()  class IdleConf: -    """ -    holds config parsers for all idle config files: -    default config files -        (idle install dir)/config-main.def -        (idle install dir)/config-extensions.def -        (idle install dir)/config-highlight.def -        (idle install dir)/config-keys.def -    user config  files -        (user home dir)/.idlerc/config-main.cfg -        (user home dir)/.idlerc/config-extensions.cfg -        (user home dir)/.idlerc/config-highlight.cfg -        (user home dir)/.idlerc/config-keys.cfg +    """Hold config parsers for all idle config files in singleton instance. + +    Default config files, self.defaultCfg -- +        for config_type in self.config_types: +            (idle install dir)/config-{config-type}.def + +    User config files, self.userCfg -- +        for config_type in self.config_types: +        (user home dir)/.idlerc/config-{config-type}.cfg      """      def __init__(self): -        self.defaultCfg={} -        self.userCfg={} -        self.cfg={} +        self.config_types = ('main', 'extensions', 'highlight', 'keys') +        self.defaultCfg = {} +        self.userCfg = {} +        self.cfg = {}  # TODO use to select userCfg vs defaultCfg          self.CreateConfigHandlers()          self.LoadCfgFiles() -        #self.LoadCfg() +      def CreateConfigHandlers(self): -        """ -        set up a dictionary of config parsers for default and user -        configurations respectively -        """ +        "Populate default and user config parser dictionaries."          #build idle install path          if __name__ != '__main__': # we were imported              idleDir=os.path.dirname(__file__)          else: # we were exec'ed (for testing only)              idleDir=os.path.abspath(sys.path[0])          userDir=self.GetUserCfgDir() -        configTypes=('main','extensions','highlight','keys') -        defCfgFiles={} -        usrCfgFiles={} -        for cfgType in configTypes: #build config file names -            defCfgFiles[cfgType]=os.path.join(idleDir,'config-'+cfgType+'.def') -            usrCfgFiles[cfgType]=os.path.join(userDir,'config-'+cfgType+'.cfg') -        for cfgType in configTypes: #create config parsers -            self.defaultCfg[cfgType]=IdleConfParser(defCfgFiles[cfgType]) -            self.userCfg[cfgType]=IdleUserConfParser(usrCfgFiles[cfgType]) + +        defCfgFiles = {} +        usrCfgFiles = {} +        # TODO eliminate these temporaries by combining loops +        for cfgType in self.config_types: #build config file names +            defCfgFiles[cfgType] = os.path.join( +                    idleDir, 'config-' + cfgType + '.def') +            usrCfgFiles[cfgType] = os.path.join( +                    userDir, 'config-' + cfgType + '.cfg') +        for cfgType in self.config_types: #create config parsers +            self.defaultCfg[cfgType] = IdleConfParser(defCfgFiles[cfgType]) +            self.userCfg[cfgType] = IdleUserConfParser(usrCfgFiles[cfgType])      def GetUserCfgDir(self): -        """ -        Creates (if required) and returns a filesystem directory for storing -        user config files. +        """Return a filesystem directory for storing user config files. +        Creates it if required.          """          cfgDir = '.idlerc'          userDir = os.path.expanduser('~')          if userDir != '~': # expanduser() found user home dir              if not os.path.exists(userDir): -                warn = ('\n Warning: os.path.expanduser("~") points to\n '+ -                        userDir+',\n but the path does not exist.') +                warn = ('\n Warning: os.path.expanduser("~") points to\n ' + +                        userDir + ',\n but the path does not exist.')                  try:                      print(warn, file=sys.stderr)                  except OSError: @@ -217,28 +200,28 @@ class IdleConf:              try:                  os.mkdir(userDir)              except OSError: -                warn = ('\n Warning: unable to create user config directory\n'+ -                        userDir+'\n Check path and permissions.\n Exiting!\n') +                warn = ('\n Warning: unable to create user config directory\n' + +                        userDir + '\n Check path and permissions.\n Exiting!\n')                  print(warn, file=sys.stderr)                  raise SystemExit +        # TODO continue without userDIr instead of exit          return userDir      def GetOption(self, configType, section, option, default=None, type=None,                    warn_on_default=True, raw=False): -        """ -        Get an option value for given config type and given general -        configuration section/option or return a default. If type is specified, -        return as type. Firstly the user configuration is checked, with a -        fallback to the default configuration, and a final 'catch all' -        fallback to a useable passed-in default if the option isn't present in -        either the user or the default configuration. -        configType must be one of ('main','extensions','highlight','keys') -        If a default is returned, and warn_on_default is True, a warning is -        printed to stderr. +        """Return a value for configType section option, or default. + +        If type is not None, return a value of that type.  Also pass raw +        to the config parser.  First try to return a valid value +        (including type) from a user configuration. If that fails, try +        the default configuration. If that fails, return default, with a +        default of None. +        Warn if either user or default configurations have an invalid value. +        Warn if default is returned and warn_on_default is True.          """          try: -            if self.userCfg[configType].has_option(section,option): +            if self.userCfg[configType].has_option(section, option):                  return self.userCfg[configType].Get(section, option,                                                      type=type, raw=raw)          except ValueError: @@ -246,16 +229,15 @@ class IdleConf:                         ' invalid %r value for configuration option %r\n'                         ' from section %r: %r' %                         (type, option, section, -                        self.userCfg[configType].Get(section, option, -                                                     raw=raw))) +                       self.userCfg[configType].Get(section, option, raw=raw)))              try:                  print(warning, file=sys.stderr)              except OSError:                  pass          try:              if self.defaultCfg[configType].has_option(section,option): -                return self.defaultCfg[configType].Get(section, option, -                                                       type=type, raw=raw) +                return self.defaultCfg[configType].Get( +                        section, option, type=type, raw=raw)          except ValueError:              pass          #returning default, print warning @@ -272,22 +254,19 @@ class IdleConf:          return default      def SetOption(self, configType, section, option, value): -        """In user's config file, set section's option to value. - -        """ +        """Set section option to value in user config file."""          self.userCfg[configType].SetOption(section, option, value)      def GetSectionList(self, configSet, configType): -        """ -        Get a list of sections from either the user or default config for -        the given config type. +        """Return sections for configSet configType configuration. +          configSet must be either 'user' or 'default' -        configType must be one of ('main','extensions','highlight','keys') +        configType must be in self.config_types.          """ -        if not (configType in ('main','extensions','highlight','keys')): +        if not (configType in self.config_types):              raise InvalidConfigType('Invalid configType specified')          if configSet == 'user': -            cfgParser=self.userCfg[configType] +            cfgParser = self.userCfg[configType]          elif configSet == 'default':              cfgParser=self.defaultCfg[configType]          else: @@ -295,22 +274,22 @@ class IdleConf:          return cfgParser.sections()      def GetHighlight(self, theme, element, fgBg=None): -        """ -        return individual highlighting theme elements. +        """Return individual highlighting theme elements. +          fgBg - string ('fg'or'bg') or None, if None return a dictionary          containing fg and bg colours (appropriate for passing to Tkinter in,          e.g., a tag_config call), otherwise fg or bg colour only as specified.          """          if self.defaultCfg['highlight'].has_section(theme): -            themeDict=self.GetThemeDict('default',theme) +            themeDict = self.GetThemeDict('default', theme)          else: -            themeDict=self.GetThemeDict('user',theme) -        fore=themeDict[element+'-foreground'] -        if element=='cursor': #there is no config value for cursor bg -            back=themeDict['normal-background'] +            themeDict = self.GetThemeDict('user', theme) +        fore = themeDict[element + '-foreground'] +        if element == 'cursor': #there is no config value for cursor bg +            back = themeDict['normal-background']          else: -            back=themeDict[element+'-background'] -        highlight={"foreground": fore,"background": back} +            back = themeDict[element + '-background'] +        highlight = {"foreground": fore, "background": back}          if not fgBg: #return dict of both colours              return highlight          else: #return specified colour only @@ -321,26 +300,26 @@ class IdleConf:              else:                  raise InvalidFgBg('Invalid fgBg specified') -    def GetThemeDict(self,type,themeName): -        """ +    def GetThemeDict(self, type, themeName): +        """Return {option:value} dict for elements in themeName. +          type - string, 'default' or 'user' theme type          themeName - string, theme name -        Returns a dictionary which holds {option:value} for each element -        in the specified theme. Values are loaded over a set of ultimate last -        fallback defaults to guarantee that all theme elements are present in -        a newly created theme. +        Values are loaded over ultimate fallback defaults to guarantee +        that all theme elements are present in a newly created theme.          """          if type == 'user': -            cfgParser=self.userCfg['highlight'] +            cfgParser = self.userCfg['highlight']          elif type == 'default': -            cfgParser=self.defaultCfg['highlight'] +            cfgParser = self.defaultCfg['highlight']          else:              raise InvalidTheme('Invalid theme type specified')          #foreground and background values are provded for each theme element          #(apart from cursor) even though all these values are not yet used          #by idle, to allow for their use in the future. Default values are          #generally black and white. -        theme={ 'normal-foreground':'#000000', +        # TODO make theme, a constant, a module or class attribute +        theme ={'normal-foreground':'#000000',                  'normal-background':'#ffffff',                  'keyword-foreground':'#000000',                  'keyword-background':'#ffffff', @@ -370,9 +349,9 @@ class IdleConf:                  'console-foreground':'#000000',                  'console-background':'#ffffff' }          for element in theme: -            if not cfgParser.has_option(themeName,element): +            if not cfgParser.has_option(themeName, element):                  #we are going to return a default, print warning -                warning=('\n Warning: configHandler.py - IdleConf.GetThemeDict' +                warning = ('\n Warning: configHandler.py - IdleConf.GetThemeDict'                             ' -\n problem retrieving theme element %r'                             '\n from theme %r.\n'                             ' returning default value: %r' % @@ -381,41 +360,39 @@ class IdleConf:                      print(warning, file=sys.stderr)                  except OSError:                      pass -            colour=cfgParser.Get(themeName,element,default=theme[element]) -            theme[element]=colour +            colour = cfgParser.Get(themeName, element, default=theme[element]) +            theme[element] = colour          return theme      def CurrentTheme(self): -        """ -        Returns the name of the currently active theme -        """ -        return self.GetOption('main','Theme','name',default='') +        "Return the name of the currently active theme." +        return self.GetOption('main', 'Theme', 'name', default='')      def CurrentKeys(self): -        """ -        Returns the name of the currently active key set -        """ -        return self.GetOption('main','Keys','name',default='') +        "Return the name of the currently active key set." +        return self.GetOption('main', 'Keys', 'name', default='')      def GetExtensions(self, active_only=True, editor_only=False, shell_only=False): +        """Return extensions in default and user config-extensions files. + +        If active_only True, only return active (enabled) extensions +        and optionally only editor or shell extensions. +        If active_only False, return all extensions.          """ -        Gets a list of all idle extensions declared in the config files. -        active_only - boolean, if true only return active (enabled) extensions -        """ -        extns=self.RemoveKeyBindNames( -                self.GetSectionList('default','extensions')) -        userExtns=self.RemoveKeyBindNames( -                self.GetSectionList('user','extensions')) +        extns = self.RemoveKeyBindNames( +                self.GetSectionList('default', 'extensions')) +        userExtns = self.RemoveKeyBindNames( +                self.GetSectionList('user', 'extensions'))          for extn in userExtns:              if extn not in extns: #user has added own extension                  extns.append(extn)          if active_only: -            activeExtns=[] +            activeExtns = []              for extn in extns:                  if self.GetOption('extensions', extn, 'enable', default=True,                                    type='bool'):                      #the extension is enabled -                    if editor_only or shell_only: +                    if editor_only or shell_only:  # TODO if both, contradictory                          if editor_only:                              option = "enable_editor"                          else: @@ -430,107 +407,108 @@ class IdleConf:          else:              return extns -    def RemoveKeyBindNames(self,extnNameList): -        #get rid of keybinding section names -        names=extnNameList -        kbNameIndicies=[] +    def RemoveKeyBindNames(self, extnNameList): +        "Return extnNameList with keybinding section names removed." +        # TODO Easier to return filtered copy with list comp +        names = extnNameList +        kbNameIndicies = []          for name in names:              if name.endswith(('_bindings', '_cfgBindings')):                  kbNameIndicies.append(names.index(name)) -        kbNameIndicies.sort() -        kbNameIndicies.reverse() +        kbNameIndicies.sort(reverse=True)          for index in kbNameIndicies: #delete each keybinding section name              del(names[index])          return names -    def GetExtnNameForEvent(self,virtualEvent): -        """ -        Returns the name of the extension that virtualEvent is bound in, or -        None if not bound in any extension. -        virtualEvent - string, name of the virtual event to test for, without -                       the enclosing '<< >>' +    def GetExtnNameForEvent(self, virtualEvent): +        """Return the name of the extension binding virtualEvent, or None. + +        virtualEvent - string, name of the virtual event to test for, +                       without the enclosing '<< >>'          """ -        extName=None -        vEvent='<<'+virtualEvent+'>>' +        extName = None +        vEvent = '<<' + virtualEvent + '>>'          for extn in self.GetExtensions(active_only=0):              for event in self.GetExtensionKeys(extn):                  if event == vEvent: -                    extName=extn +                    extName = extn  # TODO return here?          return extName -    def GetExtensionKeys(self,extensionName): -        """ -        returns a dictionary of the configurable keybindings for a particular -        extension,as they exist in the dictionary returned by GetCurrentKeySet; -        that is, where previously used bindings are disabled. +    def GetExtensionKeys(self, extensionName): +        """Return dict: {configurable extensionName event : active keybinding}. + +        Events come from default config extension_cfgBindings section. +        Keybindings come from GetCurrentKeySet() active key dict, +        where previously used bindings are disabled.          """ -        keysName=extensionName+'_cfgBindings' -        activeKeys=self.GetCurrentKeySet() -        extKeys={} +        keysName = extensionName + '_cfgBindings' +        activeKeys = self.GetCurrentKeySet() +        extKeys = {}          if self.defaultCfg['extensions'].has_section(keysName): -            eventNames=self.defaultCfg['extensions'].GetOptionList(keysName) +            eventNames = self.defaultCfg['extensions'].GetOptionList(keysName)              for eventName in eventNames: -                event='<<'+eventName+'>>' -                binding=activeKeys[event] -                extKeys[event]=binding +                event = '<<' + eventName + '>>' +                binding = activeKeys[event] +                extKeys[event] = binding          return extKeys      def __GetRawExtensionKeys(self,extensionName): +        """Return dict {configurable extensionName event : keybinding list}. + +        Events come from default config extension_cfgBindings section. +        Keybindings list come from the splitting of GetOption, which +        tries user config before default config.          """ -        returns a dictionary of the configurable keybindings for a particular -        extension, as defined in the configuration files, or an empty dictionary -        if no bindings are found -        """ -        keysName=extensionName+'_cfgBindings' -        extKeys={} +        keysName = extensionName+'_cfgBindings' +        extKeys = {}          if self.defaultCfg['extensions'].has_section(keysName): -            eventNames=self.defaultCfg['extensions'].GetOptionList(keysName) +            eventNames = self.defaultCfg['extensions'].GetOptionList(keysName)              for eventName in eventNames: -                binding=self.GetOption('extensions',keysName, -                        eventName,default='').split() -                event='<<'+eventName+'>>' -                extKeys[event]=binding +                binding = self.GetOption( +                        'extensions', keysName, eventName, default='').split() +                event = '<<' + eventName + '>>' +                extKeys[event] = binding          return extKeys -    def GetExtensionBindings(self,extensionName): -        """ -        Returns a dictionary of all the event bindings for a particular -        extension. The configurable keybindings are returned as they exist in -        the dictionary returned by GetCurrentKeySet; that is, where re-used -        keybindings are disabled. +    def GetExtensionBindings(self, extensionName): +        """Return dict {extensionName event : active or defined keybinding}. + +        Augment self.GetExtensionKeys(extensionName) with mapping of non- +        configurable events (from default config) to GetOption splits, +        as in self.__GetRawExtensionKeys.          """ -        bindsName=extensionName+'_bindings' -        extBinds=self.GetExtensionKeys(extensionName) +        bindsName = extensionName + '_bindings' +        extBinds = self.GetExtensionKeys(extensionName)          #add the non-configurable bindings          if self.defaultCfg['extensions'].has_section(bindsName): -            eventNames=self.defaultCfg['extensions'].GetOptionList(bindsName) +            eventNames = self.defaultCfg['extensions'].GetOptionList(bindsName)              for eventName in eventNames: -                binding=self.GetOption('extensions',bindsName, -                        eventName,default='').split() -                event='<<'+eventName+'>>' -                extBinds[event]=binding +                binding = self.GetOption( +                        'extensions', bindsName, eventName, default='').split() +                event = '<<' + eventName + '>>' +                extBinds[event] = binding          return extBinds      def GetKeyBinding(self, keySetName, eventStr): +        """Return the keybinding list for keySetName eventStr. + +        keySetName - name of key binding set (config-keys section). +        eventStr - virtual event, including brackets, as in '<<event>>'.          """ -        returns the keybinding for a specific event. -        keySetName - string, name of key binding set -        eventStr - string, the virtual event we want the binding for, -                   represented as a string, eg. '<<event>>' -        """ -        eventName=eventStr[2:-2] #trim off the angle brackets -        binding=self.GetOption('keys',keySetName,eventName,default='').split() +        eventName = eventStr[2:-2] #trim off the angle brackets +        binding = self.GetOption('keys', keySetName, eventName, default='').split()          return binding      def GetCurrentKeySet(self): +        "Return CurrentKeys with 'darwin' modifications."          result = self.GetKeySet(self.CurrentKeys())          if sys.platform == "darwin":              # OS X Tk variants do not support the "Alt" keyboard modifier.              # So replace all keybingings that use "Alt" with ones that              # use the "Option" keyboard modifier. -            # TO DO: the "Option" modifier does not work properly for +            # TODO (Ned?): the "Option" modifier does not work properly for              #        Cocoa Tk and XQuartz Tk so we should not use it              #        in default OS X KeySets.              for k, v in result.items(): @@ -540,40 +518,43 @@ class IdleConf:          return result -    def GetKeySet(self,keySetName): -        """ -        Returns a dictionary of: all requested core keybindings, plus the -        keybindings for all currently active extensions. If a binding defined -        in an extension is already in use, that binding is disabled. +    def GetKeySet(self, keySetName): +        """Return event-key dict for keySetName core plus active extensions. + +        If a binding defined in an extension is already in use, the +        extension binding is disabled by being set to ''          """ -        keySet=self.GetCoreKeys(keySetName) -        activeExtns=self.GetExtensions(active_only=1) +        keySet = self.GetCoreKeys(keySetName) +        activeExtns = self.GetExtensions(active_only=1)          for extn in activeExtns: -            extKeys=self.__GetRawExtensionKeys(extn) +            extKeys = self.__GetRawExtensionKeys(extn)              if extKeys: #the extension defines keybindings                  for event in extKeys:                      if extKeys[event] in keySet.values():                          #the binding is already in use -                        extKeys[event]='' #disable this binding -                    keySet[event]=extKeys[event] #add binding +                        extKeys[event] = '' #disable this binding +                    keySet[event] = extKeys[event] #add binding          return keySet -    def IsCoreBinding(self,virtualEvent): -        """ -        returns true if the virtual event is bound in the core idle keybindings. -        virtualEvent - string, name of the virtual event to test for, without -                       the enclosing '<< >>' +    def IsCoreBinding(self, virtualEvent): +        """Return True if the virtual event is one of the core idle key events. + +        virtualEvent - string, name of the virtual event to test for, +                       without the enclosing '<< >>'          """          return ('<<'+virtualEvent+'>>') in self.GetCoreKeys() +# TODO make keyBindins a file or class attribute used for test above +# and copied in function below +      def GetCoreKeys(self, keySetName=None): -        """ -        returns the requested set of core keybindings, with fallbacks if -        required. -        Keybindings loaded from the config file(s) are loaded _over_ these -        defaults, so if there is a problem getting any core binding there will -        be an 'ultimate last resort fallback' to the CUA-ish bindings -        defined here. +        """Return dict of core virtual-key keybindings for keySetName. + +        The default keySetName None corresponds to the keyBindings base +        dict. If keySetName is not None, bindings from the config +        file(s) are loaded _over_ these defaults, so if there is a +        problem getting any core binding there will be an 'ultimate last +        resort fallback' to the CUA-ish bindings defined here.          """          keyBindings={              '<<copy>>': ['<Control-c>', '<Control-C>'], @@ -628,9 +609,9 @@ class IdleConf:              }          if keySetName:              for event in keyBindings: -                binding=self.GetKeyBinding(keySetName,event) +                binding = self.GetKeyBinding(keySetName, event)                  if binding: -                    keyBindings[event]=binding +                    keyBindings[event] = binding                  else: #we are going to return a default, print warning                      warning=('\n Warning: configHandler.py - IdleConf.GetCoreKeys'                                 ' -\n problem retrieving key binding for event %r' @@ -643,8 +624,8 @@ class IdleConf:                          pass          return keyBindings -    def GetExtraHelpSourceList(self,configSet): -        """Fetch list of extra help sources from a given configSet. +    def GetExtraHelpSourceList(self, configSet): +        """Return list of extra help sources from a given configSet.          Valid configSets are 'user' or 'default'.  Return a list of tuples of          the form (menu_item , path_to_help_file , option), or return the empty @@ -653,19 +634,19 @@ class IdleConf:          therefore the returned list must be sorted by 'option'.          """ -        helpSources=[] -        if configSet=='user': -            cfgParser=self.userCfg['main'] -        elif configSet=='default': -            cfgParser=self.defaultCfg['main'] +        helpSources = [] +        if configSet == 'user': +            cfgParser = self.userCfg['main'] +        elif configSet == 'default': +            cfgParser = self.defaultCfg['main']          else:              raise InvalidConfigSet('Invalid configSet specified')          options=cfgParser.GetOptionList('HelpFiles')          for option in options: -            value=cfgParser.Get('HelpFiles',option,default=';') -            if value.find(';')==-1: #malformed config entry with no ';' -                menuItem='' #make these empty -                helpPath='' #so value won't be added to list +            value=cfgParser.Get('HelpFiles', option, default=';') +            if value.find(';') == -1: #malformed config entry with no ';' +                menuItem = '' #make these empty +                helpPath = '' #so value won't be added to list              else: #config entry contains ';' as expected                  value=value.split(';')                  menuItem=value[0].strip() @@ -676,47 +657,44 @@ class IdleConf:          return helpSources      def GetAllExtraHelpSourcesList(self): +        """Return a list of the details of all additional help sources. + +        Tuples in the list are those of GetExtraHelpSourceList.          """ -        Returns a list of tuples containing the details of all additional help -        sources configured, or an empty list if there are none. Tuples are of -        the format returned by GetExtraHelpSourceList. -        """ -        allHelpSources=( self.GetExtraHelpSourceList('default')+ +        allHelpSources = (self.GetExtraHelpSourceList('default') +                  self.GetExtraHelpSourceList('user') )          return allHelpSources      def LoadCfgFiles(self): -        """ -        load all configuration files. -        """ +        "Load all configuration files."          for key in self.defaultCfg:              self.defaultCfg[key].Load()              self.userCfg[key].Load() #same keys      def SaveUserCfgFiles(self): -        """ -        write all loaded user configuration files back to disk -        """ +        "Write all loaded user configuration files to disk."          for key in self.userCfg:              self.userCfg[key].Save() -idleConf=IdleConf() +idleConf = IdleConf() + +# TODO Revise test output, write expanded unittest  ### module test  if __name__ == '__main__':      def dumpCfg(cfg): -        print('\n',cfg,'\n') +        print('\n', cfg, '\n')          for key in cfg: -            sections=cfg[key].sections() +            sections = cfg[key].sections()              print(key)              print(sections)              for section in sections: -                options=cfg[key].options(section) +                options = cfg[key].options(section)                  print(section)                  print(options)                  for option in options: -                    print(option, '=', cfg[key].Get(section,option)) +                    print(option, '=', cfg[key].Get(section, option))      dumpCfg(idleConf.defaultCfg)      dumpCfg(idleConf.userCfg) -    print(idleConf.userCfg['main'].Get('Theme','name')) +    print(idleConf.userCfg['main'].Get('Theme', 'name'))      #print idleConf.userCfg['highlight'].GetDefHighlight('Foo','normal')  | 
