[yum-cvs] yum/yum config.py,1.90,1.91
Menno Smits
mjs at linux.duke.edu
Thu Jan 26 04:08:26 UTC 2006
Update of /home/groups/yum/cvs/yum/yum
In directory login1.linux.duke.edu:/tmp/cvs-serv13633
Modified Files:
config.py
Log Message:
- fixed bug that caused option inheritance via class inheritance not to work
(installroot and distroverpkg no longer need to be defined twice)
- lots of documentation
- handle repo sections that don't have a name set (warn and use id instead)
- warn when getConfigOption and setConfigOption are used
Index: config.py
===================================================================
RCS file: /home/groups/yum/cvs/yum/yum/config.py,v
retrieving revision 1.90
retrieving revision 1.91
diff -u -r1.90 -r1.91
--- config.py 13 Jan 2006 06:07:15 -0000 1.90
+++ config.py 26 Jan 2006 04:08:23 -0000 1.91
@@ -15,12 +15,12 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Copyright 2002 Duke University
-#TODO: docstrings
-
import os
+import warnings
import rpm
import copy
import urlparse
+import sys
from parser import IncludingConfigParser, IncludedDirConfigParser
from ConfigParser import NoSectionError, NoOptionError
import rpmUtils.transaction
@@ -29,6 +29,9 @@
from repos import Repository
class OptionData(object):
+ '''
+ Simple class to track state for a single option instance.
+ '''
def __init__(self, parser, section, name):
self.parser = parser
self.section = section
@@ -36,6 +39,13 @@
self.value = None
class Option(object):
+ '''
+ This class handles a single Yum configuration file option. Create
+ subclasses for each type of supported configuration option.
+
+ Python descriptor foo (__get__ and __set__) is used to make option
+ definition easy and consise.
+ '''
def __init__(self, default=None):
self._setattrname()
@@ -43,9 +53,19 @@
self.default = default
def _setattrname(self):
+ '''Calculate the internal attribute name used to store option state in
+ configuration instances.
+ '''
self._attrname = '__opt%X' % id(self)
def __get__(self, obj, objtype):
+ '''Called when the option is read (via the descriptor protocol).
+
+ @param obj: The configuration instance to modify.
+ @param objtype: The type of the config instance (not used).
+ @return: The parsed option value or the default value if the value
+ wasn't set in the configuration file.
+ '''
if obj is None:
return self
optdata = getattr(obj, self._attrname, None)
@@ -55,6 +75,12 @@
return self.default
def __set__(self, obj, value):
+ '''Called when the option is set (via the descriptor protocol).
+
+ @param obj: The configuration instance to modify.
+ @param value: The value to set the option to.
+ @return: Nothing.
+ '''
optdata = getattr(obj, self._attrname)
# Only try to parse if its a string
@@ -93,6 +119,9 @@
def parse(self, s):
'''Parse the string value to the Option's native value.
+ @param s: Raw string value to parse.
+ @return: Validated native value.
+
Will raise ValueError if there was a problem parsing the string.
Subclasses should override this.
'''
@@ -101,12 +130,23 @@
def tostring(self, value):
'''Convert the Option's native value to a string value.
- This does the opposite fo the parse() method above.
+ @param value: Native option value.
+ @return: String representation of input.
+
+ This does the opposite of the parse() method above.
Subclasses should override this.
'''
return str(value)
def Inherit(option_obj):
+ '''Clone an Option instance for the purposes of inheritance. The returned
+ instance has all the same properties as the input Option and shares items
+ such as the default value. Use this to avoid redefinition of reused
+ options.
+
+ @param option_obj: Option instance to inherit.
+ @return: New Option instance inherited from the input.
+ '''
new_option = option_obj.clone()
new_option.inherit = True
return new_option
@@ -311,7 +351,10 @@
class BaseConfig(object):
- #XXX: document
+ '''
+ Base class for storing configuration definitions. Subclass when creating
+ your own definitons.
+ '''
def __init__(self):
self._section = None
@@ -324,6 +367,13 @@
return '\n'.join(out)
def populate(self, parser, section, parent=None):
+ '''Set option values from a INI file section.
+
+ @param parser: ConfParser instance (or subclass)
+ @param section: INI file section to read use.
+ @param parent: Optional parent BaseConfig (or subclass) instance to use
+ when doing option value inheritance.
+ '''
self._section = section
self.cfg = parser # Keep a reference to the parser
@@ -344,38 +394,78 @@
def optionobj(cls, name):
'''Return the Option instance for the given name
'''
- return cls.__dict__[name]
+ # Look for Option instances in this class and base classes so that
+ # option inheritance works
+ for klass in (cls,) + cls.__bases__:
+ obj = klass.__dict__.get(name, None)
+ if obj is not None:
+ break
+
+ if obj is not None and isinstance(obj, Option):
+ return obj
+ else:
+ raise KeyError
optionobj = classmethod(optionobj)
+ def isoption(cls, name):
+ '''Return True if the given name refers to a defined option
+ '''
+ try:
+ cls.optionobj(name)
+ return True
+ except KeyError:
+ return False
+ isoption = classmethod(isoption)
+
def iterkeys(self):
- for name, item in self.__class__.__dict__.iteritems():
- if isinstance(item, Option):
- yield name
+ '''Yield the names of all defined options in the instance.
+ '''
+ for name, item in self.iteritems():
+ yield name
def iteritems(self):
- for name in self.iterkeys():
- yield (name, getattr(self, name))
+ '''Yield (name, value) pairs for every option in the instance.
+
+ The value returned is the parsed, validated option value.
+ '''
+ # Use dir() so that we see inherited options too
+ for name in dir(self):
+ if self.isoption(name):
+ yield (name, getattr(self, name))
def getConfigOption(self, option, default=None):
+ warnings.warn('getConfigOption() will go away in a future version of Yum.\n'
+ 'Please access option values as attributes or using getattr().',
+ DeprecationWarning)
if hasattr(self, option):
return getattr(self, option)
return default
def setConfigOption(self, option, value):
+ warnings.warn('setConfigOption() will go away in a future version of Yum.\n'
+ 'Please set option values as attributes or using setattr().',
+ DeprecationWarning)
if hasattr(self, option):
setattr(self, option, value)
else:
raise Errors.ConfigError, 'No such option %s' % option
class EarlyConf(BaseConfig):
-
+ '''
+ Configuration option definitions for yum.conf's [main] section that are
+ required before the other [main] options can be parsed (mainly due to
+ variable substitution).
+ '''
distroverpkg = Option('fedora-release')
installroot = Option('/')
class YumConf(EarlyConf):
+ '''
+ Configuration option definitions for yum.conf's [main] section.
+
+ Note: inherits options from EarlyConf too.
+ '''
- distroverpkg = Option('fedora-release')
- installroot = Option('/')
debuglevel = IntOption(2)
errorlevel = IntOption(2)
retries = IntOption(10)
@@ -428,8 +518,10 @@
metadata_expire = IntOption(1800) # time in seconds
class RepoConf(BaseConfig):
-
- name = Option() #XXX: error out if no name set
+ '''
+ Option definitions for repository INI file sections.
+ '''
+ name = Option()
enabled = Inherit(YumConf.enabled)
baseurl = UrlListOption()
mirrorlist = UrlOption()
@@ -454,7 +546,13 @@
metadata_expire = Inherit(YumConf.metadata_expire)
def readMainConfig(configfile, root):
- #XXX: document
+ '''Parse Yum's main configuration file
+
+ @param configfile: Path to the configuration file to parse (typically
+ '/etc/yum.conf').
+ @param root: The base path to use for installation (typically '/')
+ @return: Populated YumConf instance.
+ '''
# Read up config variables that are needed early to calculate substitution
# variables
@@ -495,11 +593,23 @@
return yumconf
def readRepoConfig(parser, section, mainconf):
- #XXX: document
+ '''Parse an INI file section for a repository.
+
+ @param parser: ConfParser or similar to read INI file values from.
+ @param section: INI file section to read.
+ @param mainconf: ConfParser or similar for yum.conf.
+ @return: Repository instance.
+ '''
conf = RepoConf()
conf.populate(parser, section, mainconf)
+ # Ensure that the repo name is set
+ if not conf.name:
+ conf.name = section
+ print >> sys.stderr, \
+ 'Repository %r is missing name in configuration, using id' % section
+
thisrepo = Repository(section)
# Transfer attributes across
@@ -548,6 +658,12 @@
return yumvar
def _getsysver(installroot, distroverpkg):
+ '''Calculate the release version for the system.
+
+ @param installroot: The value of the installroot option.
+ @param distroverpkg: The value of the distroverpkg option.
+ @return: The release version as a string (eg. '4' for FC4)
+ '''
ts = rpmUtils.transaction.initReadOnlyTransaction(root=installroot)
ts.pushVSFlags(~(rpm._RPMVSF_NOSIGNATURES|rpm._RPMVSF_NODIGESTS))
idx = ts.dbMatch('provides', distroverpkg)
@@ -563,3 +679,12 @@
del ts
return releasever
+
+#def main():
+# mainconf = readMainConfig('/etc/yum.conf', '/')
+# repoconf = readRepoConfig(mainconf.cfg, 'core', mainconf)
+#
+# print `repoconf.name`
+#
+#if __name__ == '__main__':
+# main()
More information about the Yum-cvs-commits
mailing list