public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/R_overlay:master commit in: /, roverlay/depres/simpledeprule/, roverlay/depres/, config/, roverlay/recipe/
@ 2012-07-11 18:43 André Erdmann
  0 siblings, 0 replies; only message in thread
From: André Erdmann @ 2012-07-11 18:43 UTC (permalink / raw
  To: gentoo-commits

commit:     bb8c8f16dd67c14f31af69e70c7c99baebbb80d9
Author:     André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Wed Jul 11 18:36:32 2012 +0000
Commit:     André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Wed Jul 11 18:36:32 2012 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=bb8c8f16

dependency resolution

* simple dep rules are now a sub module of depres
* split rule creation from rule file reading, this allows
  to create rules for strings (not only for files)
* fixed some issues like 'DependencyResolver does not run
  without an error queue'
* added the possibility to read dependency rules from a directory
  this will scan the dir non-recursively and read all files found

	modified:   R-overlay.conf
	modified:   config/R-overlay.conf
	modified:   roverlay/depres/channels.py
	modified:   roverlay/depres/depresolver.py
	modified:   roverlay/depres/deprule.py
	deleted:    roverlay/depres/simpledeprule.py
	new file:   roverlay/depres/simpledeprule/__init__.py
	renamed:    roverlay/depres/abstractsimpledeprule.py -> roverlay/depres/simpledeprule/abstractrules.py
	new file:   roverlay/depres/simpledeprule/pool.py
	new file:   roverlay/depres/simpledeprule/reader.py
	new file:   roverlay/depres/simpledeprule/rulemaker.py
	new file:   roverlay/depres/simpledeprule/rules.py
	modified:   roverlay/recipe/easyresolver.py

---
 R-overlay.conf                                     |   11 +-
 config/R-overlay.conf                              |    4 +-
 roverlay/depres/channels.py                        |   26 ++-
 roverlay/depres/depresolver.py                     |   31 ++-
 roverlay/depres/deprule.py                         |    2 +-
 roverlay/depres/simpledeprule.py                   |  301 --------------------
 roverlay/depres/simpledeprule/__init__.py          |    1 +
 .../abstractrules.py}                              |   29 ++-
 roverlay/depres/simpledeprule/pool.py              |   79 +++++
 roverlay/depres/simpledeprule/reader.py            |  112 ++++++++
 roverlay/depres/simpledeprule/rulemaker.py         |  136 +++++++++
 roverlay/depres/simpledeprule/rules.py             |   89 ++++++
 roverlay/recipe/easyresolver.py                    |    9 +-
 13 files changed, 484 insertions(+), 346 deletions(-)

diff --git a/R-overlay.conf b/R-overlay.conf
index 7e94dbc..e37c220 100644
--- a/R-overlay.conf
+++ b/R-overlay.conf
@@ -19,11 +19,12 @@ LOG_FILE_UNRESOLVABLE = log/dep_unresolvable.log
 
 # SIMPLE_RULES_FILE lists the rule files for dependency resolution
 #  SIMPLE_RULES_FILE ::= "<file>[ <file>]"
-SIMPLE_RULES_FILE = "
-simple-deprules.d/R
-simple-deprules.d/selfdeps
-simple-deprules.d/other
-"
+#SIMPLE_RULES_FILE = "
+#simple-deprules.d/R
+#simple-deprules.d/selfdeps
+#simple-deprules.d/other
+#"
+SIMPLE_RULES_FILE = "simple-deprules.d"
 
 OVERLAY_NAME     = ROverlay
 OVERLAY_DIR      = overlay-root

diff --git a/config/R-overlay.conf b/config/R-overlay.conf
index 5276520..8c0f985 100644
--- a/config/R-overlay.conf
+++ b/config/R-overlay.conf
@@ -165,13 +165,13 @@
 #REPO_CONFIG = "repo.list"
 
 # SIMPLE_RULES_FILE
-#  list of (simple) dependency rule files
+#  list of (simple) dependency rule files or dirs
 #   Please see the rule example file for file format.
+#   Directories will be non-recursively scanned for files.
 #  * defaults to <unset>, which effectively disables dependency resolution
 #     since no other dependency resolution methods are available.
 #     This gives poor results!
 #  * alias: SIMPLE_RULES_FILES
-#  *** TODO-note: accept directories as value ***
 #SIMPLE_RULES_FILE = "simple-deprules.d/R"
 
 # == logging ==

diff --git a/roverlay/depres/channels.py b/roverlay/depres/channels.py
index 56491f4..72f2b87 100644
--- a/roverlay/depres/channels.py
+++ b/roverlay/depres/channels.py
@@ -155,7 +155,9 @@ class EbuildJobChannel ( DependencyResolverChannel ):
 		raise Exception ( "cannot do that" )
 	# --- end of collect_dependencies (...) ---
 
-	def satisfy_request ( self, close_if_unresolvable=True ):
+	def satisfy_request ( self,
+		close_if_unresolvable=True, preserve_order=False
+	):
 		"""Tells to the dependency resolver to run.
 		It blocks until this channel is done, which means that either all
 		deps are resolved or one is unresolvable.
@@ -163,6 +165,10 @@ class EbuildJobChannel ( DependencyResolverChannel ):
 		arguments:
 		* close_if_unresolvable -- close the channel if one dep is unresolvable
 		                           this seems reasonable and defaults to True
+		* preserve_order        -- if set and True:
+		                           return resolved deps as tuple, not as
+		                           frozenset
+		                           Note that this doesn't filter out duplicates!
 
 		Returns the list of resolved dependencies if all could be resolved,
 		else None.
@@ -171,19 +177,24 @@ class EbuildJobChannel ( DependencyResolverChannel ):
 		# using a set allows easy difference() operations between
 		# DEPEND/RDEPEND/.. later, seewave requires sci-libs/fftw
 		# in both DEPEND and RDEPEND for example
-		dep_collected = set()
-		satisfiable   = self.err_queue.empty()
+		dep_collected = list()
+		satisfiable   = True \
+			if self.err_queue is None \
+			else self.err_queue.empty()
 
 
 		def handle_queue_item ( dep_env ):
 			self._depdone += 1
 			if dep_env is None:
 				# could used to unblock the queue
-				return self.err_queue.empty()
+				if self.err_queue is None:
+					return False
+				else:
+					return self.err_queue.empty()
 			elif dep_env.is_resolved():
 				### and dep_env in self.dep_env_list
 				# successfully resolved
-				dep_collected.add ( dep_env.get_result() [1] )
+				dep_collected.append ( dep_env.get_result() [1] )
 				self._depres_queue.task_done()
 				return True
 			else:
@@ -211,7 +222,10 @@ class EbuildJobChannel ( DependencyResolverChannel ):
 
 		if satisfiable:
 			self._collected_deps = frozenset ( dep_collected )
-			return self._collected_deps
+			if preserve_order:
+				return tuple ( dep_collected )
+			else:
+				return self._collected_deps
 		else:
 			if close_if_unresolvable: self.close()
 			return None

diff --git a/roverlay/depres/depresolver.py b/roverlay/depres/depresolver.py
index e1fc792..d0383dd 100644
--- a/roverlay/depres/depresolver.py
+++ b/roverlay/depres/depresolver.py
@@ -13,7 +13,7 @@ except ImportError:
 
 
 from roverlay        import config
-from roverlay.depres import simpledeprule, communication, events
+from roverlay.depres import communication, events
 
 #from roverlay.depres.depenv import DepEnv (implicit)
 
@@ -29,7 +29,7 @@ class DependencyResolver ( object ):
 	"""Main object for dependency resolution."""
 
 
-	NUMTHREADS = config.get ( "DEPRES.jobcount", 3 )
+	NUMTHREADS = config.get ( "DEPRES.jobcount", 0 )
 
 	def __init__ ( self ):
 		"""Initializes a DependencyResolver."""
@@ -51,6 +51,8 @@ class DependencyResolver ( object ):
 		# the dep res worker threads
 		self._threads    = None
 
+		self.err_queue = None
+
 
 		# the list of registered listener modules
 		self.listeners = list ()
@@ -88,6 +90,7 @@ class DependencyResolver ( object ):
 
 	def set_exception_queue ( self, equeue ):
 		self.err_queue = equeue
+	# --- end of set_exception_queue (...) ---
 
 	def _sort ( self ):
 		"""Sorts the rule pools of this resolver."""
@@ -96,6 +99,11 @@ class DependencyResolver ( object ):
 		self.static_rule_pools.sort ( key=poolsort )
 	# --- end of sort (...) ---
 
+	def _reset_unresolvable ( self ):
+		if USING_DEPRES_CACHE:
+			self._dep_unresolvable.clear()
+	# --- end of _reset_unresolvable (...) ---
+
 	def add_rulepool ( self, rulepool, pool_type=None ):
 		"""Adds a (static) rule pool to this resolver.
 		Calls self.sort() afterwards.
@@ -105,8 +113,7 @@ class DependencyResolver ( object ):
 		* pool_type -- ignored.
 		"""
 		self.static_rule_pools.append ( rulepool )
-		if USING_DEPRES_CACHE:
-			self._dep_unresolvable.clear()
+		self._reset_unresolvable()
 		self._sort()
 	# --- end of add_rulepool (...) ---
 
@@ -320,7 +327,7 @@ class DependencyResolver ( object ):
 
 	def _thread_run_main ( self ):
 		"""Tells the resolver to run."""
-		jobcount = DependencyResolver.NUMTHREADS
+		jobcount = self.__class__.NUMTHREADS
 
 		try:
 			if jobcount < 1:
@@ -353,7 +360,6 @@ class DependencyResolver ( object ):
 				del self._threads
 				self._threads = None
 
-
 			# iterate over _depqueue_failed and report unresolved
 			## todo can thread this
 			while not self._depqueue_failed.empty():
@@ -377,14 +383,13 @@ class DependencyResolver ( object ):
 					# channel has been closed before calling put, ignore this
 					pass
 
-				if not self.err_queue.empty():
+				if self.err_queue and not self.err_queue.empty():
 					self.unblock_channels()
 
 		except ( Exception, KeyboardInterrupt ) as e:
-
 			self.unblock_channels()
 
-			if jobcount > 0 and hasattr ( self, 'err_queue' ):
+			if jobcount > 0 and self.err_queue:
 				self.err_queue.put_nowait ( id ( self ), e )
 				return
 			else:
@@ -402,8 +407,9 @@ class DependencyResolver ( object ):
 		returns: None (implicit)
 		"""
 		try:
-			while self.err_queue.empty() and not self._depqueue.empty():
-
+			while ( not self.err_queue or self.err_queue.empty()  ) \
+				and not self._depqueue.empty() \
+			:
 				try:
 					to_resolve = self._depqueue.get_nowait()
 				except queue.Empty:
@@ -449,7 +455,6 @@ class DependencyResolver ( object ):
 								break
 
 
-
 					if is_resolved == 2:
 						dep_env.set_resolved ( resolved, append=False )
 						self._report_event ( 'RESOLVED', dep_env )
@@ -480,7 +485,7 @@ class DependencyResolver ( object ):
 			# --- end while
 
 		except ( Exception, KeyboardInterrupt ) as e:
-			if jobcount > 0 and hasattr ( self, 'err_queue' ):
+			if self.__class__.NUMTHREADS > 0 and self.err_queue:
 				self.err_queue.put_nowait ( id ( self ), e )
 				return
 			else:

diff --git a/roverlay/depres/deprule.py b/roverlay/depres/deprule.py
index 72e706d..27e0f47 100644
--- a/roverlay/depres/deprule.py
+++ b/roverlay/depres/deprule.py
@@ -34,7 +34,7 @@ class DependencyRulePool ( object ):
 		* name -- name of this rule pool
 		* priority -- priority of this pool (lower is better)
 		"""
-		self.rules       = list ()
+		self.rules       = list()
 		self.name        = name
 		self.priority    = priority
 		# the "rule weight" is the sum of the rules' priorities

diff --git a/roverlay/depres/simpledeprule.py b/roverlay/depres/simpledeprule.py
deleted file mode 100644
index 04a47a6..0000000
--- a/roverlay/depres/simpledeprule.py
+++ /dev/null
@@ -1,301 +0,0 @@
-# R overlay -- simple dependency rules
-# Copyright 2006-2012 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-import re
-import logging
-
-from roverlay import config
-from roverlay.depres import deprule
-from roverlay.depres.abstractsimpledeprule import SimpleRule, FuzzySimpleRule
-
-TMP_LOGGER = logging.getLogger ('simpledeps')
-
-class SimpleIgnoreDependencyRule ( SimpleRule ):
-
-	RULE_PREFIX = '!'
-
-	def __init__ ( self, dep_str=None, priority=50, resolving_package=None ):
-		super ( SimpleIgnoreDependencyRule, self ) . __init__ (
-			dep_str=dep_str,
-			priority=priority,
-			resolving_package=None,
-			logger_name = 'IGNORE_DEPS',
-		)
-
-class SimpleDependencyRule ( SimpleRule ):
-
-	def __init__ ( self, resolving_package, dep_str=None, priority=70 ):
-		"""Initializes a SimpleDependencyRule. This is
-		a SimpleIgnoreDependencyRule extended by a portage package string.
-
-		arguments:
-		* resolving package --
-		* dep_str --
-		* priority --
-		"""
-		super ( SimpleDependencyRule, self ) . __init__ (
-			dep_str=dep_str,
-			priority=priority,
-			resolving_package=resolving_package,
-			logger_name=resolving_package
-		)
-
-	# --- end of __init__ (...) ---
-
-class SimpleFuzzyIgnoreDependencyRule ( FuzzySimpleRule ):
-
-	RULE_PREFIX = '%'
-
-	def __init__ ( self, dep_str=None, priority=51, resolving_package=None ):
-		super ( SimpleFuzzyIgnoreDependencyRule, self ) . __init__ (
-			dep_str=dep_str,
-			priority=priority,
-			resolving_package=None,
-			logger_name = 'FUZZY.IGNORE_DEPS',
-		)
-
-class SimpleFuzzyDependencyRule ( FuzzySimpleRule ):
-
-	RULE_PREFIX = '~'
-
-	def __init__ ( self, resolving_package, dep_str=None, priority=71 ):
-		super ( SimpleFuzzyDependencyRule, self ) . __init__ (
-			dep_str=dep_str,
-			priority=priority,
-			resolving_package=resolving_package,
-			logger_name = 'FUZZY.' + resolving_package,
-		)
-
-
-class SimpleDependencyRulePool ( deprule.DependencyRulePool ):
-
-	def __init__ ( self, name, priority=70, filepath=None ):
-		"""Initializes a SimpleDependencyRulePool, which is a DependencyRulePool
-		specialized in simple dependency rules;
-		it offers loading rules from files.
-
-		arguments:
-		* name     -- string identifier for this pool
-		* priority -- of this pool
-		* filepath -- if set and not None: load a rule file directly
-		"""
-		super ( SimpleDependencyRulePool, self ) . __init__ ( name, priority )
-
-		if not filepath is None:
-			self.load_rule_file ( filepath )
-
-	# --- end of __init__ (...) ---
-
-	def add ( self, rule ):
-		"""Adds a rule to this pool.
-		Its class has to be SimpleIgnoreDependencyRule or derived from it.
-
-		arguments:
-		* rule --
-		"""
-		if isinstance ( rule, SimpleRule ):
-			self.rules.append ( rule )
-		else:
-			raise Exception ( "bad usage (simple dependency rule expected)." )
-
-	# --- end of add (...) ---
-
-	def load_rule_file ( self, filepath ):
-		"""Loads a rule file and adds the read rules to this pool.
-
-		arguments:
-		* filepath -- file to read
-		"""
-		reader = SimpleDependencyRuleReader()
-
-		new_rules = reader.read_file ( filepath )
-		for rule in new_rules:
-			self.add ( rule )
-
-	# --- end of load_rule_file (...) ---
-
-	def export_rules ( self, fh ):
-		"""Exports all rules from this pool into the given file handle.
-
-		arguments:
-		* fh -- object that has a writelines ( list ) method
-
-		raises: IOError (fh)
-		"""
-		for rule in self.rules:
-			fh.write ( str ( rule ) )
-			fh.write ( '\n' )
-
-	# --- end of export_rules (...) ---
-
-
-class SimpleDependencyRuleReader ( object ):
-
-	one_line_separator = re.compile ( '\s+::\s+' )
-	multiline_start    = '{'
-	multiline_stop     = '}'
-	comment_chars      = "#;"
-
-	# todo: const/config?
-	package_ignore = SimpleIgnoreDependencyRule.RULE_PREFIX
-	fuzzy          = SimpleFuzzyDependencyRule.RULE_PREFIX
-	fuzzy_ignore   = SimpleFuzzyIgnoreDependencyRule.RULE_PREFIX
-
-	BREAK_PARSING  = frozenset (( '#! NOPARSE', '#! BREAK' ))
-
-
-	def __init__ ( self ):
-		""" A SimpleDependencyRuleReader reads such rules from a file."""
-		pass
-	# --- end of __init__  (...) ---
-
-	def read_file ( self, filepath ):
-		"""Reads a file that contains simple dependency rules
-		(SimpleIgnoreDependencyRules/SimpleDependencyRules).
-
-		arguments:
-		* filepath -- file to read
-		"""
-
-		# line number is used for logging
-		lineno = 0
-
-		try:
-			logging.debug ( "Reading simple dependency rule file %s." % filepath )
-			fh = open ( filepath, 'r' )
-
-			CLS = self.__class__
-
-			# the list of read rules
-			rules = list ()
-
-			# next rule is set when in a multi line rule (else None)
-			next_rule = None
-
-			for line in fh.readlines():
-				lineno += 1
-				line    = line.strip()
-
-				if not line:
-					# empty
-					pass
-
-				elif line in CLS.BREAK_PARSING:
-					# stop reading here
-					break
-
-				elif not next_rule is None:
-					# in a multiline rule
-
-					if line [0] == CLS.multiline_stop:
-						# end of a multiline rule,
-						#  add rule to rules and set next_rule to None
-						next_rule.done_reading()
-						rules.append ( next_rule )
-						next_rule = None
-					else:
-						# new resolved str
-						next_rule.add_resolved ( line )
-
-				elif line [0] in CLS.comment_chars:
-					# comment
-					#  it is intented that multi line rules cannot contain comments
-					pass
-
-				elif line [-1] == CLS.multiline_start:
-					# start of a multiline rule
-					portpkg = line [:-1].rstrip()
-
-					if portpkg == CLS.fuzzy_ignore:
-						next_rule = SimpleFuzzyIgnoreDependencyRule ( None )
-					elif portpkg == CLS.fuzzy:
-						next_rule = SimpleFuzzyDependencyRule ( portpkg[1:], None )
-					elif portpkg == CLS.package_ignore:
-						next_rule = SimpleIgnoreDependencyRule ( None, 60 )
-					else:
-						next_rule = SimpleDependencyRule ( portpkg, None, 70 )
-
-				else:
-					# single line rule, either selfdep,
-					#  e.g. '~zoo' -> fuzzy sci-R/zoo :: zoo
-					#  or normal rule 'dev-lang/R :: R'
-					# selfdeps are always single line statements (!)
-					rule_str = CLS.one_line_separator.split (line, 1)
-
-					new_rule   = None
-					rule_class = None
-					resolving  = None
-
-					first_char = rule_str [0][0] if len ( rule_str [0] ) else ''
-
-					if first_char == CLS.fuzzy:
-						rule_class = SimpleFuzzyDependencyRule
-						resolving  = rule_str [0] [1:]
-
-					elif rule_str [0] == CLS.fuzzy_ignore:
-						rule_class = SimpleFuzzyIgnoreDependencyRule
-						resolving  = None
-
-					elif rule_str [0] == CLS.package_ignore:
-						rule_class = SimpleIgnoreDependencyRule
-
-					else:
-						rule_class = SimpleDependencyRule
-						resolving  = rule_str [0]
-
-					if len ( rule_str ) == 2:
-						# normal rule
-						new_rule = rule_class (
-							resolving_package=resolving,
-							dep_str=rule_str [1]
-						)
-
-					elif resolving is not None:
-						# selfdep
-						dep_str = resolving
-						resolving = '/'.join ( (
-							config.get_or_fail ( 'OVERLAY.category' ),
-							resolving
-						) )
-						new_rule = rule_class (
-							resolving_package=resolving,
-							dep_str=dep_str
-						)
-
-					# else: error
-
-
-					if new_rule:
-						new_rule.done_reading()
-						rules.append ( new_rule )
-
-					else:
-						logging.error (
-							"In %s, line %i : cannot use this line." %
-								( filepath, lineno )
-						)
-				# ---
-
-			if fh: fh.close ()
-
-			if next_rule is not None:
-				logging.warning ( "Multi line rule does not end at EOF - ignored" )
-
-			logging.info (
-				"%s: read %i dependency rules (in %i lines)" %
-					( filepath, len ( rules ), lineno )
-			)
-
-			return rules
-
-		except IOError as ioerr:
-			if lineno:
-				logging.error (
-					"Failed to read file %s after %i lines." % ( filepath, lineno )
-				)
-			else:
-				logging.error ( "Could not read file %s." % filepath )
-			raise
-
-		# --- end of read_file (...) ---

diff --git a/roverlay/depres/simpledeprule/__init__.py b/roverlay/depres/simpledeprule/__init__.py
new file mode 100644
index 0000000..3cf31e2
--- /dev/null
+++ b/roverlay/depres/simpledeprule/__init__.py
@@ -0,0 +1 @@
+from roverlay.depres.simpledeprule.pool import SimpleDependencyRulePool

diff --git a/roverlay/depres/abstractsimpledeprule.py b/roverlay/depres/simpledeprule/abstractrules.py
similarity index 90%
rename from roverlay/depres/abstractsimpledeprule.py
rename to roverlay/depres/simpledeprule/abstractrules.py
index 811f88e..1f0ba28 100644
--- a/roverlay/depres/abstractsimpledeprule.py
+++ b/roverlay/depres/simpledeprule/abstractrules.py
@@ -10,7 +10,7 @@ class SimpleRule ( deprule.DependencyRule ):
 
 	def __init__ ( self,
 		dep_str=None, priority=50, resolving_package=None,
-		logger_name='simple_rule'
+		is_selfdep=False, logger_name='simple_rule'
 	):
 		"""Initializes a SimpleIgnoreDependencyRule.
 
@@ -23,6 +23,8 @@ class SimpleRule ( deprule.DependencyRule ):
 
 		self.logger = TMP_LOGGER.getChild ( logger_name )
 
+		self.is_selfdep = is_selfdep
+
 		self.resolving_package = resolving_package
 
 		self.prepare_lowercase_alias = True
@@ -51,9 +53,9 @@ class SimpleRule ( deprule.DependencyRule ):
 			if hasattr ( self, 'dep_alias_low' ):
 				if dep_str in self.dep_alias_low:
 					return True
-			else:
-				if dep_str in ( alias.lower() for alias in self.dep_alias ):
-					return True
+
+			elif dep_str in ( alias.lower() for alias in self.dep_alias ):
+				return True
 
 		return dep_str in self.dep_alias
 	# --- end of _find (...) ---
@@ -89,19 +91,21 @@ class SimpleRule ( deprule.DependencyRule ):
 		else:
 			resolving = self.resolving_package
 
-			cat = config.get ( 'OVERLAY.category', None )
+			if self.is_selfdep:
+				resolving = resolving.split ( '/', 1 ) [1]
 
-			if cat is not None:
-				resolving = resolving.replace ( cat + '/', '')
 
 		if hasattr ( self.__class__, 'RULE_PREFIX' ):
 			resolving = self.__class__.RULE_PREFIX + resolving
 
-		if len ( self.dep_alias ) == 0:
+		if self.is_selfdep:
+			yield resolving
+
+		elif len ( self.dep_alias ) == 0:
 			pass
 
 		elif len ( self.dep_alias ) == 1:
-			yield "%s :: %s\n" % ( resolving, iter ( self.dep_alias ).next() )
+			yield "%s :: %s" % ( resolving, iter ( self.dep_alias ).next() )
 
 		else:
 			yield resolving + ' {'
@@ -151,8 +155,11 @@ class FuzzySimpleRule ( SimpleRule ):
 								self.resolving_package, fuzzy ['version']
 							) )
 
-							if 'version_modifier' in fuzzy:
-								vmod = fuzzy ['version_modifier']
+							vmod = fuzzy ['version_modifier'] \
+									if 'version_modifier' in fuzzy \
+								else None
+
+							if vmod:
 								if '!' in vmod:
 									# package matches, but specific version is forbidden
 									# ( !<package>-<specific verion> <package> )

diff --git a/roverlay/depres/simpledeprule/pool.py b/roverlay/depres/simpledeprule/pool.py
new file mode 100644
index 0000000..8a2b7b2
--- /dev/null
+++ b/roverlay/depres/simpledeprule/pool.py
@@ -0,0 +1,79 @@
+# R overlay -- simple dependency rules
+# Copyright 2006-2012 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+#import re
+import logging
+
+#from roverlay import config
+from roverlay.depres import deprule
+from roverlay.depres.simpledeprule.reader import SimpleDependencyRuleReader
+#from roverlay.depres.simpledeprule.rules import *
+from roverlay.depres.simpledeprule.abstractrules import SimpleRule
+
+TMP_LOGGER = logging.getLogger ('simpledeps')
+
+class SimpleDependencyRulePool ( deprule.DependencyRulePool ):
+
+	def __init__ ( self, name, priority=70, filepath=None ):
+		"""Initializes a SimpleDependencyRulePool, which is a DependencyRulePool
+		specialized in simple dependency rules;
+		it offers loading rules from files.
+
+		arguments:
+		* name     -- string identifier for this pool
+		* priority -- of this pool
+		* filepath -- if set and not None: load a rule file directly
+		"""
+		super ( SimpleDependencyRulePool, self ) . __init__ ( name, priority )
+
+		if not filepath is None:
+			self.load_rule_file ( filepath )
+
+	# --- end of __init__ (...) ---
+
+	def add ( self, rule ):
+		"""Adds a rule to this pool.
+		Its class has to be SimpleIgnoreDependencyRule or derived from it.
+
+		arguments:
+		* rule --
+		"""
+		if isinstance ( rule, SimpleRule ):
+			self.rules.append ( rule )
+		else:
+			raise Exception ( "bad usage (simple dependency rule expected)." )
+
+	# --- end of add (...) ---
+
+	def get_reader ( self ):
+		return SimpleDependencyRuleReader ( rule_add=self.add )
+	# --- end of get_reader (...) ---
+
+	def load_rule_file ( self, filepath ):
+		"""Loads a rule file and adds the read rules to this pool.
+
+		arguments:
+		* filepath -- file to read
+		"""
+		logging.error ( "load_rule_file(***) is deprecated, use get_reader()!" )
+		new_rules = SimpleDependencyRuleReader().read_file ( filepath )
+		for rule in new_rules:
+			self.add ( rule )
+
+	# --- end of load_rule_file (...) ---
+
+	def export_rules ( self, fh ):
+		"""Exports all rules from this pool into the given file handle.
+
+		arguments:
+		* fh -- object that has a writelines ( list ) method
+
+		raises: IOError (fh)
+		"""
+		for rule in self.rules:
+			fh.write ( str ( rule ) )
+			fh.write ( '\n' )
+
+	# --- end of export_rules (...) ---
+

diff --git a/roverlay/depres/simpledeprule/reader.py b/roverlay/depres/simpledeprule/reader.py
new file mode 100644
index 0000000..40c6353
--- /dev/null
+++ b/roverlay/depres/simpledeprule/reader.py
@@ -0,0 +1,112 @@
+# R overlay -- simple dependency rules
+# Copyright 2006-2012 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+import os
+import logging
+
+from roverlay.depres.simpledeprule.rulemaker import SimpleRuleMaker
+
+class SimpleDependencyRuleReader ( object ):
+	"""SimpleDependencyRuleReader is a SimpleRuleMaker frontend for files."""
+
+	def __init__ ( self, rule_add=None ):
+		""" A SimpleDependencyRuleReader reads such rules from a file."""
+		self.logger = logging.getLogger ( self.__class__.__name__ )
+
+		# note that breakparse is reader-specific (not in SimpleRuleMaker)
+		self.breakparse = set (( '#! NOPARSE', '#! BREAK' ))
+
+		self._rmaker = SimpleRuleMaker()
+
+		self.rule_add = rule_add
+	# --- end of __init__  (...) ---
+
+	def read ( self, files_or_dirs ):
+		if self.rule_add is None:
+			raise AssertionError ( "Rule pool expected, but rule_add is None." )
+
+		for k in files_or_dirs:
+			if os.path.isdir ( k ):
+				self.read_dir ( k )
+			else:
+				self.read_file ( k )
+
+
+	def read_dir ( self, _dir ):
+		# without recursion
+		for fname in os.listdir ( _dir ):
+			f = _dir + os.sep + fname
+			if os.path.isfile ( f ):
+				self.read_file ( f )
+	# --- end of read_dir (...) ---
+
+
+	def read_file ( self, filepath ):
+		"""Reads a file that contains simple dependency rules
+		(SimpleIgnoreDependencyRules/SimpleDependencyRules).
+
+		arguments:
+		* filepath -- file to read
+		"""
+
+		# line number is used for logging
+		lineno = 0
+
+		try:
+			self.logger.debug (
+				"Reading simple dependency rule file %{!r}.".format ( filepath )
+			)
+			fh = open ( filepath, 'r' )
+
+			for line in fh.readlines():
+				lineno += 1
+				line    = line.strip()
+
+				if not line:
+					# empty (the rule maker catches this, too)
+					pass
+
+				elif line in self.breakparse:
+					# stop reading here
+					break
+
+				elif not self._rmaker.add ( line ):
+					self.logger.error (
+						"In {!r}, line {}: cannot use this line.".format (
+							filepath, lineno
+						)
+					)
+				# ---
+
+			if fh: fh.close()
+
+			rules = self._rmaker.done()
+
+			self.logger.info (
+				"{}: read {} dependency rules (in {} lines)".format (
+					filepath, len ( rules ), lineno
+				)
+			)
+
+			if self.rule_add is not None:
+				for rule in rules:
+					self.rule_add ( rule )
+			else:
+				return rules
+
+		except IOError as ioerr:
+			if lineno:
+				self.logger.error (
+					"Failed to read file {!r} after {} lines.".format (
+						filepath, lineno
+					)
+				)
+			else:
+				self.logger.error (
+					"Could not read file {!r}.".format ( filepath )
+				)
+			raise
+		finally:
+			if 'fh' in locals() and fh: fh.close()
+
+		# --- end of read_file (...) ---

diff --git a/roverlay/depres/simpledeprule/rulemaker.py b/roverlay/depres/simpledeprule/rulemaker.py
new file mode 100644
index 0000000..2435787
--- /dev/null
+++ b/roverlay/depres/simpledeprule/rulemaker.py
@@ -0,0 +1,136 @@
+# R overlay -- simple dependency rules
+# Copyright 2006-2012 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+import re
+import logging
+
+from roverlay import config
+
+from roverlay.depres.simpledeprule import rules
+from roverlay.depres.simpledeprule.abstractrules import *
+
+class SimpleRuleMaker ( object ):
+
+	class RuleKeywords ( object ):
+		def __init__ ( self ):
+			self._default_rule, self._rule_map = rules.get_rule_map()
+
+		def lookup ( self, keyworded_string ):
+			"""Returns <matching rule class>, <keyworded_string without kw>."""
+			if len ( keyworded_string ) == 0:
+				cls    = self._default_rule
+				kwless = None
+			else:
+				# all keywords have length 1
+				kw = keyworded_string [0]
+				if kw in self._rule_map:
+					cls    = self._rule_map [kw]
+					kwless = keyworded_string[1:].lstrip()
+					if len ( kwless ) == 0:
+						kwless = None
+				else:
+					cls    = self._default_rule
+					kwless = keyworded_string
+
+			return ( cls, kwless )
+		# --- end of lookup (...) ---
+
+	def __init__ ( self, rule_separator=None ):
+		self.logger = logging.getLogger ( self.__class__.__name__ )
+
+		self.single_line_separator = re.compile (
+			'\s+::\s+' if rule_separator is None else rule_separator
+		)
+
+		self.multiline_start = '{'
+		self.multiline_stop  = '}'
+		self.comment_char    = '#'
+		self._kw             = self.__class__.RuleKeywords()
+		self._next           = None
+		self._rules          = list()
+	# --- end of __init__ (...) ---
+
+	def zap ( self ):
+		if self._next is not None:
+			self.logger.warning (
+				"Multi line rule does not end at EOF - ignored"
+			)
+		self._next         = None
+		self._rules        = list()
+	# --- end of zap (...) ---
+
+	def done ( self ):
+		retrules = self._rules
+		self.zap()
+		return retrules
+	# --- end of done (...) ---
+
+	def _single_line_rule ( self, dep, dep_str='' ):
+		# single line rule, either selfdep,
+		#  e.g. '~zoo' -> fuzzy sci-R/zoo :: zoo
+		#  or normal rule 'dev-lang/R :: R'
+		# selfdeps are always single line statements (!)
+
+		rule_class, resolving = self._kw.lookup ( dep )
+
+		if dep_str:
+			# normal rule
+			new_rule = rule_class (
+				resolving_package=resolving,
+				dep_str=dep_str,
+				is_selfdep=False
+			)
+
+		elif resolving is not None:
+			# selfdep
+			dep_str   = resolving
+			resolving = \
+				config.get_or_fail ( 'OVERLAY.category' ) + '/' + resolving
+
+			new_rule = rule_class (
+				resolving_package=resolving,
+				dep_str=dep_str,
+				is_selfdep=True
+			)
+		else:
+			return False
+
+		new_rule.done_reading()
+		self._rules.append ( new_rule )
+		return True
+	# --- end of _single_line_rule (...) ---
+
+	def add ( self, line ):
+		if len ( line ) == 0:
+			return True
+		elif self._next is not None:
+			if line [0] == self.multiline_stop:
+				# end of a multiline rule,
+				#  add rule to rules and set next_rule to None
+				self._next.done_reading()
+				self._rules.append ( self._next )
+				self._next = None
+			else:
+				# new resolved str
+				self._next.add_resolved ( line )
+
+			return True
+
+		elif line [0] == self.comment_char:
+			# comment
+			#  it is intented that multi line rules cannot contain comments
+			return True
+
+		elif len ( line ) > 1 and line [-1] == self.multiline_start:
+			l = line [:-1].rstrip()
+			rule_class, resolving = self._kw.lookup ( l )
+
+			self._next = rule_class ( resolving_package=resolving )
+			return True
+
+		else:
+			return self._single_line_rule (
+				*self.single_line_separator.split ( line, 1  )
+			)
+	# --- end of add (...) ---

diff --git a/roverlay/depres/simpledeprule/rules.py b/roverlay/depres/simpledeprule/rules.py
new file mode 100644
index 0000000..e78e7cc
--- /dev/null
+++ b/roverlay/depres/simpledeprule/rules.py
@@ -0,0 +1,89 @@
+# R overlay -- simple dependency rules
+# Copyright 2006-2012 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+from roverlay.depres.simpledeprule.abstractrules import \
+	SimpleRule, FuzzySimpleRule
+
+__all__ = (
+	'SimpleIgnoreDependencyRule', 'SimpleDependencyRule',
+	'SimpleFuzzyDependencyRule', 'SimpleFuzzyIgnoreDependencyRule'
+)
+
+def get_rule_map():
+	kwmap = { c.RULE_PREFIX : c for c in (
+		SimpleIgnoreDependencyRule,
+		SimpleFuzzyDependencyRule,
+		SimpleFuzzyIgnoreDependencyRule
+	) }
+
+	return ( SimpleDependencyRule, kwmap )
+# --- end of get_rule_map (...) ---
+
+
+class SimpleIgnoreDependencyRule ( SimpleRule ):
+
+	RULE_PREFIX = '!'
+
+	def __init__ ( self, priority=50, resolving_package=None, **kw ):
+		super ( SimpleIgnoreDependencyRule, self ) . __init__ (
+			logger_name = 'IGNORE_DEPS',
+			resolving_package=None,
+			priority=50,
+			**kw
+		)
+
+	def __str__ ( self ):
+		if self.is_selfdep:
+			return self.__class__.RULE_PREFIX + iter ( self.dep_alias ).next()
+		else:
+			return super ( self.__class__, self ) . __str__()
+
+class SimpleDependencyRule ( SimpleRule ):
+
+	def __init__ ( self, priority=70, resolving_package=None, **kw ):
+		"""Initializes a SimpleDependencyRule. This is
+		a SimpleIgnoreDependencyRule extended by a portage package string.
+
+		arguments:
+		* resolving package --
+		* dep_str --
+		* priority --
+		"""
+		super ( SimpleDependencyRule, self ) . __init__ (
+			priority=priority,
+			logger_name=resolving_package,
+			resolving_package=resolving_package,
+			**kw
+		)
+
+	# --- end of __init__ (...) ---
+
+class SimpleFuzzyIgnoreDependencyRule ( FuzzySimpleRule ):
+
+	RULE_PREFIX = '%'
+
+	def __init__ ( self, priority=51, resolving_package=None, **kw ):
+		super ( SimpleFuzzyIgnoreDependencyRule, self ) . __init__ (
+			priority=priority,
+			resolving_package=resolving_package,
+			logger_name = 'FUZZY.IGNORE_DEPS',
+			**kw
+		)
+
+	def __str__ ( self ):
+		if self.is_selfdep:
+			return self.__class__.RULE_PREFIX + iter ( self.dep_alias ).next()
+		else:
+			return super ( self.__class__, self ) . __str__()
+
+class SimpleFuzzyDependencyRule ( FuzzySimpleRule ):
+
+	RULE_PREFIX = '~'
+
+	def __init__ ( self, priority=71, resolving_package=None, **kw ):
+		super ( SimpleFuzzyDependencyRule, self ) . __init__ (
+			priority=priority,
+			resolving_package=resolving_package,
+			logger_name = 'FUZZY.' + resolving_package,
+			**kw
+		)

diff --git a/roverlay/recipe/easyresolver.py b/roverlay/recipe/easyresolver.py
index e510181..749396b 100644
--- a/roverlay/recipe/easyresolver.py
+++ b/roverlay/recipe/easyresolver.py
@@ -10,16 +10,11 @@ def setup():
 	# log everything
 	res.set_logmask ( -1 )
 
-	srule_pool = SimpleDependencyRulePool ( 'default pool', priority=45 )
-
 	srule_files = config.get ( 'DEPRES.simple_rules.files', None )
 
 	if srule_files:
-		if isinstance ( srule_files, str ):
-			srule_pool.load_rule_file ( srule_files )
-		else:
-			for f in srule_files:
-				srule_pool.load_rule_file ( f )
+		srule_pool = SimpleDependencyRulePool ( 'default pool', priority=45 )
+		srule_pool.get_reader().read ( srule_files )
 
 		res.add_rulepool ( srule_pool )
 



^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2012-07-11 18:44 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-11 18:43 [gentoo-commits] proj/R_overlay:master commit in: /, roverlay/depres/simpledeprule/, roverlay/depres/, config/, roverlay/recipe/ André Erdmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox