[yum-cvs] yum/yum __init__.py, 1.138, 1.139 config.py, 1.77, 1.78 parser.py, 1.3, 1.4 plugins.py, 1.17, 1.18 repos.py, 1.83, 1.84

Menno Smits mjs at login.linux.duke.edu
Tue Oct 25 12:28:46 UTC 2005


Update of /home/groups/yum/cvs/yum/yum
In directory login:/tmp/cvs-serv17120/yum

Modified Files:
	__init__.py config.py parser.py plugins.py repos.py 
Log Message:
Major overhaul of configuration file handling.


Index: __init__.py
===================================================================
RCS file: /home/groups/yum/cvs/yum/yum/__init__.py,v
retrieving revision 1.138
retrieving revision 1.139
diff -u -r1.138 -r1.139
--- __init__.py	18 Oct 2005 05:27:07 -0000	1.138
+++ __init__.py	25 Oct 2005 12:28:44 -0000	1.139
@@ -34,6 +34,7 @@
 import rpmUtils.arch
 import newcomps
 import config
+import parser
 import repos
 import misc
 import transactioninfo
@@ -79,55 +80,51 @@
     def doConfigSetup(self, fn='/etc/yum.conf', root='/'):
         """basic stub function for doing configuration setup"""
        
-        self.conf = config.yumconf(configfile=fn, root=root)
+        self.conf = config.readMainConfig(fn, root)
+        self.yumvar = self.conf.yumvar
         self.getReposFromConfig()
 
     def getReposFromConfig(self):
         """read in repositories from config main and .repo files"""
-        
+
         reposlist = []
-        # look through our repositories.
-        for section in self.conf.cfg.sections(): # loop through the list of sections
-            if section != 'main': # must be a repoid
-                try:
-                    thisrepo = config.cfgParserRepo(section, self.conf, self.conf.cfg)
-                except (Errors.RepoError, Errors.ConfigError), e:
-                    self.errorlog(2, e)
-                    continue
-                else:
-                    reposlist.append(thisrepo)
 
-        # reads through each reposdir for *.repo
-        # does not read recursively
-        # read each of them in using confpp, then parse them same as any other repo
-        # section - as above.
+        # Check yum.conf for repositories
+        for section in self.conf.cfg.sections():
+            # All sections except [main] are repositories
+            if section == 'main': 
+                continue
+
+            try:
+                thisrepo = config.readRepoConfig(self.conf.cfg, section, self.conf)
+            except (Errors.RepoError, Errors.ConfigError), e:
+                self.errorlog(2, e)
+            else:
+                reposlist.append(thisrepo)
+
+        # Read .repo files from directories specified by the reposdir option
+        # (typically /etc/yum.repos.d and /etc/yum/repos.d)
+        parser = config.IncludedDirConfigParser(vars=self.yumvar)
         for reposdir in self.conf.reposdir:
-            if os.path.exists(self.conf.installroot + '/' + reposdir):
+            if os.path.exists(self.conf.installroot+'/'+reposdir):
                 reposdir = self.conf.installroot + '/' + reposdir
-            
+
             if os.path.isdir(reposdir):
-                repofn = glob.glob(reposdir+'/*.repo')
-                repofn.sort()
-                
-                for fn in repofn:
-                    if not os.path.isfile(fn):
-                        continue
-                    try:
-                        cfg, sections = config.parseDotRepo(fn)
-                    except Errors.ConfigError, e:
-                        self.errorlog(2, e)
-                        continue
+                #XXX: why can't we just pass the list of files?
+                files = ' '.join(glob.glob('%s/*.repo' % reposdir))
+                #XXX: error catching here
+                parser.read(files)
 
-                    for section in sections:
-                        try:
-                            thisrepo = config.cfgParserRepo(section, self.conf, 
-                                    cfg)
-                            reposlist.append(thisrepo)
-                        except (Errors.RepoError, Errors.ConfigError), e:
-                            self.errorlog(2, e)
-                            continue
+        # Check sections in the .repo files that were just slurped up
+        for section in parser.sections():
+            try:
+                thisrepo = config.readRepoConfig(parser, section, self.conf)
+            except (Errors.RepoError, Errors.ConfigError), e:
+                self.errorlog(2, e)
+            else:
+                reposlist.append(thisrepo)
 
-        # got our list of repo objects
+        # Got our list of repo objects, add them to the repos collection
         for thisrepo in reposlist:
             try:
                 self.repos.add(thisrepo)
@@ -170,10 +167,10 @@
         if hasattr(self, 'read_ts'):
             return
             
-        if not self.conf.getConfigOption('installroot'):
+        if not self.conf.installroot:
             raise Errors.YumBaseError, 'Setting up TransactionSets before config class is up'
         
-        installroot = self.conf.getConfigOption('installroot')
+        installroot = self.conf.installroot
         self.read_ts = rpmUtils.transaction.initReadOnlyTransaction(root=installroot)
         self.tsInfo = transactioninfo.TransactionData()
         self.rpmdb = rpmUtils.RpmDBHolder()
@@ -205,7 +202,6 @@
         """grabs the repomd.xml for each enabled repository and sets up 
            the basics of the repository"""
 
-        
         self.plugins.run('prereposetup')
         
         repos = []
@@ -221,7 +217,7 @@
             if repo.repoXML is not None and len(repo.urls) > 0:
                 continue
             try:
-                repo.cache = self.conf.getConfigOption('cache')
+                repo.cache = self.conf.cache
                 repo.baseurlSetup()
                 repo.dirSetup()
                 self.log(3, 'Baseurl(s) for repo: %s' % repo.urls)
@@ -279,17 +275,17 @@
         # raise an error
         self.up = rpmUtils.updates.Updates(self.rpmdb.getPkgList(),
                                            self.pkgSack.simplePkgList())
-        if self.conf.getConfigOption('debuglevel') >= 6:
+        if self.conf.debuglevel >= 6:
             self.up.debug = 1
             
-        if self.conf.getConfigOption('obsoletes'):
+        if self.conf.obsoletes:
             self.up.rawobsoletes = self.pkgSack.returnObsoletes()
             
-        self.up.exactarch = self.conf.getConfigOption('exactarch')
-        self.up.exactarchlist = self.conf.getConfigOption('exactarchlist')
+        self.up.exactarch = self.conf.exactarch
+        self.up.exactarchlist = self.conf.exactarchlist
         self.up.doUpdates()
 
-        if self.conf.getConfigOption('obsoletes'):
+        if self.conf.obsoletes:
             self.up.doObsoletes()
 
         self.up.condenseUpdates()
@@ -313,7 +309,7 @@
                 reposWithGroups.append(repo)
                 
         # now we know which repos actually have groups files.
-        overwrite = self.conf.getConfigOption('overwrite_groups')
+        overwrite = self.conf.overwrite_groups
         self.comps = newcomps.Comps(overwrite_groups = overwrite)
 
         for repo in reposWithGroups:
@@ -360,10 +356,10 @@
         # if repo: then do only that repos' packages and excludes
         
         if not repo: # global only
-            excludelist = self.conf.getConfigOption('exclude')
+            excludelist = self.conf.exclude
             repoid = None
         else:
-            excludelist = repo.excludes
+            excludelist = repo.exclude
             repoid = repo.id
 
         if len(excludelist) == 0:
@@ -428,7 +424,7 @@
         """perform the yum locking, raise yum-based exceptions, not OSErrors"""
         
         # if we're not root then we don't lock - just return nicely
-        if self.conf.getConfigOption('uid') != 0:
+        if self.conf.uid != 0:
             return
             
         root = self.conf.installroot
@@ -461,7 +457,7 @@
         """do the unlock for yum"""
         
         # if we're not root then we don't lock - just return nicely
-        if self.conf.getConfigOption('uid') != 0:
+        if self.conf.uid != 0:
             return
         
         root = self.conf.installroot
@@ -944,7 +940,7 @@
         elif pkgnarrow == 'obsoletes':
             self.doRepoSetup()
             self.doRpmDBSetup()
-            self.conf.setConfigOption('obsoletes', 1)
+            self.conf.obsoletes = 1
             self.doUpdateSetup()
 
             for (pkgtup, instTup) in self.up.getObsoletesTuples():

Index: config.py
===================================================================
RCS file: /home/groups/yum/cvs/yum/yum/config.py,v
retrieving revision 1.77
retrieving revision 1.78
diff -u -r1.77 -r1.78
--- config.py	7 Oct 2005 05:44:53 -0000	1.77
+++ config.py	25 Oct 2005 12:28:44 -0000	1.78
@@ -1,4 +1,5 @@
 #!/usr/bin/python -t
+
 # This program 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
@@ -14,128 +15,175 @@
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 # Copyright 2002 Duke University 
 
-import ConfigParser
-import sys
[...1146 lines suppressed...]
-                continue
-            else:
-                reposlist.append(thisrepo)
-
-    # got our list of repo objects
-    reposlist.sort()
-    for thisrepo in reposlist:
-        try:
-            thisrepo.baseurlSetup()
-        except Errors.RepoError, e:
-            pass
-        print thisrepo.dump()
-        print ''
-
-if __name__ == "__main__":
-        if len(sys.argv) < 2:
-            print 'command: config file'
-            sys.exit(1)
-            
-        main(sys.argv[1:])

Index: parser.py
===================================================================
RCS file: /home/groups/yum/cvs/yum/yum/parser.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- parser.py	11 Oct 2005 21:11:03 -0000	1.3
+++ parser.py	25 Oct 2005 12:28:44 -0000	1.4
@@ -6,10 +6,11 @@
 import os.path
 from ConfigParser import ConfigParser, NoSectionError, NoOptionError
 
+#TODO: include'ing of URLs (Yum currently supports this)
 #TODO: problem: interpolation tokens are lost when config files are rewritten
 #       - workaround is to not set vars, not sure if this is ok
 #       - maybe we should do interpolation at the Option level after all?
-#TODO: include'ing of URLs (Yum currently supports this)
+#       - preserve original uninterpolated value?
 #TODO: separate $var interpolation into YumParser?
 
 class IncludingConfigParser(ConfigParser):
@@ -175,41 +176,22 @@
             inc = open(fn, 'w')
             self._fns[fn].write(inc)
 
-    _KEYCRE = re.compile(r"\$(\w+)")
-
     def _interpolate(self, section, option, rawval, vars):
         '''Perform $var subsitution (this overides the default %(..)s subsitution)
 
         Only the rawval and vars arguments are used. The rest are present for
         compatibility with the parent class.
         '''
-        done = []                           # Completed chunks to return
-
-        while rawval:
-            m = self._KEYCRE.search(rawval)
-            if not m:
-                done.append(rawval)
-                break
-
-            # Determine replacement value (if unknown variable then preserve original)
-            varname = m.group(1).lower()
-            replacement = vars.get(varname, m.group())
-
-            start, end = m.span()
-            done.append(rawval[:start])     # Keep stuff leading up to token
-            done.append(replacement)        # Append replacement value
-            rawval = rawval[end:]           # Continue with remainder of string
-
-        return ''.join(done)
+        return varReplace(rawval, vars)
 
 
 class IncludedDirConfigParser(IncludingConfigParser):
     """A conf.d recursive parser - supporting one level of included dirs"""
 
-    def __init__(self, defaults = None, includedir=None, includeglob="*.conf", include="include"):
+    def __init__(self, vars=None, includedir=None, includeglob="*.conf", include="include"):
         self.includeglob = includeglob
         self.includedir = includedir
-        IncludingConfigParser.__init__(self,include=include)
+        IncludingConfigParser.__init__(self, vars=vars, include=include)
 
     def read(self, filenames):
         for filename in shlex.split(filenames):
@@ -232,3 +214,29 @@
         self._add_include(section, filename)
 
 
+_KEYCRE = re.compile(r"\$(\w+)")
+
+def varReplace(raw, vars):
+    '''Perform variable replacement
+
+    @parma  
+    '''
+
+    done = []                      # Completed chunks to return
+
+    while raw:
+        m = _KEYCRE.search(raw)
+        if not m:
+            done.append(raw)
+            break
+
+        # Determine replacement value (if unknown variable then preserve original)
+        varname = m.group(1).lower()
+        replacement = vars.get(varname, m.group())
+
+        start, end = m.span()
+        done.append(raw[:start])    # Keep stuff leading up to token
+        done.append(replacement)    # Append replacement value
+        raw = raw[end:]             # Continue with remainder of string
+
+    return ''.join(done)

Index: plugins.py
===================================================================
RCS file: /home/groups/yum/cvs/yum/yum/plugins.py,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- plugins.py	17 Jul 2005 02:09:16 -0000	1.17
+++ plugins.py	25 Oct 2005 12:28:44 -0000	1.18
@@ -22,6 +22,16 @@
 import config 
 import Errors
 
+# XXX: break the API for how plugins define config file options
+#   - they should just be able to manipulate the YumConf and RepoConf classes
+#     directly, adding Option instances as required
+#   - cleaner, more flexible and 
+#   - update PLUGINS document
+#   - will take care of the following existing TODOs:
+# TODO: detect conflicts between builtin yum options and registered plugin
+# options (will require refactoring of config.py)
+# TODO: plugins should be able to specify convertor functions for config vars
+
 # TODO: should plugin searchpath be affected by installroot option?
 
 # TODO: cleaner method to query installed packages rather than exposing RpmDB
@@ -47,11 +57,6 @@
 
 # TODO: allow plugins to extend commands (on the command line)
 
-# TODO: plugins should be able to specify convertor functions for config vars
-
-# TODO: detect conflicts between builtin yum options and registered plugin
-# options (will require refactoring of config.py)
-
 # TODO: More developer docs:  use epydoc as API begins to stablise
 
 # TODO: test the API by implementing some crack from bugzilla
@@ -183,7 +188,8 @@
         modname = modname.split('.py')[0]
 
         conf = self._getpluginconf(modname)
-        if not conf or not conf._getboolean('main', 'enabled', 0):
+        if not conf or not config.getOption(conf, 'main', 'enabled', False,
+                config.BoolOption()):
             self.base.log(3, '"%s" plugin is disabled' % modname)
             return
 
@@ -231,17 +237,16 @@
                         )
 
     def _getpluginconf(self, modname):
-        '''Parse the plugin specific configuration file and return a CFParser
-        instance representing it. Returns None if there was an error reading or
-        parsing the configuration file.
+        '''Parse the plugin specific configuration file and return a
+        IncludingConfigParser instance representing it. Returns None if there
+        was an error reading or parsing the configuration file.
         '''
+        #XXX: should this use installroot?
         conffilename = os.path.join('/etc/yum/pluginconf.d', modname+'.conf')
 
-        parser = config.CFParser()
         try:
-            fin = open(conffilename, 'rt')
-            parser.readfp(fin)
-            fin.close()
+            parser = config.IncludingConfigParser()
+            parser.read(conffilename)
         except ConfigParser.Error, e:
             raise Errors.ConfigError("Couldn't parse %s: %s" % (conffilename,
                 str(e)))
@@ -269,31 +274,33 @@
     def parseopts(self, conf, repos):
         '''Parse any configuration options registered by plugins
 
-        conf: the yumconf instance holding Yum's global options
-        repos: a list of all repository objects
+        @param conf: the yumconf instance holding Yum's global options
+        @param repos: a list of all repository objects
         '''
+        #XXX: with the new config stuff this is an ugly hack!
+        # See first TODO at top of this file
+
+        type2opt =  {
+            PLUG_OPT_STRING: config.Option(),
+            PLUG_OPT_INT: config.IntOption(),
+            PLUG_OPT_BOOL: config.BoolOption(),
+            PLUG_OPT_FLOAT: config.FloatOption(),
+            }
 
         # Process [main] options first
-        self._do_opts(conf.cfg, 'main', PLUG_OPT_WHERE_MAIN, 
-                conf.setConfigOption)
+        for name, (vtype, where, default) in self.opts.iteritems(): 
+            if where in (PLUG_OPT_WHERE_MAIN, PLUG_OPT_WHERE_ALL):
+                val = config.getOption(conf.cfg, 'main', name, default,
+                        type2opt[vtype])
+                setattr(conf, name, val)
 
         # Process repository level options
         for repo in repos:
-            self._do_opts(repo.cfgparser, repo.id, PLUG_OPT_WHERE_REPO, 
-                repo.set)
-
-    def _do_opts(self, cfgparser, section, targetwhere, setfunc):
-        '''Process registered plugin options for one config file section
-        '''
-        typetofunc =  {
-            PLUG_OPT_STRING: cfgparser._getoption,
-            PLUG_OPT_INT: cfgparser._getint,
-            PLUG_OPT_BOOL: cfgparser._getboolean,
-            PLUG_OPT_FLOAT: cfgparser._getfloat,
-            }
-        for name, (vtype, where, default) in self.opts.iteritems(): 
-            if where in (targetwhere, PLUG_OPT_WHERE_ALL):
-                setfunc(name, typetofunc[vtype](section, name, default))
+            for name, (vtype, where, default) in self.opts.iteritems(): 
+                if where in (PLUG_OPT_WHERE_REPO, PLUG_OPT_WHERE_ALL):
+                    val = config.getOption(conf.cfg, repo.id, name, default,
+                            type2opt[vtype])
+                    repo.set(name, val)
 
     def setCmdLine(self, opts, commands):
         '''Set the parsed command line options so that plugins can access them
@@ -326,7 +333,7 @@
 
     def promptYN(self, msg):
         self.info(2, msg)
-        if self._base.conf.getConfigOption('assumeyes'):
+        if self._base.conf.assumeyes:
             return 1
         else:
             return self._base.userconfirm()
@@ -360,7 +367,8 @@
         @param default: Value to read if option is missing.
         @return: String option value read, or default if option was missing.
         '''
-        return self._conf._getoption(section, opt, default)
+        return config.getoption(self._conf, section, opt, default,
+                config.Option())
 
     def confInt(self, section, opt, default=None):
         '''Read an integer value from the plugin's own configuration file
@@ -371,7 +379,8 @@
         @return: Integer option value read, or default if option was missing or
             could not be parsed.
         '''
-        return self._conf._getint(section, opt, default)
+        return config.getoption(self._conf, section, opt, default,
+                config.IntOption())
 
     def confFloat(self, section, opt, default=None):
         '''Read a float value from the plugin's own configuration file
@@ -382,7 +391,8 @@
         @return: Float option value read, or default if option was missing or
             could not be parsed.
         '''
-        return self._conf._getfloat(section, opt, default)
+        return config.getoption(self._conf, section, opt, default,
+                config.FloatOption())
 
     def confBool(self, section, opt, default=None):
         '''Read a boolean value from the plugin's own configuration file
@@ -393,7 +403,8 @@
         @return: Boolean option value read, or default if option was missing or
             could not be parsed.
         '''
-        return self._conf._getboolean(section, opt, default)
+        return config.getoption(self._conf, section, opt, default,
+                config.BoolOption())
 
 class ConfigPluginConduit(PluginConduit):
 

Index: repos.py
===================================================================
RCS file: /home/groups/yum/cvs/yum/yum/repos.py,v
retrieving revision 1.83
retrieving revision 1.84
diff -u -r1.83 -r1.84
--- repos.py	8 Aug 2005 14:57:05 -0000	1.83
+++ repos.py	25 Oct 2005 12:28:44 -0000	1.84
@@ -30,6 +30,7 @@
 from repomd import packageSack
 from packages import YumAvailablePackage
 import mdcache
+import parser
 
 _is_fnmatch_pattern = re.compile(r"[*?[]").search
 
@@ -332,9 +333,9 @@
         self.cache = 0
         self.callback = None # callback for the grabber
         self.failure_obj = None
-        self.mirrorlistfn = None # filename/url of mirrorlist file
+        self.mirrorlist = None # filename/url of mirrorlist file
         self.mirrorlistparsed = 0
-        self.baseurls = [] # baseurls from the config file
+        self.baseurl = [] # baseurls from the config file
         self.yumvar = {} # empty dict of yumvariables for $string replacement
         self.proxy_password = None
         self.proxy_username = None
@@ -401,8 +402,8 @@
         output = '[%s]\n' % self.id
         vars = ['name', 'bandwidth', 'enabled', 'enablegroups', 
                  'gpgcheck', 'includepkgs', 'keepalive', 'proxy',
-                 'proxy_password', 'proxy_username', 'excludes', 
-                 'retries', 'throttle', 'timeout', 'mirrorlistfn', 
+                 'proxy_password', 'proxy_username', 'exclude', 
+                 'retries', 'throttle', 'timeout', 'mirrorlist', 
                  'cachedir', 'gpgkey', 'pkgdir', 'hdrdir']
         vars.sort()
         for attr in vars:
@@ -524,15 +525,15 @@
            with valid ones, run  self.check() at the end to make sure it worked"""
 
         goodurls = []
-        if self.mirrorlistfn and not self.mirrorlistparsed:
-            mirrorurls = getMirrorList(self.mirrorlistfn)
+        if self.mirrorlist and not self.mirrorlistparsed:
+            mirrorurls = getMirrorList(self.mirrorlist)
             self.mirrorlistparsed = 1
             for url in mirrorurls:
-                url = variableReplace(self.yumvar, url)
-                self.baseurls.append(url)
-        
-        for url in self.baseurls:
-            url = variableReplace(self.yumvar, url)
+                url = parser.varReplace(url, self.yumvar)
+                self.baseurl.append(url)
+       
+        for url in self.baseurl:
+            url = parser.varReplace(url, self.yumvar)
             (s,b,p,q,f,o) = urlparse.urlparse(url)
             if s not in ['http', 'ftp', 'file', 'https']:
                 print 'not using ftp, http[s], or file for repos, skipping - %s' % (url)
@@ -814,46 +815,3 @@
     
     return returnlist
 
-def variableReplace(yumvar, thing):
-    """ do the replacement of $ variables, releasever, arch and basearch on any 
-        string or list  passed to it - returns whatever you passed"""
-    
-    if thing is None:
-        return thing
-
-    elif type(thing) is types.ListType:
-        shortlist = thing
-
-    elif type(thing) is types.StringType:
-        shortlist = []
-        shortlist.append(thing)
-        
-    else:
-        # not a list or string, screw it
-        return thing
-    
-    basearch_reg = re.compile('\$basearch', re.I)
-    arch_reg = re.compile('\$arch', re.I)
-    releasever_reg = re.compile('\$releasever', re.I)
-    yumvar_reg = {}
-
-    for num in range(0,10):
-        env = '\$YUM%s' % num
-        yumvar_reg[num] = re.compile(env, re.I)
-
-    returnlist = []        
-    for string in shortlist:
-        (string, count) = basearch_reg.subn(yumvar['basearch'], string)
-        (string, count) = arch_reg.subn(yumvar['arch'], string)
-        (string, count) = releasever_reg.subn(yumvar['releasever'], string)
-        for num in range(0,10):
-            (string, count) = yumvar_reg[num].subn(yumvar[num], string)
-        returnlist.append(string)
-        
-    if type(thing) is types.StringType:
-        thing = returnlist[0]
-    
-    if type(thing) is types.ListType:
-        thing = returnlist
-        
-    return thing




More information about the Yum-cvs-commits mailing list