# config.py -- Portage Config
# Copyright 2007 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$

import os

class LoaderError(Exception):
	
	def __init__(self, resource, error_msg):
		"""
		@param resource: Resource that failed to load (file/sql/etc)
		@type resource: String
		@param error_msg: Error from underlying Loader system
		@type error_msg: String
		"""

		self.resource = resource
		self.error_msg = error_msg
	
	def __str__(self):
		return "Failed while loading resource: %s, error was: %s" % (
			self.resource, self.error_msg)


def RecursiveFileLoader(filename):
	"""
	If filename is of type file, return a generate that yields filename
	else if filename is of type directory, return a generator that fields
	files in that directory.
	
	Ignore files beginning with . or ending in ~.
	Prune CVS directories.

	@param filename: name of a file/directory to traverse
	@rtype: list
	@returns: List of files to process
	"""
	if not os.path.exists(filename):
		return
	elif os.path.isdir(filename):
		for root, dirs, files in os.walk(filename):
			if 'CVS' in dirs:
				dirs.remove('CVS')
			files = [f for f in files if not f.startswith('.') and not f.endswith('~')]
			for f in files:
				yield os.path.join(root, f)
	else:
		yield filename


class DataLoader(object):

	def __init__(self, validator):
		f = validator
		if f is None:
			# if they pass in no validator, just make a fake one
			# that always returns true
			def validate(key):
				return True
			f = validate
		self._validate = f

	def load(self):
		"""
		Function to do the actual work of a Loader
		"""
		raise NotImplementedError("Please override in a subclass")

class EnvLoader(DataLoader):
	""" Class to access data in the environment """
	def __init__(self, validator):
		DataLoader.__init__(self, validator)

	def load(self):
		return os.environ

class TestTextLoader(DataLoader):
	""" You give it some data, it 'loads' it for you, no filesystem access
	"""
	def __init__(self, validator):
		DataLoader.__init__(self, validator)
		self.data = {}
		self.errors = {}

	def setData(self, text):
		"""Explicitly set the data field
		Args:
			text - a dict of data typical of Loaders
		Returns:
			None
		"""
		if isinstance(text, dict):
			self.data = text
		else:
			raise ValueError("setData requires a dict argument")

	def setErrors(self, errors):
		self.errors = errors
	
	def load(self):
		return (self.data, self.errors)


class FileLoader(DataLoader):
	""" Class to access data in files """

	def __init__(self, filename, validator):
		"""
			Args:
				filename : Name of file or directory to open
				validator : class with validate() method to validate data.
		"""
		DataLoader.__init__(self, validator)
		self.fname = filename

	def load(self):
		"""
		Return the {source: {key: value}} pairs from a file
		Return the {source: [list of errors] from a load

		@param recursive: If set and self.fname is a directory; 
			load all files in self.fname
		@type: Boolean
		@rtype: tuple
		@returns:
		Returns (data,errors), both may be empty dicts or populated.
		"""
		data = {}
		errors = {}
		# I tried to save a nasty lookup on lineparser by doing the lookup
		# once, which may be expensive due to digging in child classes.
		func = self.lineParser
		for fn in RecursiveFileLoader(self.fname):
			f = open(fn, 'rb')
			for line_num, line in enumerate(f):
				func(line, line_num, data, errors)
		return (data, errors)

	def lineParser(self, line, line_num, data, errors):
		""" This function parses 1 line at a time
			Args:
				line: a string representing 1 line of a file
				line_num: an integer representing what line we are processing
				data: a dict that contains the data we have extracted from the file
				      already
				errors: a dict representing parse errors.
			Returns:
				Nothing (None).  Writes to data and errors
		"""
		raise NotImplementedError("Please over-ride this in a child class")

class ItemFileLoader(FileLoader):
	"""
	Class to load data from a file full of items one per line
	
	>>> item1
	>>> item2
	>>> item3
	>>> item1
	
	becomes { 'item1':None, 'item2':None, 'item3':None }
	Note that due to the data store being a dict, duplicates
	are removed.
	"""

	def __init__(self, filename, validator):
		FileLoader.__init__(self, filename, validator)
	
	def lineParser(self, line, line_num, data, errors):
		line = line.strip()
		if line.startswith('#'): # Skip commented lines
			return
		if not len(line): # skip empty lines
			return
		split = line.split()
		if not len(split):
			errors.setdefault(self.fname, []).append(
				"Malformed data at line: %s, data: %s"
				% (line_num + 1, line))
			return
		key = split[0]
		if not self._validate(key):
			errors.setdefault(self.fname, []).append(
				"Validation failed at line: %s, data %s"
				% (line_num + 1, key))
			return
		data[key] = None

class KeyListFileLoader(FileLoader):
	"""
	Class to load data from a file full of key [list] tuples
	
	>>>>key foo1 foo2 foo3
	becomes
	{'key':['foo1','foo2','foo3']}
	"""

	def __init__(self, filename, validator=None, valuevalidator=None):
		FileLoader.__init__(self, filename, validator)

		f = valuevalidator
		if f is None:
			# if they pass in no validator, just make a fake one
			# that always returns true
			def validate(key):
				return True
			f = validate
		self._valueValidate = f

	def lineParser(self, line, line_num, data, errors):
		line = line.strip()
		if line.startswith('#'): # Skip commented lines
			return
		if not len(line): # skip empty lines
			return
		split = line.split()
		if len(split) < 1:
			errors.setdefault(self.fname, []).append(
				"Malformed data at line: %s, data: %s"
				% (line_num + 1, line))
			return
		key = split[0]
		value = split[1:]
		if not self._validate(key):
			errors.setdefault(self.fname, []).append(
				"Key validation failed at line: %s, data %s"
				% (line_num + 1, key))
			return
		if not self._valueValidate(value):
			errors.setdefault(self.fname, []).append(
				"Value validation failed at line: %s, data %s"
				% (line_num + 1, value))
			return
		if key in data:
			data[key].append(value)
		else:
			data[key] = value


class KeyValuePairFileLoader(FileLoader):
	"""
	Class to load data from a file full of key=value pairs
	
	>>>>key=value
	>>>>foo=bar
	becomes:
	{'key':'value',
	 'foo':'bar'}
	"""

	def __init__(self, filename, validator, valuevalidator=None):
		FileLoader.__init__(self, filename, validator)

		f = valuevalidator
		if f is None:
			# if they pass in no validator, just make a fake one
			# that always returns true
			def validate(key):
				return True
			f = validate
		self._valueValidate = f


	def lineParser(self, line, line_num, data, errors):
		line = line.strip()
		if line.startswith('#'): # skip commented lines
			return
		if not len(line): # skip empty lines
			return
		split = line.split('=')
		if len(split) < 2:
			errors.setdefault(self.fname, []).append(
				"Malformed data at line: %s, data %s"
				% (line_num + 1, line))
			return
		key = split[0]
		value = split[1:]
		if not key:
			errors.setdefault(self.fname, []).append(
				"Malformed key at line: %s, key %s"
				% (line_num + 1, key))
			return
		if not self._validate(key):
			errors.setdefault(self.fname, []).append(
				"Key validation failed at line: %s, data %s"
				% (line_num + 1, key))
			return
		if not self._valueValidate(value):
			errors.setdefault(self.fname, []).append(
				"Value validation failed at line: %s, data %s"
				% (line_num + 1, value))
			return
		if key in data:
			data[key].append(value)
		else:
			data[key] = value
