--- pym/portage/_sets/__init__.py | 29 ++----------------- pym/portage/repository/config.py | 38 ++----------------------- pym/portage/util/_desktop_entry.py | 20 ++----------- pym/portage/util/configparser.py | 57 +++++++++++++++++++++++++++++++++++++- 4 files changed, 64 insertions(+), 80 deletions(-)
diff --git a/pym/portage/_sets/__init__.py b/pym/portage/_sets/__init__.py index ec42f7c..6d69bda 100644 --- a/pym/portage/_sets/__init__.py +++ b/pym/portage/_sets/__init__.py @@ -22,7 +22,7 @@ from portage.exception import PackageSetNotFound from portage.localization import _ from portage.util import writemsg_level from portage.util.configparser import (SafeConfigParser, - NoOptionError, ParsingError) + NoOptionError, ParsingError, read_configs) SETPREFIX = "@" @@ -50,32 +50,7 @@ class SetConfig(object): }) if _ENABLE_SET_CONFIG: - # use read_file/readfp in order to control decoding of unicode - try: - # Python >=3.2 - read_file = self._parser.read_file - except AttributeError: - read_file = self._parser.readfp - - for p in paths: - f = None - try: - f = io.open(_unicode_encode(p, - encoding=_encodings['fs'], errors='strict'), - mode='r', encoding=_encodings['repo.content'], - errors='replace') - except EnvironmentError: - pass - else: - try: - read_file(f) - except ParsingError as e: - writemsg_level(_unicode_decode( - _("!!! Error while reading sets config file: %s\n") - ) % e, level=logging.ERROR, noiselevel=-1) - finally: - if f is not None: - f.close() + read_configs(self._parser, paths) else: self._create_default_config() diff --git a/pym/portage/repository/config.py b/pym/portage/repository/config.py index 9039886..a23f4bd 100644 --- a/pym/portage/repository/config.py +++ b/pym/portage/repository/config.py @@ -17,7 +17,8 @@ from portage.eapi import eapi_allows_directories_on_profile_level_and_repository from portage.env.loaders import KeyValuePairFileLoader from portage.util import (normalize_path, read_corresponding_eapi_file, shlex_split, stack_lists, writemsg, writemsg_level, _recursive_file_list) -from portage.util.configparser import SafeConfigParser, ConfigParserError +from portage.util.configparser import (SafeConfigParser, ConfigParserError, + read_configs) from portage.util._path import isdir_raise_eaccess from portage.util.path import first_existing from portage.localization import _ @@ -542,15 +543,6 @@ class RepoConfigLoader(object): """Parse files in paths to load config""" parser = SafeConfigParser(defaults=default_opts) - # use read_file/readfp in order to control decoding of unicode - try: - # Python >=3.2 - read_file = parser.read_file - source_kwarg = 'source' - except AttributeError: - read_file = parser.readfp - source_kwarg = 'filename' - recursive_paths = [] for p in paths: if isinstance(p, basestring): @@ -558,31 +550,7 @@ class RepoConfigLoader(object): else: recursive_paths.append(p) - for p in recursive_paths: - if isinstance(p, basestring): - f = None - try: - f = io.open(_unicode_encode(p, - encoding=_encodings['fs'], errors='strict'), - mode='r', encoding=_encodings['repo.content'], - errors='replace') - except EnvironmentError: - pass - else: - # The 'source' keyword argument is needed since otherwise - # ConfigParser in Python <3.3.3 may throw a TypeError - # because it assumes that f.name is a native string rather - # than binary when constructing error messages. - kwargs = {source_kwarg: p} - read_file(f, **portage._native_kwargs(kwargs)) - finally: - if f is not None: - f.close() - elif isinstance(p, io.StringIO): - kwargs = {source_kwarg: "<io.StringIO>"} - read_file(p, **portage._native_kwargs(kwargs)) - else: - raise TypeError("Unsupported type %r of element %r of 'paths' argument" % (type(p), p)) + read_configs(parser, recursive_paths) prepos['DEFAULT'] = RepoConfig("DEFAULT", parser.defaults(), local_config=local_config) diff --git a/pym/portage/util/_desktop_entry.py b/pym/portage/util/_desktop_entry.py index 95a015e..4fe4194 100644 --- a/pym/portage/util/_desktop_entry.py +++ b/pym/portage/util/_desktop_entry.py @@ -9,7 +9,8 @@ import sys import portage from portage import _encodings, _unicode_encode, _unicode_decode from portage.util import writemsg -from portage.util.configparser import ConfigParserError, RawConfigParser +from portage.util.configparser import (ConfigParserError, RawConfigParser, + read_configs) def parse_desktop_entry(path): @@ -20,22 +21,7 @@ def parse_desktop_entry(path): """ parser = RawConfigParser() - # use read_file/readfp in order to control decoding of unicode - try: - # Python >=3.2 - read_file = parser.read_file - except AttributeError: - read_file = parser.readfp - - with io.open(_unicode_encode(path, - encoding=_encodings['fs'], errors='strict'), - mode='r', encoding=_encodings['repo.content'], - errors='replace') as f: - content = f.read() - - # In Python 3.2, read_file does not support bytes in file names - # (see bug #429544), so use StringIO to hide the file name. - read_file(io.StringIO(content)) + read_configs(parser, [path]) return parser diff --git a/pym/portage/util/configparser.py b/pym/portage/util/configparser.py index d305052..fb1a351 100644 --- a/pym/portage/util/configparser.py +++ b/pym/portage/util/configparser.py @@ -2,12 +2,13 @@ # Distributed under the terms of the GNU General Public License v2 __all__ = ['ConfigParserError', 'NoOptionError', 'ParsingError', - 'RawConfigParser', 'SafeConfigParser'] + 'RawConfigParser', 'SafeConfigParser', 'read_configs'] # the following scary compatibility thing provides two classes: # - SafeConfigParser that provides safe interpolation for values, # - RawConfigParser that provides no interpolation for values. +import io import sys try: @@ -20,3 +21,57 @@ try: except ImportError: from ConfigParser import (Error as ConfigParserError, NoOptionError, ParsingError, RawConfigParser, SafeConfigParser) + +from portage import _encodings +from portage import _native_kwargs +from portage import _unicode_encode + + +if sys.hexversion >= 0x3000000: + # pylint: disable=W0622 + basestring = str + + +def read_configs(parser, paths): + """ + Read configuration files from given paths into the specified + ConfigParser, handling path encoding portably. + @param parser: target *ConfigParser instance + @type parser: SafeConfigParser or RawConfigParser + @param paths: list of paths to read + @type paths: iterable + """ + # use read_file/readfp in order to control decoding of unicode + try: + # Python >=3.2 + read_file = parser.read_file + source_kwarg = 'source' + except AttributeError: + read_file = parser.readfp + source_kwarg = 'filename' + + for p in paths: + if isinstance(p, basestring): + f = None + try: + f = io.open(_unicode_encode(p, + encoding=_encodings['fs'], errors='strict'), + mode='r', encoding=_encodings['repo.content'], + errors='replace') + except EnvironmentError: + pass + else: + # The 'source' keyword argument is needed since otherwise + # ConfigParser in Python <3.3.3 may throw a TypeError + # because it assumes that f.name is a native string rather + # than binary when constructing error messages. + kwargs = {source_kwarg: p} + read_file(f, **_native_kwargs(kwargs)) + finally: + if f is not None: + f.close() + elif isinstance(p, io.StringIO): + kwargs = {source_kwarg: "<io.StringIO>"} + read_file(p, **_native_kwargs(kwargs)) + else: + raise TypeError("Unsupported type %r of element %r of 'paths' argument" % (type(p), p)) -- 2.8.3