From: Zac Medico Date: Sat, 18 Feb 2012 02:01:27 +0000 (-0800) Subject: PreservedLibsRegistry: add JSON read/write X-Git-Tag: v2.2.0_alpha87~3 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=4c8d1060304a4e793c5d813a1d925e7cf1fcccbd;p=portage.git PreservedLibsRegistry: add JSON read/write Support serialization as JSON instead of pickle, so that /var/lib/portage/preserved_libs_registry is human readable/writable, for those rare cases where it may be useful. Currently, pickle is still used for writes. The plan is to migrate to JSON after JSON read has been supported for some time. --- diff --git a/pym/portage/util/_dyn_libs/PreservedLibsRegistry.py b/pym/portage/util/_dyn_libs/PreservedLibsRegistry.py index 510c390af..405a23a88 100644 --- a/pym/portage/util/_dyn_libs/PreservedLibsRegistry.py +++ b/pym/portage/util/_dyn_libs/PreservedLibsRegistry.py @@ -1,7 +1,8 @@ -# Copyright 1998-2011 Gentoo Foundation +# Copyright 1998-2012 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 import errno +import json import logging import sys @@ -27,6 +28,19 @@ if sys.hexversion >= 0x3000000: class PreservedLibsRegistry(object): """ This class handles the tracking of preserved library objects """ + + # Enable this after JSON read has been supported for some time. + _json_write = False + + _json_write_opts = { + "ensure_ascii": False, + "indent": "\t", + "sort_keys": True + } + if sys.hexversion < 0x3020000: + # indent only supports int number of spaces + _json_write_opts["indent"] = 4 + def __init__(self, root, filename): """ @param root: root used to check existence of paths in pruneNonExisting @@ -56,17 +70,11 @@ class PreservedLibsRegistry(object): """ Reload the registry data from file """ self._data = None f = None + content = None try: f = open(_unicode_encode(self._filename, encoding=_encodings['fs'], errors='strict'), 'rb') - if os.fstat(f.fileno()).st_size == 0: - # ignore empty lock file - pass - else: - self._data = pickle.load(f) - except (AttributeError, EOFError, ValueError, pickle.UnpicklingError) as e: - writemsg_level(_("!!! Error loading '%s': %s\n") % \ - (self._filename, e), level=logging.ERROR, noiselevel=-1) + content = f.read() except EnvironmentError as e: if not hasattr(e, 'errno'): raise @@ -79,8 +87,33 @@ class PreservedLibsRegistry(object): finally: if f is not None: f.close() + + # content is empty if it's an empty lock file + if content: + try: + self._data = pickle.loads(content) + except SystemExit: + raise + except Exception as e: + try: + self._data = json.loads(_unicode_decode(content, + encoding=_encodings['repo.content'], errors='strict')) + except SystemExit: + raise + except Exception: + writemsg_level(_("!!! Error loading '%s': %s\n") % + (self._filename, e), level=logging.ERROR, + noiselevel=-1) + if self._data is None: self._data = {} + else: + for k, v in self._data.items(): + if isinstance(v, (list, tuple)) and len(v) == 3 and \ + isinstance(v[2], set): + # convert set to list, for write with JSONEncoder + self._data[k] = (v[0], v[1], list(v[2])) + self._data_orig = self._data.copy() self.pruneNonExisting() @@ -97,7 +130,12 @@ class PreservedLibsRegistry(object): return try: f = atomic_ofstream(self._filename, 'wb') - pickle.dump(self._data, f, protocol=2) + if self._json_write: + f.write(_unicode_encode( + json.dumps(self._data, **self._json_write_opts), + encoding=_encodings['repo.content'], errors='strict')) + else: + pickle.dump(self._data, f, protocol=2) f.close() except EnvironmentError as e: if e.errno != PermissionDenied.errno: @@ -138,6 +176,9 @@ class PreservedLibsRegistry(object): self._normalize_counter(self._data[cps][1]) == counter: del self._data[cps] elif len(paths) > 0: + if isinstance(paths, set): + # convert set to list, for write with JSONEncoder + paths = list(paths) self._data[cps] = (cpv, counter, paths) def unregister(self, cpv, slot, counter):