From: "André Erdmann" <dywi@mailerd.de>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/R_overlay:master commit in: roverlay/packagerules/parser/, roverlay/packagerules/parser/context/, ...
Date: Thu, 1 Aug 2013 12:44:54 +0000 (UTC) [thread overview]
Message-ID: <1375360359.703b273c1559be91ad2e7eeceff1b963e0f91e8a.dywi@gentoo> (raw)
commit: 703b273c1559be91ad2e7eeceff1b963e0f91e8a
Author: André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Thu Aug 1 12:32:39 2013 +0000
Commit: André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Thu Aug 1 12:32:39 2013 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=703b273c
package rules, syntax: support else-action block
Package rules can now declare an ELSE: block (following the ACTION: block) whose
action statements are executed if the rule's MATCH: block did not match a
package.
"ELSE IF" statements are not supported, but can be realized by placing a nested
rule in the ELSE: block.
Other changes:
* "null"/"pass" action statement. A no-op statement (removed at rule "compile"
time) which can be used to improve readability (e.g. if a rule has no actions
in the ACTION: block)
* "do-not-process"/"ignore" is now available as action (in addition to the
hard-wired IgnorePackageRule class). The rule parser chooses the "correct"
implementation (which depends on the rule).
An "do-not-process if <matches...> else do-not-process" rule is forbidden.
(As "workaround", it can be achieved via "do-not-process if <always true
condition>.)
* minor fix in RuleActionContext.feed() concerning arg count
* the rule context (responsible for parsing a single rule) manipulates its
status bitmask (bitwise-AND/OR) now instead of setting it directly
---
roverlay/packagerules/abstract/actions.py | 2 +
roverlay/packagerules/abstract/rules.py | 181 ++++++++++++++++---
roverlay/packagerules/acceptors/stringmatch.py | 6 +-
roverlay/packagerules/actions/evar.py | 2 +-
roverlay/packagerules/actions/ignore.py | 25 +++
roverlay/packagerules/actions/info.py | 4 +-
roverlay/packagerules/actions/trace.py | 4 +-
roverlay/packagerules/parser/context/action.py | 18 +-
roverlay/packagerules/parser/context/base.py | 2 +-
roverlay/packagerules/parser/context/rule.py | 233 +++++++++++++++++++------
roverlay/packagerules/parser/namespace.py | 9 +
roverlay/packagerules/parser/text.py | 18 +-
roverlay/packagerules/rules.py | 25 ++-
13 files changed, 419 insertions(+), 110 deletions(-)
diff --git a/roverlay/packagerules/abstract/actions.py b/roverlay/packagerules/abstract/actions.py
index f903398..608d20a 100644
--- a/roverlay/packagerules/abstract/actions.py
+++ b/roverlay/packagerules/abstract/actions.py
@@ -9,6 +9,8 @@ __all__ = [ 'PackageRuleAction', ]
class PackageRuleAction ( object ):
"""PackageRuleActions manipulate PackageInfo instances."""
+ INDENT = 3 * ' '
+
def __init__ ( self, priority=1000 ):
super ( PackageRuleAction, self ).__init__()
self.priority = priority
diff --git a/roverlay/packagerules/abstract/rules.py b/roverlay/packagerules/abstract/rules.py
index 02ce4df..98db68d 100644
--- a/roverlay/packagerules/abstract/rules.py
+++ b/roverlay/packagerules/abstract/rules.py
@@ -14,15 +14,16 @@ class IgnorePackageRule ( object ):
def __init__ ( self, priority=100 ):
super ( IgnorePackageRule, self ).__init__()
- self.priority = priority
- self._acceptor = None
- self.logger = None
+ self.is_toplevel = False
+ self.priority = priority
+ self._acceptor = None
+ self.logger = None
# --- end of __init__ (...) ---
- def _iter_rules ( self, with_self=True ):
+ def _iter_all_rules ( self, with_self=True ):
if with_self:
yield self
- # --- end of _iter_rules (...) ---
+ # --- end of _iter_all_rules (...) ---
def accepts ( self, p_info ):
"""Returns True if this rule matches the given PackageInfo else False.
@@ -50,7 +51,7 @@ class IgnorePackageRule ( object ):
* logger --
"""
self.logger = logger
- if hasattr ( self, '_acceptor' ):
+ if self._acceptor:
self._acceptor.set_logger ( self.logger )
# --- end of set_logger (...) ---
@@ -63,11 +64,20 @@ class IgnorePackageRule ( object ):
return False
# --- end of apply_actions (...) ---
+ def apply_alternative_actions ( self, p_info ):
+ """Nop.
+
+ arguments:
+ * p_info --
+ """
+ return True
+ # --- end of apply_alternative_actions (...) ---
+
def prepare ( self ):
"""
Prepares this rule for usage. Has to be called after adding actions.
"""
- if hasattr ( self, '_acceptor' ):
+ if self._acceptor:
self._acceptor.prepare()
# --- end of prepare (...) ---
@@ -75,19 +85,51 @@ class IgnorePackageRule ( object ):
yield level * ' ' + 'ignore'
# --- end of _gen_action_str (...) ---
+ def _gen_alt_action_str ( self, level ):
+ raise NotImplementedError()
+ # --- end of _gen_alt_action_str (...) ---
+
+ def _gen_alt_rules_str ( self, level ):
+ raise NotImplementedError()
+ # --- end of _gen_alt_rules_str (...) ---
+
+ def has_alternative_actions ( self ):
+ return False
+ # --- end of has_alternative_actions (...) ---
+
+ def has_alternative_rules ( self ):
+ return False
+ # --- end of has_alternative_rules (...) ---
+
def gen_str ( self, level ):
- indent = level * ' '
+ indent = level * ' '
+ next_level = level + 1
yield ( indent + 'MATCH:' )
- for s in self._acceptor.gen_str ( level=( level + 1 ), match_level=0 ):
+ for s in self._acceptor.gen_str ( level=next_level, match_level=0 ):
yield s
yield ( indent + 'ACTION:' )
- for s in self._gen_action_str ( level=( level + 1 ) ):
+ for s in self._gen_action_str ( level=next_level ):
yield s
if hasattr ( self, '_gen_rules_str' ):
- for s in self._gen_rules_str ( level=( level + 1 ) ):
+ for s in self._gen_rules_str ( level=next_level ):
+ yield s
+
+ have_alt = False
+
+ if self.has_alternative_actions():
+ yield ( indent + 'ELSE:' )
+ have_alt = True
+ for s in self._gen_alt_action_str ( level=next_level ):
+ yield s
+
+ if self.has_alternative_rules():
+ if not have_alt:
+ yield ( indent + 'ELSE:' )
+ have_alt = True
+ for s in self._gen_alt_rules_str ( level=next_level ):
yield s
yield ( indent + 'END;' )
@@ -109,15 +151,21 @@ class PackageRule ( IgnorePackageRule ):
def __init__ ( self, priority=1000 ):
super ( PackageRule, self ).__init__( priority )
- self._actions = list()
+ self._actions = list()
+ self._alt_actions = list()
# --- end of __init__ (...) ---
+ def has_alternative_actions ( self ):
+ return bool ( self._alt_actions )
+ # --- end of has_alternative_actions (...) ---
+
def prepare ( self ):
"""
Prepares this rule for usage. Has to be called after adding actions.
"""
super ( PackageRule, self ).prepare()
- self._actions = roverlay.util.priosort ( self._actions )
+ self._actions = roverlay.util.priosort ( self._actions )
+ self._alt_actions = roverlay.util.priosort ( self._alt_actions )
# --- end of prepare (...) ---
def set_logger ( self, logger ):
@@ -127,9 +175,14 @@ class PackageRule ( IgnorePackageRule ):
* logger --
"""
super ( PackageRule, self ).set_logger ( logger )
+
action_logger = self.logger.getChild ( 'Action' )
for action in self._actions:
action.set_logger ( action_logger )
+
+ #action_logger = self.logger.getChild ( 'ElseAction' )
+ for action in self._alt_actions:
+ action.set_logger ( action_logger )
# --- end of set_logger (...) ---
def apply_actions ( self, p_info ):
@@ -148,6 +201,18 @@ class PackageRule ( IgnorePackageRule ):
return True
# --- end of apply_actions (...) ---
+ def apply_alternative_actions ( self, p_info ):
+ """Applies all 'alternative' actions to the given PackageInfo.
+
+ arguments:
+ * p_info --
+ """
+ for action in self._alt_actions:
+ if action.apply_action ( p_info ) is False:
+ return False
+ return True
+ # --- end of apply_alternative_actions (...) ---
+
def add_action ( self, action ):
"""Adds an action to this rule.
@@ -157,12 +222,27 @@ class PackageRule ( IgnorePackageRule ):
self._actions.append ( action )
# --- end of add_action (...) ---
+ def add_alternative_action ( self, action ):
+ """Adds an 'alternative' action to this rule.
+
+ arguments:
+ * action --
+ """
+ self._alt_actions.append ( action )
+ # --- end of add_alternative_action (...) ---
+
def _gen_action_str ( self, level ):
for x in self._actions:
for s in x.gen_str ( level=level ):
yield s
# --- end of _gen_action_str (...) ---
+ def _gen_alt_action_str ( self, level ):
+ for x in self._alt_actions:
+ for s in x.gen_str ( level=level ):
+ yield s
+ # --- end of _gen_alt_action_str (...) ---
+
# --- end of PackageRule ---
@@ -171,23 +251,38 @@ class NestedPackageRule ( PackageRule ):
def __init__ ( self, priority=2000 ):
super ( NestedPackageRule, self ).__init__ ( priority )
- self._rules = list()
+ self._rules = list()
+ self._alt_rules = list()
# --- end of __init__ (...) ---
+ def has_alternative_rules ( self ):
+ return bool ( self._alt_rules )
+ # --- end of has_alternative_rules (...) ---
+
def _gen_rules_str ( self, level ):
for rule in self._rules:
for s in rule.gen_str ( level ):
yield s
# --- end of _gen_rules_str (...) ---
- def _iter_rules ( self, with_self=True ):
+ def _gen_alt_rules_str ( self, level ):
+ for rule in self._alt_rules:
+ for s in rule.gen_str ( level ):
+ yield s
+ # --- end of _gen_alt_rules_str (...) ---
+
+ def _iter_all_rules ( self, with_self=True ):
if with_self:
yield self
for rule in self._rules:
- for nested_rule in rule._iter_rules ( with_self=True ):
+ for nested_rule in rule._iter_all_rules ( with_self=True ):
+ yield nested_rule
+
+ for rule in self._alt_rules:
+ for nested_rule in rule._iter_all_rules ( with_self=True ):
yield nested_rule
- # --- end of _iter_rules (...) ---
+ # --- end of _iter_all_rules (...) ---
def set_logger ( self, logger ):
"""Assigns a logger to this package rule and all actions.
@@ -196,13 +291,17 @@ class NestedPackageRule ( PackageRule ):
* logger --
"""
super ( NestedPackageRule, self ).set_logger ( logger )
- if hasattr ( self, 'is_toplevel' ) and self.is_toplevel:
+
+ if self.is_toplevel:
nested_logger = self.logger.getChild ( 'nested' )
- for nested_rule in self._rules:
- nested_rule.set_logger ( nested_logger )
else:
- for nested_rule in self._rules:
- nested_rule.set_logger ( self.logger )
+ nested_logger = self.logger
+
+ for nested_rule in self._rules:
+ nested_rule.set_logger ( nested_logger )
+
+ for nested_rule in self._alt_rules:
+ nested_rule.set_logger ( nested_logger )
# --- end of set_logger (...) ---
def prepare ( self ):
@@ -212,7 +311,8 @@ class NestedPackageRule ( PackageRule ):
super ( NestedPackageRule, self ).prepare()
for rule in self._rules:
rule.prepare()
- self._rules = roverlay.util.priosort ( self._rules )
+ self._rules = roverlay.util.priosort ( self._rules )
+ self._alt_rules = roverlay.util.priosort ( self._alt_rules )
# --- end of prepare (...) ---
def apply_actions ( self, p_info ):
@@ -226,13 +326,37 @@ class NestedPackageRule ( PackageRule ):
"""
if super ( NestedPackageRule, self ).apply_actions ( p_info ):
for rule in self._rules:
- if rule.accepts ( p_info ) and not rule.apply_actions ( p_info ):
+ if rule.accepts ( p_info ):
+ if not rule.apply_actions ( p_info ):
+ return False
+ elif not rule.apply_alternative_actions ( p_info ):
return False
return True
else:
return False
# --- end of apply_actions (...) ---
+ def apply_alternative_actions ( self, p_info ):
+ """Applies all 'alternative' actions to the given PackageInfo.
+
+ arguments:
+ * p_info --
+ """
+ if ( super (
+ NestedPackageRule, self ).apply_alternative_actions ( p_info )
+ ):
+ for rule in self._alt_rules:
+ if rule.accepts ( p_info ):
+ if not rule.apply_actions ( p_info ):
+ return False
+ elif not rule.apply_alternative_actions ( p_info ):
+ return False
+
+ return True
+ else:
+ return False
+ # --- end of apply_alternative_actions (...) ---
+
def add_rule ( self, rule ):
"""Adds a rule.
@@ -242,4 +366,13 @@ class NestedPackageRule ( PackageRule ):
self._rules.append ( rule )
# --- end of add_rule (...) ---
+ def add_alternative_rule ( self, rule ):
+ """Adds an 'alternative' rule.
+
+ arguments:
+ * rule --
+ """
+ self._alt_rules.append ( rule )
+ # --- end of add_alternative_rule (...) ---
+
# --- end of NestedPackageRule ---
diff --git a/roverlay/packagerules/acceptors/stringmatch.py b/roverlay/packagerules/acceptors/stringmatch.py
index f5da49f..b6007b6 100644
--- a/roverlay/packagerules/acceptors/stringmatch.py
+++ b/roverlay/packagerules/acceptors/stringmatch.py
@@ -103,8 +103,10 @@ class RegexAcceptor (
self.__class__.__name__
)
)
-
- self._regex = regex_compiled if regex_compiled else re.compile ( regex )
+ elif regex_compiled:
+ self._regex = regex_compiled
+ else:
+ self._regex = re.compile ( regex )
# --- end of __init__ (...) ---
def _matches ( self, value ):
diff --git a/roverlay/packagerules/actions/evar.py b/roverlay/packagerules/actions/evar.py
index c789219..17f46fe 100644
--- a/roverlay/packagerules/actions/evar.py
+++ b/roverlay/packagerules/actions/evar.py
@@ -46,7 +46,7 @@ class EvarAction ( roverlay.packagerules.abstract.actions.PackageRuleAction ):
def gen_str ( self, level ):
yield (
- level * ' ' + self._evar.name.lower()
+ ( level * self.INDENT ) + self._evar.name.lower()
+ ' "' + self._evar.value + '"'
)
# --- end of gen_str (...) ---
diff --git a/roverlay/packagerules/actions/ignore.py b/roverlay/packagerules/actions/ignore.py
new file mode 100644
index 0000000..5ee19f9
--- /dev/null
+++ b/roverlay/packagerules/actions/ignore.py
@@ -0,0 +1,25 @@
+# R overlay -- package rule actions, ignore package
+# -*- coding: utf-8 -*-
+# Copyright (C) 2013 André Erdmann <dywi@mailerd.de>
+# Distributed under the terms of the GNU General Public License;
+# either version 2 of the License, or (at your option) any later version.
+
+import roverlay.packagerules.abstract.actions
+
+__all__ = [ 'IgnoreAction', ]
+
+class IgnoreAction (
+ roverlay.packagerules.abstract.actions.PackageRuleAction
+):
+
+ KEYWORD = 'ignore'
+
+ def apply_action ( self, p_info ):
+ return False
+ # --- end of apply_action (...) ---
+
+ def gen_str ( self, level ):
+ yield ( level * self.INDENT ) + self.KEYWORD
+ # --- end of gen_str (...) ---
+
+# --- end of IgnoreAction ---
diff --git a/roverlay/packagerules/actions/info.py b/roverlay/packagerules/actions/info.py
index 538fdef..d9f1390 100644
--- a/roverlay/packagerules/actions/info.py
+++ b/roverlay/packagerules/actions/info.py
@@ -59,7 +59,7 @@ class InfoRenameAction (
# FIXME: that's not always correct!
# (could be solved by storing the original regex delimiter)
yield (
- level * ' ' + 'rename ' + self.key
+ level * self.INDENT + 'rename ' + self.key
+ ' s/' + self.regex.pattern + '/' + self.subst + '/' # + flags
)
# --- end of gen_str (...) ---
@@ -162,7 +162,7 @@ class InfoSetToAction (
# --- end of apply_action (...) ---
def gen_str ( self, level ):
- yield ( level * ' ' + 'set ' + self.key + ' ' + self.value )
+ yield ( level * self.INDENT + 'set ' + self.key + ' ' + self.value )
# --- end of gen_str (...) ---
# --- end of InfoSetToAction ---
diff --git a/roverlay/packagerules/actions/trace.py b/roverlay/packagerules/actions/trace.py
index 669969a..c16f6c6 100644
--- a/roverlay/packagerules/actions/trace.py
+++ b/roverlay/packagerules/actions/trace.py
@@ -38,7 +38,7 @@ class TraceAction (
# --- end of apply_action (...) ---
def gen_str ( self, level ):
- yield ( level * ' ' ) + "trace " + str ( self._ident )
+ yield ( level * self.INDENT ) + "trace " + str ( self._ident )
# --- end of gen_str (...) ---
@@ -57,5 +57,5 @@ class MarkAsModifiedAction (
# --- end of apply_action (...) ---
def gen_str ( self, level ):
- yield ( level * ' ' ) + "trace"
+ yield ( level * self.INDENT ) + "trace"
# --- end of gen_str (...) ---
diff --git a/roverlay/packagerules/parser/context/action.py b/roverlay/packagerules/parser/context/action.py
index 22936cc..49ed7db 100644
--- a/roverlay/packagerules/parser/context/action.py
+++ b/roverlay/packagerules/parser/context/action.py
@@ -37,14 +37,16 @@ class RuleActionContext (
"""RuleActionContext parses action-blocks."""
# keywords for the "ignore" action
- KEYWORDS_ACTION_IGNORE = frozenset ((
+ KEYWORDS_ACTION_IGNORE = frozenset ({
'ignore',
'do-not-process'
- ))
+ })
- KEYWORDS_ACTION_TRACE = frozenset ((
+ KEYWORDS_ACTION_TRACE = frozenset ({
'trace',
- ))
+ })
+
+ KEYWORDS_NO_ACTION = frozenset ({ 'pass', 'null', })
# dict ( <keyword> => <evar class> )
# Dict of evar action keywords (with corresponding classes)
@@ -225,7 +227,9 @@ class RuleActionContext (
Raises:
* InvalidContext
"""
- if _str in self.KEYWORDS_ACTION_IGNORE:
+ if _str in self.KEYWORDS_NO_ACTION:
+ pass
+ elif _str in self.KEYWORDS_ACTION_IGNORE:
if not self._actions:
self._actions = None
else:
@@ -255,7 +259,9 @@ class RuleActionContext (
)
)
- elif self._add_as_info_action ( argv [0], argv [1], _str, lino ):
+ elif len ( argv ) > 1 and (
+ self._add_as_info_action ( argv [0], argv [1], _str, lino )
+ ):
pass
else:
diff --git a/roverlay/packagerules/parser/context/base.py b/roverlay/packagerules/parser/context/base.py
index 1a09a79..9bd97b7 100644
--- a/roverlay/packagerules/parser/context/base.py
+++ b/roverlay/packagerules/parser/context/base.py
@@ -15,7 +15,7 @@ class BaseContext ( object ):
self.namespace = namespace
# --- end of __init__ (...) ---
- def feed ( self, _str ):
+ def feed ( self, _str, lino ):
raise NotImplementedError()
# --- end of feed (...) ---
diff --git a/roverlay/packagerules/parser/context/rule.py b/roverlay/packagerules/parser/context/rule.py
index 2601d7e..0f6f342 100644
--- a/roverlay/packagerules/parser/context/rule.py
+++ b/roverlay/packagerules/parser/context/rule.py
@@ -4,11 +4,18 @@
# Distributed under the terms of the GNU General Public License;
# either version 2 of the License, or (at your option) any later version.
-from roverlay.packagerules.abstract import rules
+import roverlay.packagerules.abstract.rules
+from roverlay.packagerules.abstract.rules import \
+ IgnorePackageRule, PackageRule, NestedPackageRule
-from . import base, match, action
+import roverlay.packagerules.parser.context.action
+import roverlay.packagerules.parser.context.base
+import roverlay.packagerules.parser.context.match
-class RuleContext ( base.NestableContext ):
+
+class RuleContext (
+ roverlay.packagerules.parser.context.base.NestableContext
+):
"""Class for creating rules from text input (feed(<>)) plus using a few
control flow functions (end_of_rule(), begin_match(), begin_action()).
"""
@@ -29,28 +36,55 @@ class RuleContext ( base.NestableContext ):
#
# (use bitwise operators to check against these values)
#
- CONTEXT_NONE = 0 # == only
- CONTEXT_MAIN_MATCH = 1
- CONTEXT_MAIN_ACTION = 2
- CONTEXT_SUB_MATCH = 4
- CONTEXT_SUB_ACTION = 8
+ CONTEXT_NONE = 0 # == only
+ CONTEXT_MAIN_MATCH = 1
+ CONTEXT_MAIN_ACTION = 2
+ CONTEXT_MAIN_ALT_ACTION = 4
+ CONTEXT_SUB_MATCH = 8
+ CONTEXT_SUB_ACTION = 16
+ # else-block is a non-propagating status
+ #CONTEXT_SUB_ALT_ACTION
+
+ CONTEXT_MATCH = CONTEXT_MAIN_MATCH | CONTEXT_SUB_MATCH
+ CONTEXT_ACTION = CONTEXT_MAIN_ACTION | CONTEXT_SUB_ACTION
+ CONTEXT_MAIN_ANY_ACTION = CONTEXT_MAIN_ALT_ACTION | CONTEXT_MAIN_ACTION
+ CONTEXT_SUB = CONTEXT_SUB_MATCH | CONTEXT_SUB_ACTION
+
+ CONTEXT_MAIN = (
+ CONTEXT_MAIN_MATCH | CONTEXT_MAIN_ACTION | CONTEXT_MAIN_ALT_ACTION
+ )
- CONTEXT_MATCH = CONTEXT_MAIN_MATCH | CONTEXT_SUB_MATCH
- CONTEXT_ACTION = CONTEXT_MAIN_ACTION | CONTEXT_SUB_ACTION
- CONTEXT_MAIN = CONTEXT_MAIN_MATCH | CONTEXT_MAIN_ACTION
- CONTEXT_SUB = CONTEXT_SUB_MATCH | CONTEXT_SUB_ACTION
# -- end of CONTEXT_ --
- def __init__ ( self, namespace, level=0, priority=-1 ):
+ def __init__ ( self, namespace, level=0, priority=-1, mode=None ):
super ( RuleContext, self ).__init__ ( namespace, level )
- self.context = self.CONTEXT_MAIN_MATCH
- self.priority = priority
- self._action_context = action.RuleActionContext ( self.namespace )
- self._match_context = match.RuleMatchContext (
- namespace = self.namespace,
- priority = priority
+ if mode is None:
+ if level == 0:
+ self.mode = self.CONTEXT_MAIN_ACTION
+ else:
+ raise Exception ( "mode has to be set if level is non-zero." )
+ else:
+ self.mode = mode
+
+ self.context = self.CONTEXT_MAIN_MATCH
+ self.priority = priority
+ self._action_context = (
+ roverlay.packagerules.parser.context.action.RuleActionContext (
+ self.namespace
+ )
+ )
+ self._alt_action_context = (
+ roverlay.packagerules.parser.context.action.RuleActionContext (
+ self.namespace
+ )
+ )
+ self._match_context = (
+ roverlay.packagerules.parser.context.match.RuleMatchContext (
+ namespace = self.namespace,
+ priority = priority
+ )
)
# --- end of __init__ (...) ---
@@ -66,15 +100,22 @@ class RuleContext ( base.NestableContext ):
# nested rules are stored in self._nested (and not in
# self._action_context where they syntactically belong to)
- if self.context & self.CONTEXT_MAIN_ACTION:
- # a nested rule (with depth = 1)
- self._new_nested ( priority=lino )
- self.context = self.CONTEXT_SUB_MATCH
- elif self.context & self.CONTEXT_SUB_ACTION:
+ if self.context & self.CONTEXT_SUB_ACTION:
# a nested rule inside a nested one (depth > 1)
# => redirect to nested
self.get_nested().begin_match ( lino )
- self.context = self.CONTEXT_SUB_MATCH
+ self.context |= self.CONTEXT_SUB_MATCH
+
+ elif self.context & self.CONTEXT_MAIN_ACTION:
+ # a nested rule (with depth = 1)
+ self._new_nested ( priority=lino, mode=self.CONTEXT_MAIN_ACTION )
+ self.context |= self.CONTEXT_SUB_MATCH
+
+ elif self.context & self.CONTEXT_MAIN_ALT_ACTION:
+ # a new nested rule in the else block (with depth = 1)
+ self._new_nested ( priority=lino, mode=self.CONTEXT_MAIN_ALT_ACTION )
+ self.context |= self.CONTEXT_SUB_MATCH
+
else:
# illegal
raise self.InvalidContext()
@@ -87,21 +128,50 @@ class RuleContext ( base.NestableContext ):
* lino -- line number
Raises: InvalidContext,
- an action-block has to be preceeded by a match-block
+ an action block has to be preceeded by a match block
"""
- if self.context & self.CONTEXT_MAIN_MATCH:
- # begin of the main action-block
- self.context = self.CONTEXT_MAIN_ACTION
- elif self.context & self.CONTEXT_SUB_MATCH:
+ if self.context & self.CONTEXT_SUB_MATCH:
# action-block of a nested rule
# => redirect to nested
self.get_nested().begin_action ( lino )
- self.context = self.CONTEXT_SUB_ACTION
+ self.context &= ~self.CONTEXT_SUB_MATCH
+ self.context |= self.CONTEXT_SUB_ACTION
+
+ elif self.context & self.CONTEXT_MAIN_MATCH:
+ # begin of the main action-block
+ self.context &= ~self.CONTEXT_MAIN_MATCH
+ self.context |= self.CONTEXT_MAIN_ACTION
+
else:
# illegal
raise self.InvalidContext()
# --- end of begin_action (...) ---
+ def begin_alternative_action ( self, lino ):
+ """Create/begin an else-action block of a rule (nested or "self").
+
+ arguments:
+ * lino -- line number
+
+ Raises: InvalidContext,
+ an else-action block has to be preceeded by an action block
+ """
+ if self.context & self.CONTEXT_SUB_ACTION:
+ # else-action-block of a nested rule
+ # => redirect to nested
+ # no status change as else-blocks are handled non-recursively
+ self.get_nested().begin_alternative_action ( lino )
+
+ elif self.context & self.CONTEXT_MAIN_ACTION:
+ # begin of the main else-action-block
+ self.context &= ~self.CONTEXT_MAIN_ACTION
+ self.context |= self.CONTEXT_MAIN_ALT_ACTION
+
+ else:
+ # illegal
+ raise self.InvalidContext()
+ # --- end of begin_alternative_action (...) ---
+
def end_of_rule ( self, lino ):
"""Has to be called whenever an end-of-rule statement has been reached
and ends a rule, either this one or a nested one (depending on the
@@ -116,14 +186,10 @@ class RuleContext ( base.NestableContext ):
Raises: InvalidContext,
rules can only be closed if within an action-block
"""
- if self.context & self.CONTEXT_MAIN_ACTION:
- # end of this rule
- self.context = self.CONTEXT_NONE
- return True
- elif self.context & self.CONTEXT_SUB_ACTION:
+ if self.context & self.CONTEXT_SUB_ACTION:
if self.get_nested().end_of_rule ( lino ):
# end of child rule (depth=1)
- self.context = self.CONTEXT_MAIN_ACTION
+ self.context &= ~self.CONTEXT_SUB_ACTION
# no-op, since self.context is already CONTEXT_SUB_ACTION
# else:
@@ -131,6 +197,17 @@ class RuleContext ( base.NestableContext ):
# self.context = self.CONTEXT_SUB_ACTION
return False
+
+ elif self.context & self.CONTEXT_MAIN_ANY_ACTION:
+ # end of this rule
+ #self.context = self.CONTEXT_NONE
+ self.context &= ~self.CONTEXT_MAIN_ANY_ACTION
+ if self.context != self.CONTEXT_NONE:
+ raise AssertionError (
+ "broken context bit mask {:d}!".format ( self.context )
+ )
+ return True
+
else:
raise self.InvalidContext()
# --- end of end_of_rule (...) ---
@@ -145,12 +222,18 @@ class RuleContext ( base.NestableContext ):
Raises: InvalidContext if this rule does not accept input
(if self.context is CONTEXT_NONE)
"""
- if self.context & self.CONTEXT_MAIN_MATCH:
+ if self.context & self.CONTEXT_SUB:
+ return self.get_nested().feed ( _str, lino )
+
+ elif self.context & self.CONTEXT_MAIN_MATCH:
return self._match_context.feed ( _str, lino )
+
elif self.context & self.CONTEXT_MAIN_ACTION:
return self._action_context.feed ( _str, lino )
- elif self.context & self.CONTEXT_SUB:
- return self.get_nested().feed ( _str, lino )
+
+ elif self.context & self.CONTEXT_MAIN_ALT_ACTION:
+ return self._alt_action_context.feed ( _str, lino )
+
else:
raise self.InvalidContext()
# --- end of feed (...) ---
@@ -171,37 +254,71 @@ class RuleContext ( base.NestableContext ):
raise self.InvalidContext ( "end_of_rule not reached." )
# -- if;
- package_rule = None
- actions = self._action_context.create()
- acceptor = self._match_context.create()
+ package_rule = None
+ actions = self._action_context.create()
+ alt_actions = self._alt_action_context.create()
+ acceptor = self._match_context.create()
+ ACTION_IGNORE = self.namespace.get_ignore_action()
if not acceptor:
raise Exception ( "empty match-block makes no sense." )
+ elif actions is None and alt_actions is None:
+ raise Exception ( "ignore-all rule makes no sense." )
+
elif len ( self._nested ) > 0:
# nested rule
+ package_rule = NestedPackageRule ( priority=self.priority )
+ for nested in self._nested:
+ nested_rule = nested.create()
+ if nested.mode == self.CONTEXT_MAIN_ACTION:
+ package_rule.add_rule ( nested_rule )
+ elif nested.mode == self.CONTEXT_MAIN_ALT_ACTION:
+ package_rule.add_alternative_rule ( nested_rule )
+ else:
+ raise Exception ( "nested rule has invalid mode" )
+
if actions is None:
- raise Exception (
- "ignore action-block cannot contain nested rules."
- )
+ package_rule.add_action ( ACTION_IGNORE )
else:
- package_rule = rules.NestedPackageRule ( priority=self.priority )
- for nested in self._nested:
- package_rule.add_rule ( nested.create() )
+ for rule_action in actions:
+ package_rule.add_action ( rule_action )
- for action in actions:
- package_rule.add_action ( action )
+ if alt_actions is None:
+ package_rule.add_alternative_action ( ACTION_IGNORE )
+ else:
+ for rule_action in alt_actions:
+ package_rule.add_alternative_action ( rule_action )
elif actions is None:
- # ignore rule
- package_rule = rules.IgnorePackageRule ( priority=self.priority )
+ if alt_actions:
+ # ignore rule with else-action block
+ package_rule = PackageRule ( priority=self.priority )
+ package_rule.add_action ( ACTION_IGNORE )
+
+ for rule_action in alt_actions:
+ package_rule.add_alternative_action ( rule_action )
+ else:
+ # ignore rule
+ package_rule = IgnorePackageRule ( priority=self.priority )
+
+ elif alt_actions is None:
+ # normal rule with else-ignore block
+ package_rule = PackageRule ( priority=self.priority )
+ package_rule.add_alternative_action ( ACTION_IGNORE )
+
+ for rule_action in actions:
+ package_rule.add_action ( rule_action )
+
+ elif actions or alt_actions:
+ # normal rule with action and/or else-action block
+ package_rule = PackageRule ( priority=self.priority )
- elif actions:
- # normal rule
- package_rule = rules.PackageRule ( priority=self.priority )
+ for rule_action in actions:
+ package_rule.add_action ( rule_action )
- for action in actions:
- package_rule.add_action ( action )
+ for rule_action in alt_actions:
+ package_rule.add_alternative_action ( rule_action )
else:
raise Exception ( "empty action-block makes no sense." )
diff --git a/roverlay/packagerules/parser/namespace.py b/roverlay/packagerules/parser/namespace.py
index 6af8661..ab9b7d8 100644
--- a/roverlay/packagerules/parser/namespace.py
+++ b/roverlay/packagerules/parser/namespace.py
@@ -6,6 +6,8 @@
import roverlay.util
+import roverlay.packagerules.actions.ignore
+
DEBUG_GET_OBJECT = False
if DEBUG_GET_OBJECT:
@@ -36,8 +38,15 @@ class RuleNamespace ( object ):
# )
#
self._objects = dict()
+ self._ignore_action = (
+ roverlay.packagerules.actions.ignore.IgnoreAction()
+ )
# --- end of __init__ (...) ---
+ def get_ignore_action ( self ):
+ return self._ignore_action
+ # --- end of get_ignore_action (...) ---
+
def get_object ( self, cls, *args, **kwargs ):
"""Returns the desired object.
diff --git a/roverlay/packagerules/parser/text.py b/roverlay/packagerules/parser/text.py
index 4060e95..87db0b0 100644
--- a/roverlay/packagerules/parser/text.py
+++ b/roverlay/packagerules/parser/text.py
@@ -20,17 +20,16 @@ class RuleParser ( object ):
# control flow statements
# all other keywords are defined in the respective context classes,
# namely RuleContext, RuleMatchContext and RuleActionContext
- KEYWORDS_MATCH = frozenset (( 'match:', 'MATCH:', ))
- KEYWORDS_ACTION = frozenset (( 'action:', 'ACTION:' ))
- KEYWORDS_END = frozenset (( 'end;', 'END;' ))
+ KEYWORDS_MATCH = frozenset ({ 'match:', 'MATCH:', })
+ KEYWORDS_ACTION = frozenset ({ 'action:', 'ACTION:' })
+ KEYWORDS_ACTION_ELSE = frozenset ({ 'else:', 'ELSE:' })
+ KEYWORDS_END = frozenset ({ 'end;', 'END;' })
- COMMENT_CHARS = frozenset ( "#;" )
+ COMMENT_CHARS = frozenset ({ '#', ';' })
def _zap ( self ):
self.namespace.zap ( zap_object_db=False )
- # the rule block (RuleContext) that is currently active
self._current_rule = None
- # previous rule blocks
self._parsed_rules = list()
# --- end of _zap (...) ---
@@ -44,6 +43,11 @@ class RuleParser ( object ):
self.namespace = roverlay.packagerules.parser.namespace.RuleNamespace()
self.add_rule = add_rule_method
self._zap()
+
+ # the rule block (RuleContext) that is currently active
+ self._current_rule = None
+ # previous rule blocks
+ self._parsed_rules = None
# --- end of __init__ (...) ---
def _feed ( self, l, lino ):
@@ -59,6 +63,8 @@ class RuleParser ( object ):
self._current_rule.begin_match ( lino )
elif l in self.KEYWORDS_ACTION:
self._current_rule.begin_action ( lino )
+ elif l in self.KEYWORDS_ACTION_ELSE:
+ self._current_rule.begin_alternative_action ( lino )
elif l in self.KEYWORDS_END:
if self._current_rule.end_of_rule ( lino ):
# add rule to self._parsed_rules
diff --git a/roverlay/packagerules/rules.py b/roverlay/packagerules/rules.py
index 649343a..9ca91e5 100644
--- a/roverlay/packagerules/rules.py
+++ b/roverlay/packagerules/rules.py
@@ -45,7 +45,6 @@ class PackageRules ( roverlay.packagerules.abstract.rules.NestedPackageRule ):
def __init__ ( self ):
super ( PackageRules, self ).__init__ ( priority=-1 )
- del self._acceptor
self.logger = logging.getLogger ( self.__class__.__name__ )
self.is_toplevel = True
# --- end of __init__ (...) ---
@@ -69,17 +68,27 @@ class PackageRules ( roverlay.packagerules.abstract.rules.NestedPackageRule ):
return True
# --- end of accepts (...) ---
+ def apply_alternative_actions ( self, p_info ):
+ raise Exception ( "toplevel rule does not contain else-block actions." )
+ # --- end of apply_alternative_actions (...) ---
+
+ def add_alternative_action ( self, action ):
+ raise Exception ( "toplevel rule does not accept else-block actions." )
+ # --- end of add_alternative_action (...) ---
+
def add_trace_actions ( self ):
"""Adds MarkAsModified actions to this rule and all nested ones.
- Meant for testing the package rule system."""
-
+ Meant for testing the package rule system.
+ """
marker = roverlay.packagerules.actions.trace.MarkAsModifiedAction ( -1 )
- for rule in filter (
- lambda rule : hasattr ( rule, 'add_action' ),
- self._iter_rules ( with_self=False )
- ):
- rule.add_action ( marker )
+
+ for rule in self._iter_all_rules ( with_self=False ):
+ if hasattr ( rule, 'add_action' ):
+ rule.add_action ( marker )
+
+ if hasattr ( rule, 'add_alternative_action' ):
+ rule.add_alternative_action ( marker )
self.prepare()
# --- end of add_trace_actions (...) ---
next reply other threads:[~2013-08-01 12:45 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-08-01 12:44 André Erdmann [this message]
-- strict thread matches above, loose matches on Subject: below --
2013-06-13 16:34 [gentoo-commits] proj/R_overlay:master commit in: roverlay/packagerules/parser/, roverlay/packagerules/parser/context/, André Erdmann
2013-03-01 19:00 André Erdmann
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=1375360359.703b273c1559be91ad2e7eeceff1b963e0f91e8a.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