Make 'import portage' statements more tolerant to broken source statements
authorZac Medico <zmedico@gentoo.org>
Sat, 1 Mar 2008 00:10:37 +0000 (00:10 -0000)
committerZac Medico <zmedico@gentoo.org>
Sat, 1 Mar 2008 00:10:37 +0000 (00:10 -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. (trunk r9400)

svn path=/main/branches/2.1.2/; revision=9401

pym/portage.py
pym/portage_util.py

index 97e3bbf12ab33f0eec932707bfb4e28b9cd503f6..b8da8d9b6e42a6fc4cfbc9025fcb40c27da1cb1a 100644 (file)
@@ -1104,7 +1104,11 @@ class config:
                @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
 
@@ -1377,7 +1381,7 @@ class config:
 
                        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 = {}
 
@@ -9997,7 +10001,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 486376bfceec0db25ccef8a945bb0e5a5c970ec1..902ed091ff3c079c3bb6e725b2f2aa086419786b 100644 (file)
@@ -16,6 +16,11 @@ except ImportError:
 if not hasattr(__builtins__, "set"):
        from sets import Set as set
 
+try:
+       import cStringIO as StringIO
+except ImportError:
+       import StringIO
+
 noiselimit = 0
 
 def writemsg(mystr,noiselevel=0,fd=None):
@@ -291,6 +296,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:
@@ -302,10 +316,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: