public inbox for gentoo-portage-dev@lists.gentoo.org
 help / color / mirror / Atom feed
From: "Michał Górny" <mgorny@gentoo.org>
To: gentoo-portage-dev@lists.gentoo.org
Cc: "Michał Górny" <mgorny@gentoo.org>
Subject: [gentoo-portage-dev] [PATCH 2/2] portage.util.configparser: Commonize portable config file reading routine
Date: Sun, 22 May 2016 10:41:48 +0200	[thread overview]
Message-ID: <20160522084148.2658-2-mgorny@gentoo.org> (raw)
In-Reply-To: <20160522084148.2658-1-mgorny@gentoo.org>

---
 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



  reply	other threads:[~2016-05-22  8:42 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-22  8:41 [gentoo-portage-dev] [PATCH 1/2] portage.util.configparser: Provide common code to handle cp imports Michał Górny
2016-05-22  8:41 ` Michał Górny [this message]
2016-05-22 18:04   ` [gentoo-portage-dev] [PATCH 2/2] portage.util.configparser: Commonize portable config file reading routine Zac Medico
2016-05-24  6:28     ` Michał Górny

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160522084148.2658-2-mgorny@gentoo.org \
    --to=mgorny@gentoo.org \
    --cc=gentoo-portage-dev@lists.gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox