# Copyright 2016 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

__all__ = ['ConfigParserError', 'NoOptionError', 'ParsingError',
	'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:
	from configparser import (Error as ConfigParserError,
		NoOptionError, ParsingError, RawConfigParser)
	if sys.hexversion >= 0x3020000:
		from configparser import ConfigParser as SafeConfigParser
	else:
		from configparser import SafeConfigParser
except ImportError:
	from ConfigParser import (Error as ConfigParserError,
		NoOptionError, ParsingError, RawConfigParser, SafeConfigParser)

from portage import _encodings
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, **kwargs)
			finally:
				if f is not None:
					f.close()
		elif isinstance(p, io.StringIO):
			kwargs = {source_kwarg: "<io.StringIO>"}
			read_file(p, **kwargs)
		else:
			raise TypeError("Unsupported type %r of element %r of 'paths' argument" % (type(p), p))
