Merged from trunk -r12633:12649
authorFabian Groffen <grobian@gentoo.org>
Thu, 19 Feb 2009 17:58:41 +0000 (17:58 -0000)
committerFabian Groffen <grobian@gentoo.org>
Thu, 19 Feb 2009 17:58:41 +0000 (17:58 -0000)
   | 12634   | Bug #230483 - Convert glsa-check option parsing to use the   |
   | zmedico | optparse module. This replaces some code which triggers a    |
   |         | traceback from 2to3. Thanks to Ali Polatel <hawking@g.o> for |
   |         | this patch.                                                  |

   | 12635   | For python-3.0 compatibility, raise a real exception instead |
   | zmedico | of a string.                                                 |

   | 12636   | Inside post_emerge(), skip the vardbapi counter check when   |
   | zmedico | in --pretend mode (significant performance improvement).     |
   |         | Thanks to Marat Radchenko (slonopotamus) for reporting.      |

   | 12637   | Don't bother to calculate PORTAGE_COUNTER_HASH when in       |
   | zmedico | --pretend mode.                                              |

   | 12638   | Use a regular expression for the file.name check. This       |
   | zmedico | replaces some odd map() usage that 2to3 warns about.         |

   | 12639   | For python-3.0 compatibility, don't use string.letters.      |
   | zmedico |                                                              |

   | 12640   | For compatibility with python-3.0, inherit from ObjectProxy  |
   | zmedico | instead of inheriting directly from file.                    |

   | 12641   | For compatibility with python-3.0, always open streams for   |
   | zmedico | pickles in binary mode.                                      |

   | 12642   | For compatibility with python-3.0, open files in text mode   |
   | zmedico | where appropriate.                                           |

   | 12643   | Revert accidental python-3.0 syntax.                         |
   | zmedico |                                                              |

   | 12644   | Tweak code to avoid python-3.0 errors like this one:         |
   | zmedico | SyntaxError: can not delete variable 'e' referenced in       |
   |         | nested scope                                                 |

   | 12645   | For python-3.0 compatibility, encode strings as binary       |
   | zmedico | before trying to pass them to hashlib.                       |

   | 12646   | Tweak exception handling indentation to avoid a bug in 2to3. |
   | zmedico |                                                              |

   | 12647   | Fix update() methods to work with python-3.0.                |
   | zmedico |                                                              |

   | 12648   | Handle ValueError when unpickling, since this can be         |
   | zmedico | triggered by an unsupported pickle protocol.                 |

   | 12649   | Decode terminal codes from binary when necessary, for        |
   | zmedico | python-3.0 compatibility since sys.stdout is a text stream.  |

svn path=/main/branches/prefix/; revision=12652

12 files changed:
bin/archive-conf
bin/glsa-check
bin/repoman
pym/_emerge/__init__.py
pym/portage/__init__.py
pym/portage/cache/flat_hash.py
pym/portage/cache/mappings.py
pym/portage/dbapi/vartree.py
pym/portage/elog/messages.py
pym/portage/env/loaders.py
pym/portage/getbinpkg.py
pym/portage/util.py

index f32edf29625be1104f312922c441fa36c55063aa..887af6de935705a4074a017eeb63a3448b4a32f6 100755 (executable)
@@ -89,8 +89,8 @@ def archive_conf():
                                 md5_match_hash[conf] = conf
                             todo_cnt -= 1
                             if todo_cnt == 0:
-                                raise "Break"
-    except "Break":
+                                raise StopIteration()
+    except StopIteration:
         pass
 
     for conf in args:
index 97f393c8ee97e84eb44a184e3a5cb17ef849591b..d5ab21f4bdd9d67a8d8201982a1c275ba7bbbc8e 100644 (file)
@@ -17,111 +17,89 @@ import portage
 
 from portage.output import *
 
-from getopt import getopt, GetoptError
+from optparse import OptionGroup, OptionParser
 
 __program__ = "glsa-check"
 __author__ = "Marius Mauch <genone@gentoo.org>"
 __version__ = "1.0"
 
-optionmap = [
-["-l", "--list", "list all unapplied GLSA"],
-["-d", "--dump", "--print", "show all information about the given GLSA"],
-["-t", "--test", "test if this system is affected by the given GLSA"],
-["-p", "--pretend", "show the necessary commands to apply this GLSA"],
-["-f", "--fix", "try to auto-apply this GLSA (experimental)"],
-["-i", "--inject", "inject the given GLSA into the checkfile"],
-["-n", "--nocolor", "disable colors (option)"],
-["-e", "--emergelike", "do not use a least-change algorithm (option)"],
-["-h", "--help", "show this help message"],
-["-V", "--version", "some information about this tool"],
-["-v", "--verbose", "print more information (option)"],
-["-c", "--cve", "show CAN ids in listing mode (option)"],
-["-m", "--mail", "send a mail with the given GLSAs to the administrator"]
-]
+def cb_version(*args, **kwargs):
+       """Callback for --version"""
+       sys.stderr.write("\n"+ __program__ + ", version " + __version__ + "\n")
+       sys.stderr.write("Author: " + __author__ + "\n")
+       sys.stderr.write("This program is licensed under the GPL, version 2\n\n")
+       sys.exit(0)
 
 # option parsing
-args = []
-params = []
-try:
-       args, params = getopt(sys.argv[1:], "".join([o[0][1] for o in optionmap]), \
-               [x[2:] for x in reduce(lambda x,y: x+y, [z[1:-1] for z in optionmap])])
-#              ["dump", "print", "list", "pretend", "fix", "inject", "help", "verbose", "version", "test", "nocolor", "cve", "mail"])
-       args = [a for a,b in args]
-       
-       for option in ["--nocolor", "-n"]:
-               if option in args:
-                       nocolor()
-                       args.remove(option)
-                       
-       verbose = False
-       for option in ["--verbose", "-v"]:
-               if option in args:
-                       verbose = True
-                       args.remove(option)
-
-       list_cve = False
-       for option in ["--cve", "-c"]:
-               if option in args:
-                       list_cve = True
-                       args.remove(option)
-       
-       least_change = True
-       for option in ["--emergelike", "-e"]:
-               if option in args:
-                       least_change = False
-                       args.remove(option)
-
-       # sanity checking
-       if len(args) <= 0:
-               sys.stderr.write("no option given: what should I do ?\n")
-               mode="help"
-       elif len(args) > 1:
-               sys.stderr.write("please use only one command per call\n")
-               mode = "help"
-       else:
-               # in what mode are we ?
-               args = args[0]
-               for m in optionmap:
-                       if args in [o for o in m[:-1]]:
-                               mode = m[1][2:]
-
-except GetoptError, e:
-       sys.stderr.write("unknown option given: ")
-       sys.stderr.write(str(e)+"\n")
-       mode = "help"
-
-# we need a set of glsa for most operation modes
-if len(params) <= 0 and mode in ["fix", "test", "pretend", "dump", "inject", "mail"]:
+parser = OptionParser(usage="%prog <option> [glsa-list]",
+               version="%prog "+ __version__)
+parser.epilog = "glsa-list can contain an arbitrary number of GLSA ids," \
+               " filenames containing GLSAs or the special identifiers" \
+               " 'all', 'new' and 'affected'"
+
+modes = OptionGroup(parser, "Modes")
+modes.add_option("-l", "--list", action="store_const",
+               const="list", dest="mode",
+               help="List all unapplied GLSA")
+modes.add_option("-d", "--dump", action="store_const",
+               const="dump", dest="mode",
+               help="Show all information about the given GLSA")
+modes.add_option("", "--print", action="store_const",
+               const="dump", dest="mode",
+               help="Alias for --dump")
+modes.add_option("-t", "--test", action="store_const",
+               const="test", dest="mode",
+               help="Test if this system is affected by the given GLSA")
+modes.add_option("-p", "--pretend", action="store_const",
+               const="pretend", dest="mode",
+               help="Show the necessary commands to apply this GLSA")
+modes.add_option("-f", "--fix", action="store_const",
+               const="fix", dest="mode",
+               help="Try to auto-apply this GLSA (experimental)")
+modes.add_option("-i", "--inject", action="store_const", dest="mode",
+               help="Inject the given GLSA into the checkfile")
+modes.add_option("-m", "--mail", action="store_const",
+               const="mail", dest="mode",
+               help="Send a mail with the given GLSAs to the administrator")
+parser.add_option_group(modes)
+
+parser.remove_option("--version")
+parser.add_option("-V", "--version", action="callback",
+               callback=cb_version, help="Some information about this tool")
+parser.add_option("-v", "--verbose", action="store_true", dest="verbose",
+               help="Print more information")
+parser.add_option("-n", "--nocolor", action="callback",
+               callback=lambda *args, **kwargs: nocolor(),
+               help="Disable colors")
+parser.add_option("-e", "--emergelike", action="store_false", dest="least_change",
+               help="Do not use a least-change algorithm")
+parser.add_option("-c", "--cve", action="store_true", dest="list_cve",
+               help="Show CAN ids in listing mode")
+
+options, params = parser.parse_args()
+
+mode = options.mode
+least_change = options.least_change
+list_cve = options.list_cve
+verbose = options.verbose
+
+# Sanity checking
+if mode is None:
+       sys.stderr.write("No mode given: what should I do?\n")
+       parser.print_help()
+       sys.exit(1)
+elif mode != "list" and not params:
        sys.stderr.write("\nno GLSA given, so we'll do nothing for now. \n")
        sys.stderr.write("If you want to run on all GLSA please tell me so \n")
        sys.stderr.write("(specify \"all\" as parameter)\n\n")
-       mode = "help"
-elif len(params) <= 0 and mode == "list":
-       params.append("new")
-       
-# show help message
-if mode == "help":
-       sys.stderr.write("\nSyntax: glsa-check <option> [glsa-list]\n\n")
-       for m in optionmap:
-               sys.stderr.write(m[0] + "\t" + m[1] + "   \t: " + m[-1] + "\n")
-               for o in m[2:-1]:
-                       sys.stderr.write("\t" + o + "\n")
-       sys.stderr.write("\nglsa-list can contain an arbitrary number of GLSA ids, \n")
-       sys.stderr.write("filenames containing GLSAs or the special identifiers \n")
-       sys.stderr.write("'all', 'new' and 'affected'\n")
+       parser.print_help()
        sys.exit(1)
-
-# we need root priviledges for write access
-if mode in ["fix", "inject"] and os.geteuid() != 0:
-       sys.stderr.write("\nThis tool needs root access to "+mode+" this GLSA\n\n")
+elif mode in ["fix", "inject"] and os.geteuid() != 0:
+       # we need root priviledges for write access
+       sys.stderr.write("\nThis tool needs root access to "+options.mode+" this GLSA\n\n")
        sys.exit(2)
-
-# show version and copyright information
-if mode == "version":
-       sys.stderr.write("\n"+ __program__ + ", version " + __version__ + "\n")
-       sys.stderr.write("Author: " + __author__ + "\n")
-       sys.stderr.write("This program is licensed under the GPL, version 2\n\n")
-       sys.exit(0)
+elif mode == "list" and not params:
+       params.append("new")
 
 # delay this for speed increase
 from portage.glsa import *
index 8d0cfaf25c281aa3a3392a58f4278c3015777502..eeedf8ee2466e8bc92baf3d3a096c172ccf362ce 100755 (executable)
@@ -71,11 +71,7 @@ util.initialize_logger()
 # 14 is the length of DESCRIPTION=""
 max_desc_len = 100
 allowed_filename_chars="a-zA-Z0-9._-+:"
-allowed_filename_chars_set = {}
-map(allowed_filename_chars_set.setdefault, map(chr, range(ord('a'), ord('z')+1)))
-map(allowed_filename_chars_set.setdefault, map(chr, range(ord('A'), ord('Z')+1)))
-map(allowed_filename_chars_set.setdefault, map(chr, range(ord('0'), ord('9')+1)))
-map(allowed_filename_chars_set.setdefault, map(chr, map(ord, [".", "-", "_", "+", ":"])))
+disallowed_filename_chars_re = re.compile(r'[^a-zA-Z0-9._\-+:]')
 bad = create_color_func("BAD")
 
 # A sane umask is needed for files that portage creates.
@@ -604,7 +600,7 @@ profiles={}
 valid_profile_types = frozenset(["dev", "exp", "stable"])
 descfile=portdir+"/profiles/profiles.desc"
 if os.path.exists(descfile):
-       for i, x in enumerate(open(descfile, 'rb')):
+       for i, x in enumerate(open(descfile)):
                if x[0]=="#":
                        continue
                arch=x.split()
@@ -864,11 +860,11 @@ for x in scanlist:
                continue
 
        for y in checkdirlist:
-               for c in y.strip(os.path.sep):
-                       if c not in allowed_filename_chars_set:
-                               stats["file.name"] += 1
-                               fails["file.name"].append("%s/%s: char '%s'" % (checkdir, y, c))
-                               break
+               m = disallowed_filename_chars_re.search(y.strip(os.sep))
+               if m is not None:
+                       stats["file.name"] += 1
+                       fails["file.name"].append("%s/%s: char '%s'" % \
+                               (checkdir, y, m.group(0)))
 
                if not (y in ("ChangeLog", "metadata.xml") or y.endswith(".ebuild")):
                        continue
@@ -1003,11 +999,12 @@ for x in scanlist:
                                stats["file.size"] += 1
                                fails["file.size"].append("("+ str(mystat.st_size/1024) + "K) "+x+"/files/"+y)
 
-                       for c in os.path.basename(y.rstrip(os.path.sep)):
-                               if c not in allowed_filename_chars_set:
-                                       stats["file.name"] += 1
-                                       fails["file.name"].append("%s/files/%s: char '%s'" % (checkdir, y, c))
-                                       break
+                       m = disallowed_filename_chars_re.search(
+                               os.path.basename(y.rstrip(os.sep)))
+                       if m is not None:
+                               stats["file.name"] += 1
+                               fails["file.name"].append("%s/files/%s: char '%s'" % \
+                                       (checkdir, y, m.group(0)))
 
                        if desktop_file_validate and desktop_pattern.match(y):
                                status, cmd_output = commands.getstatusoutput(
@@ -1447,7 +1444,7 @@ for x in scanlist:
                # Syntax Checks
                relative_path = os.path.join(x, y + ".ebuild")
                full_path = os.path.join(repodir, relative_path)
-               f = open(full_path, 'rb')
+               f = open(full_path)
                try:
                        for check_name, e in run_checks(f, pkg):
                                stats[check_name] += 1
index 2967beafe9cf20f79cb142423ccbb4397360ecb0..33edec9741c7eb73c064d29b2a4def9df0dd4731 100644 (file)
@@ -4070,13 +4070,12 @@ class BlockerCache(portage.cache.mappings.MutableMapping):
 
        def _load(self):
                try:
-                       f = open(self._cache_filename)
+                       f = open(self._cache_filename, mode='rb')
                        mypickle = pickle.Unpickler(f)
-                       mypickle.find_global = None
                        self._cache_data = mypickle.load()
                        f.close()
                        del f
-               except (IOError, OSError, EOFError, pickle.UnpicklingError), e:
+               except (IOError, OSError, EOFError, ValueError, pickle.UnpicklingError), e:
                        if isinstance(e, pickle.UnpicklingError):
                                writemsg("!!! Error loading '%s': %s\n" % \
                                        (self._cache_filename, str(e)), noiselevel=-1)
@@ -4156,7 +4155,7 @@ class BlockerCache(portage.cache.mappings.MutableMapping):
                if len(self._modified) >= self._cache_threshold and \
                        secpass >= 2:
                        try:
-                               f = portage.util.atomic_ofstream(self._cache_filename)
+                               f = portage.util.atomic_ofstream(self._cache_filename, mode='wb')
                                pickle.dump(self._cache_data, f, -1)
                                f.close()
                                portage.util.apply_secpass_permissions(
@@ -9667,6 +9666,9 @@ class JobStatusDisplay(object):
                        for k, capname in self._termcap_name_map.iteritems():
                                term_codes[k] = self._default_term_codes[capname]
                        object.__setattr__(self, "_term_codes", term_codes)
+               for k, v in self._term_codes.items():
+                       if not isinstance(v, str):
+                               self._term_codes[k] = v.decode()
 
        def _init_term(self):
                """
@@ -10659,7 +10661,7 @@ class Scheduler(PollScheduler):
                        log_path = self._locate_failure_log(failed_pkg)
                        if log_path is not None:
                                try:
-                                       log_file = open(log_path, 'rb')
+                                       log_file = open(log_path)
                                except IOError:
                                        pass
 
@@ -11206,7 +11208,11 @@ class Scheduler(PollScheduler):
                        success, mydepgraph, dropped_tasks = resume_depgraph(
                                self.settings, self.trees, self._mtimedb, self.myopts,
                                myparams, self._spinner)
-               except depgraph.UnsatisfiedResumeDep, e:
+               except depgraph.UnsatisfiedResumeDep, exc:
+                       # rename variable to avoid python-3.0 error:
+                       # SyntaxError: can not delete variable 'e' referenced in nested
+                       #              scope
+                       e = exc
                        mydepgraph = e.depgraph
                        dropped_tasks = set()
 
@@ -12262,8 +12268,8 @@ def post_emerge(root_config, myopts, mtimedb, retval):
        _flush_elog_mod_echo()
 
        counter_hash = settings.get("PORTAGE_COUNTER_HASH")
-       if counter_hash is not None and \
-               counter_hash == vardbapi._counter_hash():
+       if "--pretend" in myopts or (counter_hash is not None and \
+               counter_hash == vardbapi._counter_hash()):
                display_news_notification(root_config, myopts)
                # If vdb state has not changed then there's nothing else to do.
                sys.exit(retval)
@@ -14098,9 +14104,11 @@ def resume_depgraph(settings, trees, mtimedb, myopts, myparams, spinner):
                                                unsatisfied_parents[parent_node] = parent_node
                                                unsatisfied_stack.append(parent_node)
 
-                       pruned_mergelist = [x for x in mergelist \
+                       pruned_mergelist = []
+                       for x in mergelist:
                                if isinstance(x, list) and \
-                               tuple(x) not in unsatisfied_parents]
+                                       tuple(x) not in unsatisfied_parents:
+                                       pruned_mergelist.append(x)
 
                        # If the mergelist doesn't shrink then this loop is infinite.
                        if len(pruned_mergelist) == len(mergelist):
@@ -14513,14 +14521,7 @@ def action_build(settings, trees, mtimedb,
                        # a list type for options.
                        mtimedb["resume"]["myopts"] = myopts.copy()
 
-                       # Convert Atom instances to plain str since the mtimedb loader
-                       # sets unpickler.find_global = None which causes unpickler.load()
-                       # to raise the following exception:
-                       #
-                       # cPickle.UnpicklingError: Global and instance pickles are not supported.
-                       #
-                       # TODO: Maybe stop setting find_global = None, or find some other
-                       # way to avoid accidental triggering of the above UnpicklingError.
+                       # Convert Atom instances to plain str.
                        mtimedb["resume"]["favorites"] = [str(x) for x in favorites]
 
                        if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
@@ -15226,9 +15227,10 @@ def emerge_main():
                mysettings =  trees[myroot]["vartree"].settings
                mysettings.unlock()
                adjust_config(myopts, mysettings)
-               mysettings["PORTAGE_COUNTER_HASH"] = \
-                       trees[myroot]["vartree"].dbapi._counter_hash()
-               mysettings.backup_changes("PORTAGE_COUNTER_HASH")
+               if "--pretend" not in myopts:
+                       mysettings["PORTAGE_COUNTER_HASH"] = \
+                               trees[myroot]["vartree"].dbapi._counter_hash()
+                       mysettings.backup_changes("PORTAGE_COUNTER_HASH")
                mysettings.lock()
                del myroot, mysettings
 
index e4245ed2c04045a314e32c1527eccea15ce36df2..ee4cf8820c7866454de9c1c57e91d890596321b6 100644 (file)
@@ -4707,7 +4707,7 @@ def _check_build_log(mysettings, out=None):
        if logfile is None:
                return
        try:
-               f = open(logfile, 'rb')
+               f = open(logfile)
        except EnvironmentError:
                return
 
@@ -7520,7 +7520,7 @@ def commit_mtimedb(mydict=None, filename=None):
        d = {} # for full backward compat, pickle it as a plain dict object.
        d.update(mydict)
        try:
-               f = atomic_ofstream(filename)
+               f = atomic_ofstream(filename, mode='wb')
                pickle.dump(d, f, -1)
                f.close()
                portage.util.apply_secpass_permissions(filename, uid=uid, gid=portage_gid, mode=0664)
@@ -7685,13 +7685,12 @@ class MtimeDB(dict):
 
        def _load(self, filename):
                try:
-                       f = open(filename)
+                       f = open(filename, 'rb')
                        mypickle = pickle.Unpickler(f)
-                       mypickle.find_global = None
                        d = mypickle.load()
                        f.close()
                        del f
-               except (IOError, OSError, EOFError, pickle.UnpicklingError), e:
+               except (IOError, OSError, EOFError, ValueError, pickle.UnpicklingError), e:
                        if isinstance(e, pickle.UnpicklingError):
                                writemsg("!!! Error loading '%s': %s\n" % \
                                        (filename, str(e)), noiselevel=-1)
index b9781b0c7d7cd4e21c811a6fdd582c3b9af4ebf2..dda380e1c6be624620598ec1e1ff1583a853b48f 100644 (file)
@@ -65,7 +65,8 @@ class database(fs_template.FsBased):
 #              import pdb;pdb.set_trace()
                s = cpv.rfind("/")
                fp = os.path.join(self.location,cpv[:s],".update.%i.%s" % (os.getpid(), cpv[s+1:]))
-               try:    myf=open(fp, "w")
+               try:
+                       myf = open(fp, 'w')
                except (IOError, OSError), e:
                        if errno.ENOENT == e.errno:
                                try:
@@ -89,7 +90,8 @@ class database(fs_template.FsBased):
                #update written.  now we move it.
 
                new_fp = os.path.join(self.location,cpv)
-               try:    os.rename(fp, new_fp)
+               try:
+                       os.rename(fp, new_fp)
                except (OSError, IOError), e:
                        os.remove(fp)
                        raise cache_errors.CacheCorruption(cpv, e)
index 5fe836daad115c468b266ef2247c25fb98ae2bee..a632ce61d134f99c5747684e2e79d694e08d915e 100644 (file)
@@ -115,7 +115,12 @@ class MutableMapping(Mapping):
                if other is None:
                        pass
                elif hasattr(other, 'iteritems'):
-                       for k, v in other.iteritems():
+                       # Use getattr to avoid interference from 2to3.
+                       for k, v in getattr(other, 'iteritems')():
+                               self[k] = v
+               elif hasattr(other, 'items'):
+                       # Use getattr to avoid interference from 2to3.
+                       for k, v in getattr(other, 'items')():
                                self[k] = v
                elif hasattr(other, 'keys'):
                        for k in other.keys():
@@ -358,14 +363,25 @@ def slot_dict_class(keys, prefix="_val_"):
                                        self[key] = default
                                return default
 
-                       def update(self, d):
-                               i = getattr(d, "iteritems", None)
-                               if i is None:
-                                       i = d
+                       def update(self, other=None, **kwargs):
+                               if other is None:
+                                       pass
+                               elif hasattr(other, 'iteritems'):
+                                       # Use getattr to avoid interference from 2to3.
+                                       for k, v in getattr(other, 'iteritems')():
+                                               self[k] = v
+                               elif hasattr(other, 'items'):
+                                       # Use getattr to avoid interference from 2to3.
+                                       for k, v in getattr(other, 'items')():
+                                               self[k] = v
+                               elif hasattr(other, 'keys'):
+                                       for k in other.keys():
+                                               self[k] = other[k]
                                else:
-                                       i = i()
-                               for k, v in i:
-                                       self[k] = v
+                                       for k, v in other:
+                                               self[k] = v
+                               if kwargs:
+                                       self.update(kwargs)
 
                        def __getitem__(self, k):
                                try:
index 25f600ddd5489ce32e67204c927675b41e427866..e4cdbd696cf59e0ce0d8adc7a2dab94c14faeaeb 100644 (file)
@@ -58,7 +58,7 @@ class PreservedLibsRegistry(object):
        def load(self):
                """ Reload the registry data from file """
                try:
-                       self._data = pickle.load(open(self._filename, "r"))
+                       self._data = pickle.load(open(self._filename, 'rb'))
                except (EOFError, IOError), e:
                        if isinstance(e, EOFError) or e.errno == errno.ENOENT:
                                self._data = {}
@@ -75,7 +75,7 @@ class PreservedLibsRegistry(object):
                        self._data == self._data_orig:
                        return
                try:
-                       f = atomic_ofstream(self._filename)
+                       f = atomic_ofstream(self._filename, 'wb')
                        pickle.dump(self._data, f)
                        f.close()
                except EnvironmentError, e:
@@ -1313,7 +1313,7 @@ class vardbapi(dbapi):
                                counter, = self.aux_get(cpv, aux_keys)
                        except KeyError:
                                continue
-                       h.update(counter)
+                       h.update(counter.encode())
                return h.hexdigest()
 
        def cpv_inject(self, mycpv):
@@ -1553,7 +1553,7 @@ class vardbapi(dbapi):
                                        del self._aux_cache["packages"][cpv]
                        del self._aux_cache["modified"]
                        try:
-                               f = atomic_ofstream(self._aux_cache_filename)
+                               f = atomic_ofstream(self._aux_cache_filename, 'wb')
                                pickle.dump(self._aux_cache, f, -1)
                                f.close()
                                apply_secpass_permissions(
@@ -1571,13 +1571,12 @@ class vardbapi(dbapi):
        def _aux_cache_init(self):
                aux_cache = None
                try:
-                       f = open(self._aux_cache_filename)
+                       f = open(self._aux_cache_filename, 'rb')
                        mypickle = pickle.Unpickler(f)
-                       mypickle.find_global = None
                        aux_cache = mypickle.load()
                        f.close()
                        del f
-               except (IOError, OSError, EOFError, pickle.UnpicklingError), e:
+               except (IOError, OSError, EOFError, ValueError, pickle.UnpicklingError), e:
                        if isinstance(e, pickle.UnpicklingError):
                                writemsg("!!! Error loading '%s': %s\n" % \
                                        (self._aux_cache_filename, str(e)), noiselevel=-1)
@@ -1905,7 +1904,7 @@ class vardbapi(dbapi):
 
                def _hash_str(self, s):
                        h = self._new_hash()
-                       h.update(s)
+                       h.update(s.encode())
                        h = h.hexdigest()
                        h = h[-self._hex_chars:]
                        h = int(h, 16)
index ad95c975dafe83a12c2303d4a10e0b23160e7b47..a09b73229d05419fd58a5e199a2f59860201866b 100644 (file)
@@ -35,7 +35,7 @@ def collect_ebuild_messages(path):
                        logentries[msgfunction] = []
                lastmsgtype = None
                msgcontent = []
-               for l in open(filename, "rb"):
+               for l in open(filename):
                        if not l:
                                continue
                        try:
index 61bb6912661cfca1e297efe3257bfd9b99a17b4f..b23c7f39350df22da8ea24512861005b2159b34a 100644 (file)
@@ -132,7 +132,7 @@ class FileLoader(DataLoader):
                # once, which may be expensive due to digging in child classes.
                func = self.lineParser
                for fn in RecursiveFileLoader(self.fname):
-                       f = open(fn, 'rb')
+                       f = open(fn)
                        for line_num, line in enumerate(f):
                                func(line, line_num, data, errors)
                return (data, errors)
index bf00ebd65cf14122f5c602c1ba603e78702f3a36..d49fcd92007b73e7332fea72340dd22dc15c653b 100644 (file)
@@ -471,7 +471,8 @@ def dir_get_metadata(baseurl, conn=None, chunk_size=3000, verbose=1, usingcache=
        else:
                keepconnection = 1
 
-       cache_path = "/var/cache/edb"
+       cache_path = CACHE_PATH
+       metadatafilename = os.path.join(cache_path, 'remote_metadata.pickle')
 
        if makepickle is None:
                makepickle = CACHE_PATH+"/metadata.idx.most_recent"
@@ -486,12 +487,12 @@ def dir_get_metadata(baseurl, conn=None, chunk_size=3000, verbose=1, usingcache=
 
        out = sys.stdout
        try:
-               metadatafile = open(CACHE_PATH+"/remote_metadata.pickle")
+               metadatafile = open(metadatafilename, 'rb')
                metadata = pickle.load(metadatafile)
                out.write("Loaded metadata pickle.\n")
                out.flush()
                metadatafile.close()
-       except (pickle.UnpicklingError, OSError, IOError, EOFError):
+       except (IOError, OSError, EOFError, ValueError, pickle.UnpicklingError):
                metadata = {}
        if baseurl not in metadata:
                metadata[baseurl]={}
@@ -575,7 +576,7 @@ def dir_get_metadata(baseurl, conn=None, chunk_size=3000, verbose=1, usingcache=
                                        sys.stderr.write("!!! "+str(e)+"\n")
                                        sys.stderr.flush()
                        try:
-                               metadatafile = open(CACHE_PATH+"/remote_metadata.pickle", "w+")
+                               metadatafile = open(metadatafilename, 'wb')
                                pickle.dump(metadata,metadatafile)
                                metadatafile.close()
                        except SystemExit, e:
@@ -667,11 +668,11 @@ def dir_get_metadata(baseurl, conn=None, chunk_size=3000, verbose=1, usingcache=
        try:
                if "modified" in metadata[baseurl] and metadata[baseurl]["modified"]:
                        metadata[baseurl]["timestamp"] = int(time.time())
-                       metadatafile = open(CACHE_PATH+"/remote_metadata.pickle", "w+")
+                       metadatafile = open(metadatafilename, 'wb')
                        pickle.dump(metadata,metadatafile)
                        metadatafile.close()
                if makepickle:
-                       metadatafile = open(makepickle, "w")
+                       metadatafile = open(makepickle, 'wb')
                        pickle.dump(metadata[baseurl]["data"],metadatafile)
                        metadatafile.close()
        except SystemExit, e:
index 1a8acd7f093e4b3bc25ee871c2ed1dbaa46375ed..dd96c48a8533198890e78f321d927dccf20c3962 100644 (file)
@@ -334,6 +334,65 @@ def writedict(mydict,myfilename,writekey=True):
                return 0
        return 1
 
+class ObjectProxy(object):
+
+       """
+       Object that acts as a proxy to another object, forwarding
+       attribute accesses and method calls. This can be useful
+       for implementing lazy initialization.
+       """
+
+       def _get_target(self):
+               raise NotImplementedError(self)
+
+       def __getattribute__(self, attr):
+               result = object.__getattribute__(self, '_get_target')()
+               return getattr(result, attr)
+
+       def __setattr__(self, attr, value):
+               result = object.__getattribute__(self, '_get_target')()
+               setattr(result, attr, value)
+
+       def __call__(self, *args, **kwargs):
+               result = object.__getattribute__(self, '_get_target')()
+               return result(*args, **kwargs)
+
+       def __setitem__(self, key, value):
+               object.__getattribute__(self, '_get_target')()[key] = value
+
+       def __getitem__(self, key):
+               return object.__getattribute__(self, '_get_target')()[key]
+
+       def __delitem__(self, key):
+               del object.__getattribute__(self, '_get_target')()[key]
+
+       def __contains__(self, key):
+               return key in object.__getattribute__(self, '_get_target')()
+
+       def __iter__(self):
+               return iter(object.__getattribute__(self, '_get_target')())
+
+       def __len__(self):
+               return len(object.__getattribute__(self, '_get_target')())
+
+       def __repr__(self):
+               return repr(object.__getattribute__(self, '_get_target')())
+
+       def __str__(self):
+               return str(object.__getattribute__(self, '_get_target')())
+
+       def __hash__(self):
+               return hash(object.__getattribute__(self, '_get_target')())
+
+       def __eq__(self, other):
+               return object.__getattribute__(self, '_get_target')() == other
+
+       def __ne__(self, other):
+               return object.__getattribute__(self, '_get_target')() != other
+
+       def __nonzero__(self):
+               return bool(object.__getattribute__(self, '_get_target')())
+
 class _tolerant_shlex(shlex.shlex):
        def sourcehook(self, newfile):
                try:
@@ -343,7 +402,7 @@ class _tolerant_shlex(shlex.shlex):
                                (self.infile, str(e)), noiselevel=-1)
                        return (newfile, StringIO.StringIO())
 
-class _insert_newline_eof(file):
+class _insert_newline_eof(ObjectProxy):
        """
        Read functions insert anywhere from 0 and 2 newlines just before eof.
        This is useful as a workaround for avoiding a silent error in shlex that
@@ -351,32 +410,53 @@ class _insert_newline_eof(file):
        trailing newline after the source statement.
        """
 
+       def __init__(self, *pargs, **kargs):
+               ObjectProxy.__init__(self)
+               object.__setattr__(self, '_file', open(*pargs, **kargs))
+
+       def _get_target(self):
+               return object.__getattribute__(self, '_file')
+
+       def __getattribute__(self, attr):
+               if attr in ('read', 'readline', 'readlines'):
+                       return object.__getattribute__(self, attr)
+               return getattr(object.__getattribute__(self, '_file'), attr)
+
        def read(self, *args):
-               if hasattr(self, "_got_eof"):
+               try:
+                       object.__getattribute__(self, '_got_eof')
                        return ""
-               rval = file.read(self, *args)
+               except AttributeError:
+                       pass
+               rval = object.__getattribute__(self, '_file').read(*args)
                if rval and not args and rval[-1:] != "\n":
                        rval += "\n"
                if not rval:
-                       self._got_eof = True
+                       object.__setattr__(self, '_got_eof', True)
                        return "\n"
                return rval
 
        def readline(self, *args):
-               if hasattr(self, "_got_eof"):
+               try:
+                       object.__getattribute__(self, '_got_eof')
                        return ""
-               rval = file.readline(self, *args)
+               except AttributeError:
+                       pass
+               rval = object.__getattribute__(self, '_file').readline(*args)
                if rval and rval[-1:] != "\n":
                        rval += "\n"
                if not rval:
-                       self._got_eof = True
+                       object.__setattr__(self, '_got_eof', True)
                        rval = "\n"
                return rval
 
        def readlines(self, *args):
-               if hasattr(self, "_got_eof"):
+               try:
+                       object.__getattribute__(self, '_got_eof')
                        return []
-               lines = file.readlines(self, *args)
+               except AttributeError:
+                       pass
+               lines = object.__getattribute__(self, '_file').readlines(*args)
                if lines and lines[-1][-1:] != "\n":
                        lines[-1] += "\n"
                return lines
@@ -391,7 +471,7 @@ def getconfig(mycfg, tolerant=0, allow_sourcing=False, expand=True):
                expand_map = {}
        mykeys = {}
        try:
-               f = _insert_newline_eof(mycfg, 'rb')
+               f = _insert_newline_eof(mycfg)
        except IOError, e:
                if e.errno == PermissionDenied.errno:
                        raise PermissionDenied(mycfg)
@@ -408,7 +488,7 @@ def getconfig(mycfg, tolerant=0, allow_sourcing=False, expand=True):
                # only joins relative paths when the infile
                # attribute is properly set.
                lex = shlex_class(f, infile=mycfg, posix=True)
-               lex.wordchars=string.digits+string.letters+"~!@#$%*_\:;?,./-+{}"     
+               lex.wordchars += "~!@#$%*_\:;?,./-+{}"
                lex.quotes="\"'"
                if allow_sourcing:
                        lex.source="source"
@@ -578,9 +658,8 @@ def pickle_read(filename,default=None,debug=0):
                return default
        data = None
        try:
-               myf = open(filename)
+               myf = open(filename, 'rb')
                mypickle = pickle.Unpickler(myf)
-               mypickle.find_global = None
                data = mypickle.load()
                myf.close()
                del mypickle,myf
@@ -882,7 +961,7 @@ def apply_secpass_permissions(filename, uid=-1, gid=-1, mode=-1, mask=-1,
                stat_cached=stat_cached, follow_links=follow_links)
        return all_applied
 
-class atomic_ofstream(file):
+class atomic_ofstream(ObjectProxy):
        """Write a file atomically via os.rename().  Atomic replacement prevents
        interprocess interference and prevents corruption of the target
        file when the write is interrupted (for example, when an 'out of space'
@@ -890,36 +969,48 @@ class atomic_ofstream(file):
 
        def __init__(self, filename, mode='w', follow_links=True, **kargs):
                """Opens a temporary filename.pid in the same directory as filename."""
-               self._aborted = False
+               ObjectProxy.__init__(self)
+               object.__setattr__(self, '_aborted', False)
 
                if follow_links:
                        canonical_path = os.path.realpath(filename)
-                       self._real_name = canonical_path
+                       object.__setattr__(self, '_real_name', canonical_path)
                        tmp_name = "%s.%i" % (canonical_path, os.getpid())
                        try:
-                               super(atomic_ofstream, self).__init__(tmp_name, mode=mode, **kargs)
+                               object.__setattr__(self, '_file',
+                                       open(tmp_name, mode=mode, **kargs))
                                return
-                       except (OSError, IOError), e:
+                       except IOError, e:
                                if canonical_path == filename:
                                        raise
                                writemsg("!!! Failed to open file: '%s'\n" % tmp_name,
                                        noiselevel=-1)
                                writemsg("!!! %s\n" % str(e), noiselevel=-1)
 
-               self._real_name = filename
+               object.__setattr__(self, '_real_name', filename)
                tmp_name = "%s.%i" % (filename, os.getpid())
-               super(atomic_ofstream, self).__init__(tmp_name, mode=mode, **kargs)
+               object.__setattr__(self, '_file', open(tmp_name, mode=mode, **kargs))
+
+       def _get_target(self):
+               return object.__getattribute__(self, '_file')
+
+       def __getattribute__(self, attr):
+               if attr in ('close', 'abort', '__del__'):
+                       return object.__getattribute__(self, attr)
+               return getattr(object.__getattribute__(self, '_file'), attr)
 
        def close(self):
                """Closes the temporary file, copies permissions (if possible),
                and performs the atomic replacement via os.rename().  If the abort()
                method has been called, then the temp file is closed and removed."""
-               if not self.closed:
+               f = object.__getattribute__(self, '_file')
+               real_name = object.__getattribute__(self, '_real_name')
+               if not f.closed:
                        try:
-                               super(atomic_ofstream, self).close()
-                               if not self._aborted:
+                               f.close()
+                               if not object.__getattribute__(self, '_aborted'):
                                        try:
-                                               apply_stat_permissions(self.name, os.stat(self._real_name))
+                                               apply_stat_permissions(f.name, os.stat(real_name))
                                        except OperationNotPermitted:
                                                pass
                                        except FileNotFound:
@@ -929,12 +1020,12 @@ class atomic_ofstream(file):
                                                        pass
                                                else:
                                                        raise
-                                       os.rename(self.name, self._real_name)
+                                       os.rename(f.name, real_name)
                        finally:
                                # Make sure we cleanup the temp file
                                # even if an exception is raised.
                                try:
-                                       os.unlink(self.name)
+                                       os.unlink(f.name)
                                except OSError, oe:
                                        pass
 
@@ -942,19 +1033,20 @@ class atomic_ofstream(file):
                """If an error occurs while writing the file, the user should
                call this method in order to leave the target file unchanged.
                This will call close() automatically."""
-               if not self._aborted:
-                       self._aborted = True
+               if not object.__getattribute__(self, '_aborted'):
+                       object.__setattr__(self, '_aborted', True)
                        self.close()
 
        def __del__(self):
                """If the user does not explicitely call close(), it is
                assumed that an error has occurred, so we abort()."""
-               if not self.closed:
+               f = object.__getattribute__(self, '_file')
+               if not f.closed:
                        self.abort()
                # ensure destructor from the base class is called
-               base_destructor = getattr(super(atomic_ofstream, self), '__del__', None)
+               base_destructor = getattr(ObjectProxy, '__del__', None)
                if base_destructor is not None:
-                       base_destructor()
+                       base_destructor(self)
 
 def write_atomic(file_path, content):
        f = None
@@ -1002,65 +1094,6 @@ def ensure_dirs(dir_path, *args, **kwargs):
        perms_modified = apply_permissions(dir_path, *args, **kwargs)
        return created_dir or perms_modified
 
-class ObjectProxy(object):
-
-       """
-       Object that acts as a proxy to another object, forwarding
-       attribute accesses and method calls. This can be useful
-       for implementing lazy initialization.
-       """
-
-       def _get_target(self):
-               raise NotImplementedError(self)
-
-       def __getattribute__(self, attr):
-               result = object.__getattribute__(self, '_get_target')()
-               return getattr(result, attr)
-
-       def __setattr__(self, attr, value):
-               result = object.__getattribute__(self, '_get_target')()
-               setattr(result, attr, value)
-
-       def __call__(self, *args, **kwargs):
-               result = object.__getattribute__(self, '_get_target')()
-               return result(*args, **kwargs)
-
-       def __setitem__(self, key, value):
-               object.__getattribute__(self, '_get_target')()[key] = value
-
-       def __getitem__(self, key):
-               return object.__getattribute__(self, '_get_target')()[key]
-
-       def __delitem__(self, key):
-               del object.__getattribute__(self, '_get_target')()[key]
-
-       def __contains__(self, key):
-               return key in object.__getattribute__(self, '_get_target')()
-
-       def __iter__(self):
-               return iter(object.__getattribute__(self, '_get_target')())
-
-       def __len__(self):
-               return len(object.__getattribute__(self, '_get_target')())
-
-       def __repr__(self):
-               return repr(object.__getattribute__(self, '_get_target')())
-
-       def __str__(self):
-               return str(object.__getattribute__(self, '_get_target')())
-
-       def __hash__(self):
-               return hash(object.__getattribute__(self, '_get_target')())
-
-       def __eq__(self, other):
-               return object.__getattribute__(self, '_get_target')() == other
-
-       def __ne__(self, other):
-               return object.__getattribute__(self, '_get_target')() != other
-
-       def __nonzero__(self):
-               return bool(object.__getattribute__(self, '_get_target')())
-
 class LazyItemsDict(dict):
        """A mapping object that behaves like a standard dict except that it allows
        for lazy initialization of values via callable objects.  Lazy items can be