Make 'import portage' statements more tolerant to broken source statements
authorZac Medico <zmedico@gentoo.org>
Sat, 1 Mar 2008 00:04:09 +0000 (00:04 -0000)
committerZac Medico <zmedico@gentoo.org>
Sat, 1 Mar 2008 00:04:09 +0000 (00:04 -0000)
in make.conf since exceptions thrown during 'import portage' statements
can practically render the api unusable for api consumers. Thanks to lxnay
for the suggestion.

svn path=/main/trunk/; revision=9400

pym/portage/__init__.py
pym/portage/util.py

index e8a8f4f2541030cb78f786fddcdc4f8264536601..dfbe70fc25c4d6855fcdf0e94657c19926a96b69 100644 (file)
@@ -969,7 +969,11 @@ class config(object):
                @type local_config: Boolean
                """
 
-               debug = os.environ.get("PORTAGE_DEBUG") == "1"
+               # When initializing the global portage.settings instance, avoid
+               # raising exceptions whenever possible since exceptions thrown
+               # from 'import portage' or 'import portage.exceptions' statements
+               # can practically render the api unusable for api consumers.
+               tolerant = "_initializing_globals" in globals()
 
                self.already_in_regenerate = 0
 
@@ -1244,7 +1248,7 @@ class config(object):
 
                        self.mygcfg = getconfig(
                                os.path.join(config_root, MAKE_CONF_FILE.lstrip(os.path.sep)),
-                               allow_sourcing=True)
+                               tolerant=tolerant, allow_sourcing=True)
                        if self.mygcfg is None:
                                self.mygcfg = {}
 
@@ -6284,7 +6288,10 @@ def init_legacy_globals():
        for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
                kwargs[k] = os.environ.get(envvar, "/")
 
+       global _initializing_globals
+       _initializing_globals = True
        db = create_trees(**kwargs)
+       del _initializing_globals
 
        settings = db["/"]["vartree"].settings
        portdb = db["/"]["porttree"].dbapi
index 97c785c06f8152ee051320546dd98d5195ae8295..155a787f5331c33d61b4737e72ee6633498ed2f4 100644 (file)
@@ -21,6 +21,11 @@ try:
 except ImportError:
        import pickle as cPickle
 
+try:
+       import cStringIO as StringIO
+except ImportError:
+       import StringIO
+
 noiselimit = 0
 
 def initialize_logger(level=logging.WARN):
@@ -305,6 +310,15 @@ def writedict(mydict,myfilename,writekey=True):
                return 0
        return 1
 
+class _tolerant_shlex(shlex.shlex):
+       def sourcehook(self, newfile):
+               try:
+                       return shlex.shlex.sourcehook(self, newfile)
+               except EnvironmentError, e:
+                       writemsg("!!! Parse error in '%s': source command failed: %s\n" % \
+                               (self.infile, str(e)), noiselevel=-1)
+                       return (newfile, StringIO.StringIO())
+
 def getconfig(mycfg, tolerant=0, allow_sourcing=False, expand=True):
        mykeys={}
        try:
@@ -316,10 +330,14 @@ def getconfig(mycfg, tolerant=0, allow_sourcing=False, expand=True):
                        raise
                return None
        try:
+               if tolerant:
+                       shlex_class = _tolerant_shlex
+               else:
+                       shlex_class = shlex.shlex
                # The default shlex.sourcehook() implementation
                # only joins relative paths when the infile
                # attribute is properly set.
-               lex = shlex.shlex(f, infile=mycfg, posix=True)
+               lex = shlex_class(f, infile=mycfg, posix=True)
                lex.wordchars=string.digits+string.letters+"~!@#$%*_\:;?,./-+{}"     
                lex.quotes="\"'"
                if allow_sourcing: