From: "André Erdmann" <dywi@mailerd.de>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/R_overlay:master commit in: /, roverlay/depres/simpledeprule/, roverlay/depres/, config/, roverlay/recipe/
Date: Wed, 11 Jul 2012 18:43:51 +0000 (UTC) [thread overview]
Message-ID: <1342031792.bb8c8f16dd67c14f31af69e70c7c99baebbb80d9.dywi@gentoo> (raw)
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 )
reply other threads:[~2012-07-11 18:44 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=1342031792.bb8c8f16dd67c14f31af69e70c7c99baebbb80d9.dywi@gentoo \
--to=dywi@mailerd.de \
--cc=gentoo-commits@lists.gentoo.org \
--cc=gentoo-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