public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/R_overlay:gsoc13/next commit in: roverlay/depres/simpledeprule/, roverlay/depres/
  2013-07-03 10:05 [gentoo-commits] proj/R_overlay:master commit in: roverlay/depres/simpledeprule/, roverlay/depres/ André Erdmann
@ 2013-06-28  6:19 ` André Erdmann
  0 siblings, 0 replies; 4+ messages in thread
From: André Erdmann @ 2013-06-28  6:19 UTC (permalink / raw
  To: gentoo-commits

commit:     72af9d204837cbabf32c43ffcc50ebec93549f7f
Author:     André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Fri Jun 28 06:19:14 2013 +0000
Commit:     André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Fri Jun 28 06:19:14 2013 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=72af9d20

roverlay/depres: add SLOT handling to fuzzy depres

---
 roverlay/depres/depenv.py                      |  32 ++++-
 roverlay/depres/deprule.py                     |   2 +
 roverlay/depres/simpledeprule/abstractrules.py | 148 +++++++++----------
 roverlay/depres/simpledeprule/rulemaker.py     |  42 ++----
 roverlay/depres/simpledeprule/rules.py         | 192 +++++++++++++++++++++++--
 5 files changed, 303 insertions(+), 113 deletions(-)

diff --git a/roverlay/depres/depenv.py b/roverlay/depres/depenv.py
index 3021728..9371ef6 100644
--- a/roverlay/depres/depenv.py
+++ b/roverlay/depres/depenv.py
@@ -62,6 +62,27 @@ class DepEnv ( object ):
    # { <, >, ==, <=, >=, =, != }
    _VERMOD = '(?P<vmod>[<>]|[=<>!]?[=])'
 
+   # integer representation of version modifiers
+   VMOD_NONE  = 0
+   VMOD_UNDEF = 1
+   VMOD_NOT   = 2
+   VMOD_EQ    = 4
+   VMOD_NE    = VMOD_NOT | VMOD_EQ
+   VMOD_GT    = 8
+   VMOD_GE    = VMOD_EQ | VMOD_GT
+   VMOD_LT    = 16
+   VMOD_LE    = VMOD_EQ | VMOD_LT
+
+   VMOD = {
+      '!=' : VMOD_NE,
+      '='  : VMOD_EQ,
+      #'==' : VMOD_EQ, # normalized by _depslit()
+      '>'  : VMOD_GT,
+      '>=' : VMOD_GE,
+      '<'  : VMOD_LT,
+      '<=' : VMOD_LE,
+   }
+
    # name/version regexes used for fuzzy dep rules
    VERSION_REGEX = frozenset (
       re.compile ( r ) for r in ((
@@ -146,12 +167,19 @@ class DepEnv ( object ):
             if version [0] == '.': version = '0' + version
 
             vmod = m.group ( 'vmod' )
-            if vmod == '==' : vmod = '='
+
+            if not vmod:
+               # version required, but no modifier: set vmod to '>='
+               vmod = '>='
+            elif vmod == '==':
+               # "normalize"
+               vmod = '='
 
             result.append ( dict (
                name             = m.group ( 'name' ),
                version_modifier = vmod,
-               version          = version
+               version          = version,
+               vmod             = self.VMOD.get ( vmod, self.VMOD_UNDEF ),
             ) )
 
             if not self.try_all_regexes: break

diff --git a/roverlay/depres/deprule.py b/roverlay/depres/deprule.py
index b440d36..46c710d 100644
--- a/roverlay/depres/deprule.py
+++ b/roverlay/depres/deprule.py
@@ -19,6 +19,7 @@ class DependencyRule ( object ):
       arguments:
       * priority -- used for sorting rule pools, lower means more important
       """
+      super ( DependencyRule, self ).__init__()
       self.max_score = 1000
       self.priority  = priority
    # --- end of __init__ (...) ---
@@ -42,6 +43,7 @@ class DependencyRulePool ( object ):
       * name -- name of this rule pool
       * priority -- priority of this pool (lower is better)
       """
+      super ( DependencyRulePool, self ).__init__()
       if initial_rules is None:
          self.rules = list()
       else:

diff --git a/roverlay/depres/simpledeprule/abstractrules.py b/roverlay/depres/simpledeprule/abstractrules.py
index 1025b01..85c365d 100644
--- a/roverlay/depres/simpledeprule/abstractrules.py
+++ b/roverlay/depres/simpledeprule/abstractrules.py
@@ -107,7 +107,7 @@ class SimpleRule ( deprule.DependencyRule ):
          resolving = self.resolving_package
 
          if self.is_selfdep:
-            resolving = resolving.split ( '/', 1 ) [1]
+            resolving = resolving.rpartition ( '/' ) [2]
 
 
       if hasattr ( self.__class__, 'RULE_PREFIX' ):
@@ -132,86 +132,90 @@ class SimpleRule ( deprule.DependencyRule ):
       return '\n'.join ( self.export_rule() )
 
 
-
 class FuzzySimpleRule ( SimpleRule ):
 
+   # 0 : version-relative, 1 : name only, 2 : std
+   FUZZY_SCORE = ( 1250, 1000, 750 )
+   max_score   = max ( FUZZY_SCORE )
+
    def __init__ ( self, *args, **kw ):
-      super ( FuzzySimpleRule, self ) . __init__ ( *args, **kw )
+      super ( FuzzySimpleRule, self ).__init__ ( *args, **kw )
       self.prepare_lowercase_alias = True
+   # --- end of __init__ (...) ---
 
-      # 0 : version with modifier, 1 : version w/o mod, 2 : name only, 3 : std
-      self.fuzzy_score = ( 1250, 1000, 750, 500 )
-      self.max_score   = max ( self.fuzzy_score )
-
-   def matches ( self, dep_env ):
+   def match_prepare ( self, dep_env ):
       if self._find ( dep_env.dep_str_low, lowercase=True ):
-         # non-fuzzy match
-         self.logger.debug (
-            "matches {dep_str} with score {s} and priority {p}.".format (
-               dep_str=dep_env.dep_str, s=self.max_score, p=self.priority
-         ) )
-         return ( self.fuzzy_score[3], self.resolving_package )
-
-      elif hasattr ( dep_env, 'fuzzy' ):
-         for fuzzy in dep_env.fuzzy:
-            if 'name' in fuzzy:
-               if self._find ( fuzzy ['name'], lowercase=True ):
-                  # fuzzy match found
-
-                  if self.resolving_package is None:
-                     # ignore rule
-                     res   = None
-                     score = self.fuzzy_score [2]
-
-
-                  elif 'version' in fuzzy:
-
-                     ver_pkg = \
-                        self.resolving_package + '-' +  fuzzy ['version']
-
-                     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> )
-                           res = '( !=%s %s )' % (
-                              ver_pkg,
-                              self.resolving_package
-                           )
+         return ( 2, None )
 
-                        else:
-                           # std vmod: >=, <=, =, <, >
-                           res = vmod + ver_pkg
+      elif not hasattr ( dep_env, 'fuzzy' ):
+         return None
 
-                        score = self.fuzzy_score[0]
-
-                     else:
-                        # version required, but no modifier: defaults to '>='
-
-                        res   = '>=' + ver_pkg
-                        score = self.fuzzy_score[1]
-
-                  else:
-                     # substring match
-                     #  currently not possible (see DepEnv's regexes)
-                     score = fuzzy[2]
-                     res   = self.resolving_package
-                  # --- if resolving... elif version ... else
+      elif self.resolving_package is None:
+         # ignore rule
+         for fuzzy in dep_env.fuzzy:
+            if self._find ( fuzzy ['name'], lowercase=True ):
+               return ( 1, fuzzy )
+      else:
+         for fuzzy in dep_env.fuzzy:
+            if self._find ( fuzzy ['name'], lowercase=True ):
+               return ( 0, fuzzy )
+            # -- end if find (=match found)
+      # -- end if
+      return None
+   # --- end of match_prepare (...) ---
 
+   def log_fuzzy_match ( self, dep_env, dep, score ):
+      if dep is False:
+         return None
+      else:
+         self.logger.debug (
+            'fuzzy-match: {dep_str} resolved as '
+            '{dep!r} with score={s}'.format (
+               dep_str=dep_env.dep_str, dep=dep, s=score
+            )
+         )
+         return ( score, dep )
+   # --- end of log_fuzzy_match (...) ---
+
+   def log_standard_match ( self, dep_env, score ):
+      if dep is False:
+         return None
+      else:
+         self.logger.debug (
+            "matches {dep_str} with score {s} and priority {p}.".format (
+               dep_str=dep_env.dep_str, s=score, p=self.priority
+            )
+         )
+         return ( score, self.resolving_package )
+   # --- end of log_standard_match (...) ---
 
-                  self.logger.debug (
-                     'fuzzy-match: {dep_str} resolved as {dep!r} '
-                     'with score={s}.'.format (
-                        dep_str=dep_env.dep_str, dep=res, s=score
-                  ) )
-                  return ( score, res )
-               # --- if find (=match found)
-            # --- if name in
-         # --- for fuzzy
-      # --- elif hasattr
+   def handle_version_relative_match ( self, dep_env, fuzzy ):
+      raise NotImplementedError()
+   # --- end of handle_version_relative_match (...) ---
 
-      return None
+   def matches ( self, dep_env ):
+      partial_result = self.match_prepare ( dep_env )
+      if partial_result is None:
+         return None
+      else:
+         match_type, fuzzy = partial_result
+         score = self.FUZZY_SCORE [match_type]
+         if match_type == 0:
+            # real version-relative match
+            return self.log_fuzzy_match (
+               dep_env,
+               self.handle_version_relative_match ( dep_env, fuzzy ),
+               score
+            )
+         elif match_type == 1:
+            # name-only match (ignore rule?)
+            return self.log_fuzzy_match (
+               dep_env, self.resolving_package, score
+            )
+         else:
+            # non-fuzzy match
+            return self.log_standard_match ( dep_env, score )
+      # -- end if partial_result
    # --- end of matches (...) ---
+
+# --- end of FuzzySimpleRule ---

diff --git a/roverlay/depres/simpledeprule/rulemaker.py b/roverlay/depres/simpledeprule/rulemaker.py
index 6c3bc0e..a993341 100644
--- a/roverlay/depres/simpledeprule/rulemaker.py
+++ b/roverlay/depres/simpledeprule/rulemaker.py
@@ -23,29 +23,6 @@ from roverlay.depres.simpledeprule.abstractrules import *
 from roverlay.depres.simpledeprule.pool import SimpleDependencyRulePool
 
 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__ )
@@ -57,7 +34,9 @@ class SimpleRuleMaker ( object ):
       self.multiline_start = '{'
       self.multiline_stop  = '}'
       self.comment_char    = '#'
-      self._kw             = self.__class__.RuleKeywords()
+      self._kwmap          = rules.RuleConstructor (
+         eapi = config.get_or_fail ( 'EBUILD.eapi' )
+      )
       # deptype_kw is '#deptype' (this keyword requires comment 'mode')
       self.deptype_kw      = 'deptype'
       self._deptype        = deptype.ALL
@@ -113,26 +92,29 @@ class SimpleRuleMaker ( object ):
       #  or normal rule 'dev-lang/R :: R'
       # selfdeps are always single line statements (!)
 
-      rule_class, resolving = self._kw.lookup ( dep )
+      rule_class, resolving, kwargs = self._kwmap.lookup ( dep )
 
       if dep_str:
          # normal rule
          new_rule = rule_class (
             resolving_package=resolving,
             dep_str=dep_str,
-            is_selfdep=False
+            is_selfdep=False,
+            **kwargs
          )
 
       elif resolving is not None:
          # selfdep
          dep_str   = resolving
-         resolving = \
+         resolving = (
             config.get_or_fail ( 'OVERLAY.category' ) + '/' + resolving
+         )
 
          new_rule = rule_class (
             resolving_package=resolving,
             dep_str=dep_str,
-            is_selfdep=True
+            is_selfdep=True,
+            **kwargs
          )
       else:
          return False
@@ -175,11 +157,11 @@ class SimpleRuleMaker ( object ):
 
       elif len ( line ) > 1 and line [-1] == self.multiline_start:
          l = line [:-1].rstrip()
-         rule_class, resolving = self._kw.lookup ( l )
+         rule_class, resolving, kwargs = self._kwmap.lookup ( l )
 
          self._next = (
             self._deptype,
-            rule_class ( resolving_package=resolving )
+            rule_class ( resolving_package=resolving, **kwargs ),
          )
          return True
 

diff --git a/roverlay/depres/simpledeprule/rules.py b/roverlay/depres/simpledeprule/rules.py
index 6f006e6..db208d4 100644
--- a/roverlay/depres/simpledeprule/rules.py
+++ b/roverlay/depres/simpledeprule/rules.py
@@ -23,16 +23,85 @@ __all__ = (
 from roverlay.depres.simpledeprule.abstractrules import \
    SimpleRule, FuzzySimpleRule
 
-def get_rule_map():
-   kwmap = { c.RULE_PREFIX : c for c in (
-      SimpleIgnoreDependencyRule,
-      SimpleFuzzyDependencyRule,
-      SimpleFuzzyIgnoreDependencyRule
-   ) }
+class RuleConstructor ( object ):
 
-   return ( SimpleDependencyRule, kwmap )
-# --- end of get_rule_map (...) ---
+   def __init__ ( self, eapi ):
+      self.eapi = eapi
 
+      self.kw_ignore       = SimpleIgnoreDependencyRule.RULE_PREFIX
+      self.kw_fuzzy        = SimpleFuzzyDependencyRule.RULE_PREFIX
+      self.kw_fuzzy_ignore = SimpleFuzzyIgnoreDependencyRule.RULE_PREFIX
+   # --- end of __init__ (...) ---
+
+   def lookup ( self, keyworded_str ):
+      get_kwless = lambda : keyworded_str[1:].lstrip() or None
+
+      kw = keyworded_str[0]
+      if kw == self.kw_ignore:
+         return ( SimpleIgnoreDependencyRule, get_kwless(), {} )
+      elif kw == self.kw_fuzzy_ignore:
+         return ( SimpleFuzzyIgnoreDependencyRule, get_kwless(), {} )
+      elif kw == self.kw_fuzzy:
+         ##TODO
+         ## > "default"
+         ## > "slot only"
+         ## > "combined"
+   ## syntax
+   ## ~cat/pkg:<slot suffix>
+   ## ~cat/pkg:/<slot suffix>
+   ## ~cat/pkg:{major}/{minor}<slot suffix>
+   ##
+         kwless = get_kwless()
+         resolving, sepa, remainder = kwless.partition ( ':' )
+
+         if sepa:
+            # fuzzy slot rule
+            kwargs = { 'resolving_package_name' : resolving, }
+            slot_head, slot_sepa, slot_rem = remainder.partition ( ':' )
+
+            if slot_sepa:
+               # slot restriction
+               istart, isepa, istop = slot_head.partition ( '..' )
+               if isepa:
+                  kwargs ['slot_restrict'] = frozenset (
+                     range ( int ( istart or 0 ), int ( istop or 100 ) + 1 )
+                  )
+               else:
+                  kwargs ['slot_restrict'] = frozenset (
+                     int ( k ) for k in slot_head.split ( ',' )
+                  )
+
+               remainder = slot_rem
+            else:
+               remainder = slot_head
+            # -- end if;
+
+
+            if not remainder:
+               # <cat>/<pkg>:
+               kwargs ['slot_suffix'] = sepa + '{slot}'
+
+            elif remainder[0] in { '/', '*', '=' }:
+               # subslot, "any slot" operators
+               assert self.eapi >= 5
+               kwargs ['slot_suffix'] = sepa + '{slot}' + remainder
+            else:
+               kwargs ['slot_suffix'] = sepa + remainder
+
+
+            # verify that slot_suffix can be formatted properly
+##            if kwargs ['slot_suffix'] [0] != ':':
+##               kwargs ['slot_suffix'] = ':' + kwargs ['slot_suffix']
+
+            DONT_CARE = kwargs ['slot_suffix'].format ( slot='_', version='_' )
+            return ( SimpleFuzzySlotDependencyRule, resolving, kwargs )
+         else:
+            return ( SimpleFuzzyDependencyRule, kwless, {} )
+      else:
+         return ( SimpleDependencyRule, keyworded_str, {} )
+   # --- end of lookup (...) ---
+
+# --- end of RuleConstructor ---
 
 class SimpleIgnoreDependencyRule ( SimpleRule ):
 
@@ -90,14 +159,119 @@ class SimpleFuzzyIgnoreDependencyRule ( FuzzySimpleRule ):
       else:
          return super ( self.__class__, self ) . __str__()
 
+   def handle_version_relative_match ( self, *args, **kwargs ):
+      raise Exception ( "should-be unreachable code" )
+   # --- end of handle_version_relative_match (...) ---
+
+# --- end of SimpleFuzzyIgnoreDependencyRule ---
+
+
 class SimpleFuzzyDependencyRule ( FuzzySimpleRule ):
 
    RULE_PREFIX = '~'
 
-   def __init__ ( self, priority=71, resolving_package=None, **kw ):
+   def __init__ ( self, priority=72, resolving_package=None, **kw ):
       super ( SimpleFuzzyDependencyRule, self ) . __init__ (
          priority=priority,
          resolving_package=resolving_package,
          logger_name = 'FUZZY.' + resolving_package,
          **kw
       )
+   # --- end of __init__ (...) ---
+
+   def handle_version_relative_match ( self, dep_env, fuzzy ):
+      ver_pkg  = self.resolving_package + '-' + fuzzy ['version']
+      vmod_str = fuzzy ['version_modifier']
+      vmod     = fuzzy ['vmod']
+
+      #if vmod & dep_env.VMOD_NOT:
+      if vmod == dep_env.VMOD_NE:
+         # package matches, but specific version is forbidden
+         # ( !<package>-<specific verion> <package> )
+         return "( !={vres} {res} )".format (
+            vres=ver_pkg, res=self.resolving_package
+         )
+      else:
+         # std vmod: >=, <=, =, <, >
+         return vmod_str + ver_pkg
+   # --- end of handle_version_relative_match (...) ---
+
+# --- end of SimpleFuzzyDependencyRule ---
+
+
+class SimpleFuzzySlotDependencyRule ( FuzzySimpleRule ):
+   # 2 slot variants
+   # "slot only": resolve dep_str as <cat>/<pkg>:<slot>
+   # "combined": resolve dep_str as <vmod><cat>/<pkg>-<ver>:<slot>
+
+#   FMT_DICT = {
+#      'slot' : '{slot}',
+#   }
+
+   #RULE_PREFIX = '~'
+   RULE_PREFIX = SimpleFuzzyDependencyRule.RULE_PREFIX
+
+   def __init__ ( self,
+      priority               = 71,
+      resolving_package      = None,
+      resolving_package_name = None,
+      slot_suffix            = None,
+      slot_restrict          = None,
+      **kw
+   ):
+      super ( SimpleFuzzySlotDependencyRule, self ) . __init__ (
+         priority=priority,
+         resolving_package = resolving_package,
+         logger_name       = 'FUZZY_SLOT.' + (
+            resolving_package_name if resolving_package_name is not None
+            else resolving_package.partition ( ':' )[0]
+         ),
+         **kw
+      )
+
+      self.slot_suffix = slot_suffix
+
+      if slot_restrict:
+         self.slot_restrict = frozenset ( int ( k ) for k in slot_restrict )
+      else:
+         self.slot_restrict = None
+   # --- end of __init__ (...) ---
+
+   def __str__ ( self ):
+      # FIXME/TODO
+      return 'TODO! {low}..{high} {s}'.format (
+         low  = ( min ( self.slot_restrict ) if self.slot_restrict else 'X' ),
+         high = ( max ( self.slot_restrict ) if self.slot_restrict else 'X' ),
+         s    = ( super ( SimpleFuzzySlotDependencyRule, self ).__str__() ),
+      )
+   # --- end of __str__ (...) ---
+
+   def handle_version_relative_match ( self, dep_env, fuzzy ):
+      res  = False
+      vmod = fuzzy ['vmod']
+
+      if not ( vmod & dep_env.VMOD_NOT ):
+         # can be resolved as slot(ted) dep
+
+         ver_str = fuzzy ['version']
+         v_major, sepa, v_remainder = ver_str.partition ( '.' )
+         try:
+            slot = int ( v_major )
+
+            # resolve '<' and '>' by decrementing/incrementing slot
+            if vmod == dep_env.VMOD_LT:
+               slot -= 1
+            elif vmod == dep_env.VMOD_GT:
+               slot += 1
+
+            if not self.slot_restrict or slot in self.slot_restrict:
+               res = self.resolving_package + self.slot_suffix.format (
+                  slot=slot, version=ver_str,
+                  #vmod=fuzzy ['version_modifier']
+               )
+         except ValueError:
+            pass
+      # -- end if vmod
+
+      return res
+   # --- end of handle_version_relative_match (...) ---


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [gentoo-commits] proj/R_overlay:gsoc13/next commit in: roverlay/depres/simpledeprule/, roverlay/depres/
@ 2013-07-02 21:09 André Erdmann
  0 siblings, 0 replies; 4+ messages in thread
From: André Erdmann @ 2013-07-02 21:09 UTC (permalink / raw
  To: gentoo-commits

commit:     bd91581d7a6cc12e2cfe9aa45a69ac5cdfdc6f67
Author:     André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Tue Jul  2 20:58:50 2013 +0000
Commit:     André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Tue Jul  2 20:58:50 2013 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=bd91581d

roverlay/depres: configurable slot values

This commit (mainly) adds feature to FuzzySlotDependencyRule
* the relevant parts of a version string that make up the slot or subslot value
  are configurable now
* slot rule modes: "open", "with version", "default"
* slot range restrict has been removed

---
 roverlay/depres/depenv.py              |  16 ++
 roverlay/depres/simpledeprule/rules.py | 339 +++++++++++++++++----------------
 roverlay/depres/simpledeprule/util.py  | 160 ++++++++++++++++
 3 files changed, 350 insertions(+), 165 deletions(-)

diff --git a/roverlay/depres/depenv.py b/roverlay/depres/depenv.py
index 9371ef6..c298447 100644
--- a/roverlay/depres/depenv.py
+++ b/roverlay/depres/depenv.py
@@ -175,10 +175,26 @@ class DepEnv ( object ):
                # "normalize"
                vmod = '='
 
+            version_strlist = version.split ( '.' )
+            version_iparts  = list()
+
+            for v in version_strlist:
+               #i = None
+               try:
+                  i = int ( v )
+                  version_iparts.append ( i )
+               except ValueError:
+                  v2 = v.partition ( '_' )[0].partition ( '-' ) [0]
+                  version_iparts.append ( int ( v2 ) if v2 else 0 )
+
+
+
             result.append ( dict (
                name             = m.group ( 'name' ),
                version_modifier = vmod,
                version          = version,
+               version_strlist  = version_strlist,
+               version_tuple    = tuple ( version_iparts ),
                vmod             = self.VMOD.get ( vmod, self.VMOD_UNDEF ),
             ) )
 

diff --git a/roverlay/depres/simpledeprule/rules.py b/roverlay/depres/simpledeprule/rules.py
index ac3fa89..999a8b4 100644
--- a/roverlay/depres/simpledeprule/rules.py
+++ b/roverlay/depres/simpledeprule/rules.py
@@ -20,88 +20,15 @@ __all__ = (
    'SimpleFuzzyDependencyRule', 'SimpleFuzzyIgnoreDependencyRule'
 )
 
-from roverlay.depres.simpledeprule.abstractrules import \
-   SimpleRule, FuzzySimpleRule
-
-class SlotRestrict ( object ):
-   def accepts ( self, k ):
-      """Returns True if k is allowed, else False.
 
-      arguments:
-      * k -- int
-      """
-      return True
+from roverlay.depres.simpledeprule.util import \
+   RuleFileSyntaxError, get_slot_restrict, get_slot_parser
 
-   def __bool__ ( self ):
-      return True
-
-   def noexport ( self ):
-      pass
-
-   def __str__ ( self ):
-      return ':'
-# --- end of SlotRestrict ---
-
-class SlotRangeRestrict ( SlotRestrict ):
-   DEFAULT_LOW  = 0
-   DEFAULT_HIGH = 1000
-
-   def __init__ ( self, low, high ):
-      super ( SlotRangeRestrict, self ).__init__()
-      if low:
-         self.low = int ( low )
-      else:
-         self.low = self.DEFAULT_LOW
-         self._implicit_low = True
-
-      if high:
-         self.high = int ( high )
-      else:
-         self.high = self.DEFAULT_HIGH
-         self._implicit_high = True
-   # --- end of __init__ (...) ---
-
-   def noexport ( self ):
-      if hasattr ( self, '_implicit_low' ):
-         del self._implicit_low
-      if hasattr ( self, '_implicit_high' ):
-         del self._implicit_high
-   # --- end of noexport (...) ---
-
-   def accepts ( self, k ):
-      """Returns True if k is allowed, else False.
-
-      arguments:
-      * k -- int
-      """
-      return k >= self.low and k <= self.high
-
-   def __str__ ( self ):
-      return ":{low}..{high}".format (
-         low  = ( '' if hasattr ( self, '_implicit_low'  ) else self.low  ),
-         high = ( '' if hasattr ( self, '_implicit_high' ) else self.high ),
-      )
-   # --- end of __str__ (...) ---
-
-# --- end of SlotRangeRestrict ---
-
-class SlotSetRestrict ( SlotRestrict ):
-   def __init__ ( self, iterable ):
-      self._iset = frozenset ( int ( k ) for k in iterable )
-
-   def accepts ( self, k ):
-      """Returns True if k is allowed, else False.
+from roverlay.depres.simpledeprule.abstractrules import \
+   SimpleRule, FuzzySimpleRule
 
-      arguments:
-      * k -- int
-      """
-      return k in self._iset
 
-   def __str__ ( self ):
-      return ':' + ','.join ( str ( k ) for k in sorted ( self._iset ) )
-   # --- end of __str__ (...) ---
 
-# --- end of SlotSetRestrict ---
 
 class RuleConstructor ( object ):
 
@@ -123,61 +50,85 @@ class RuleConstructor ( object ):
          return ( SimpleFuzzyIgnoreDependencyRule, get_kwless(), {} )
       elif kw == self.kw_fuzzy:
          ## syntax
-         ## ~cat/pkg:<slot range>:<slot suffix>
-         kwless = get_kwless()
-         resolving, sepa, remainder = kwless.partition ( ':' )
-
-         if sepa:
-            # fuzzy slot rule
+         ## ~<cat>/<pkg>[:[<slot option>]]*
+         ##  where slot option is any of
+         ##  * slot restrict (range, list)
+         ##  * "with version", "open" ("*" and "=" slot operators)
+         ##  * relevant version parts ("1.2.3.4" => "1" if 1, "1.2" if 2, ...)
+         ##  * relevant subslot version parts ("1.2.3.4" => <SLOT>/<SUBSLOT?>)
+         ##  * slot operator ("=")
+
+         kwless          = get_kwless()
+         line_components = kwless.split ( ':' )
+
+         if len ( line_components ) < 2:
+            # non-slot fuzzy rule
+            return ( SimpleFuzzyDependencyRule, kwless, {} )
+         else:
             kwargs = dict()
-            slot_head, slot_sepa, slot_rem = remainder.partition ( ':' )
-
-            if slot_sepa:
-               # int range restriction
-               istart, isepa, istop = slot_head.partition ( '..' )
-               if isepa:
-                  kwargs ['slot_restrict'] = SlotRangeRestrict (
-                     low=istart, high=istop
-                  )
-               else:
-                  # int list restriction
+            lc_iter = iter ( line_components )
+            # drop first item as it's the resolving string and not an option
+            next ( lc_iter )
+            for opt_str in lc_iter:
+               opt, has_value, value = opt_str.partition ( '=' )
 
-                  # "filter(None,...)" filters 0 but not '0'
-                  istr_list = list (
-                     filter ( None, slot_head.split ( ',' ) )
-                     #filter ( lambda s : s or s == 0, slot_head.split ( ',' ) )
-                  )
+               if not opt_str:
+                  # empty
+                  pass
+               elif opt == 'default':
+                  kwargs ['slot_mode'] = 0
 
-                  if istr_list:
-                     kwargs ['slot_restrict'] = SlotSetRestrict ( istr_list )
+               elif opt == 'with_version' or opt == '+v':
+                  kwargs ['slot_mode'] = 1
 
-               remainder = slot_rem
-            else:
-               #kwargs ['slot_restrict'] = SlotRestrict()
-               remainder = slot_head
-            # -- end if;
-
-            if remainder[:2] == '+v':
-               kwargs ['with_version'] = True
-               remainder = remainder[2:]
-            # -- end if;
-
-            if not remainder:
-               pass
-            elif remainder[0] in { '/', '*', '=' }:
-               # subslot, "any slot" operators
-               # (subslots don't seem to make much sense here)
-
-               ##if self.eapi < 5: raise ...
-               kwargs ['slot_suffix'] = remainder
+               elif opt == 'open':
+                  kwargs ['slot_mode'] = 2
+
+               elif ( opt == 'restrict' or opt == 'r' ) and value:
+                  kwargs ['slot_restrict'] = get_slot_restrict ( value )
+
+               elif ( opt == 'slotparts' or opt == 's' ) and value:
+                  kwargs ['slotparts'] = get_slot_parser ( value )
+
+               elif ( opt == 'subslotparts' or opt == '/' ) and value:
+                  kwargs ['subslotparts'] = get_slot_parser ( value )
+
+               elif opt_str[0] == '/' and not has_value:
+                  kwargs ['subslotparts'] = get_slot_parser ( opt_str[1:] )
+
+#               elif opt == 'operator' and value:
+#                  # unsafe, could be used to inject "$(rm -rf /)" etc.
+#                  kwargs ['slot_operator'] = value
+
+               elif opt == '*':
+                  kwargs ['slot_operator'] = '*'
+
+               elif not opt and has_value:
+                  # "="
+                  kwargs ['slot_operator'] = '='
+                  pass
+
+               else:
+                  raise RuleFileSyntaxError (
+                     "cannot parse option {!r} from {!r}".format (
+                        opt_str, kwless
+                     )
+                  )
+            # -- end for lc_iter
+
+            if (
+               kwargs.get ( 'slot_operator' ) == '*'
+               and kwargs.get ( 'slot_mode' ) != 2
+            ):
+               raise RuleFileSyntaxError (
+                  "The '*' slot operator needs an 'open' rule."
+               )
             else:
-               raise Exception (
-                  "unknown slot rule remainder {!r}".format ( remainder )
+               return (
+                  SimpleFuzzySlotDependencyRule, line_components[0], kwargs
                )
+         # -- end if line_components
 
-            return ( SimpleFuzzySlotDependencyRule, resolving, kwargs )
-         else:
-            return ( SimpleFuzzyDependencyRule, kwless, {} )
       else:
          return ( SimpleDependencyRule, keyworded_str, {} )
    # --- end of lookup (...) ---
@@ -295,9 +246,11 @@ class SimpleFuzzySlotDependencyRule ( FuzzySimpleRule ):
    def __init__ ( self,
       priority          = 71,
       resolving_package = None,
-      slot_suffix       = None,
+      slot_mode         = None,
       slot_restrict     = None,
-      with_version      = False,
+      slotparts         = None,
+      subslotparts      = None,
+      slot_operator     = None,
       **kw
    ):
       super ( SimpleFuzzySlotDependencyRule, self ) . __init__ (
@@ -307,39 +260,93 @@ class SimpleFuzzySlotDependencyRule ( FuzzySimpleRule ):
          **kw
       )
 
-      self.slot_suffix   = slot_suffix
+      self.mode          = 0 if slot_mode is None else slot_mode
       self.slot_restrict = slot_restrict
-
-      if with_version:
+      self.slot_operator = slot_operator
+      self.slotparts     = get_slot_parser ("0") if slotparts is None else slotparts
+      self.subslotparts  = subslotparts
+
+      if self.mode == 0:
+         # "default"
+         self._resolving_fmt = self.resolving_package + ':{slot}'
+         if self.slot_operator:
+            self._resolving_fmt += self.slot_operator
+
+      elif self.mode == 1:
+         # "with version"
          self._resolving_fmt = (
             '{vmod}' + self.resolving_package + '-{version}:{slot}'
-            + ( slot_suffix or '' )
          )
-         self.with_version = True
+         if self.slot_operator:
+            self._resolving_fmt += self.slot_operator
+
+      elif self.mode == 2:
+         # "open" slot
+         if not self.slot_operator:
+            self.slot_operator = '='
+
+         del self.slot_restrict
+
+         self._orig_resolving_package = self.resolving_package
+         self.resolving_package += ':' + self.slot_operator
       else:
-         self._resolving_fmt = (
-            self.resolving_package + ':{slot}' + ( slot_suffix or '' )
+         raise Exception (
+            "unknown fuzzy slot rule mode {}".format ( self.mode )
          )
-         self.with_version = False
+
+
 
       if self.is_selfdep:
          raise NotImplementedError ( "fuzzy slot rule must not be a selfdep." )
    # --- end of __init__ (...) ---
 
    def noexport ( self ):
-      del self.slot_suffix
-      del self.with_version
+      del self.slot_operator
+      del self.mode
       if self.slot_restrict:
          self.slot_restrict.noexport()
    # --- end of noexport (...) ---
 
    def get_resolving_str ( self ):
-      return "{prefix}{resolv}{restrict}:{flags}{slot}".format (
-         prefix   = self.RULE_PREFIX,
-         resolv   = self.resolving_package,
-         restrict = ( self.slot_restrict or '' ),
-         flags    = ( '+v' if self.with_version else '' ),
-         slot     = ( self.slot_suffix or '' ),
+      ## syntax
+      ## ~<cat>/<pkg>[:[<slot option>]]*
+      ##  where slot option is any of
+      ##  * slot restrict (range, list)
+      ##  * "with version", "open" ("*" and "=" slot operators)
+      ##  * relevant version parts ("1.2.3.4" => "1" if 1, "1.2" if 2, ...)
+      ##  * relevant subslot version parts ("1.2.3.4" => <SLOT>/<SUBSLOT?>)
+      ##  * slot operator ("=")
+
+      def gen_opts():
+         if self.mode == 2:
+            yield "open"
+         else:
+            if self.mode == 1:
+               yield "with_version"
+
+            if self.slot_restrict:
+               yield "restrict=" + str ( self.slot_restrict )
+
+            if self.slotparts and (
+               not hasattr ( self.slotparts, '_index' )
+               or  self.slotparts._index != 0
+            ):
+               yield "s=" + str ( self.slotparts )
+
+            if self.subslotparts:
+               yield "/" + str ( self.subslotparts )
+         # -- end if
+         if self.slot_operator:
+            yield self.slot_operator
+
+      return "{prefix}{resolv}:{opts}".format (
+         prefix = self.RULE_PREFIX,
+         resolv = (
+            self._orig_resolving_package
+            if hasattr ( self, '_orig_resolving_package' )
+            else self.resolving_package,
+         ),
+         opts   = ':'.join ( gen_opts() )
       )
    # --- end of get_resolving_str (...) ---
 
@@ -350,28 +357,30 @@ class SimpleFuzzySlotDependencyRule ( FuzzySimpleRule ):
       if not ( vmod & dep_env.VMOD_NOT ):
          # can be resolved as slot(ted) dep
 
-         ver_str = fuzzy ['version']
-         v_major, sepa, v_remainder = ver_str.partition ( '.' )
-         try:
-            # TODO/FIXME: slot != int(v_major);
-            #  example: sci-libs/fftw where slots are K.J (2.1, 3.0)
-            slot = int ( v_major )
-
-            # resolve '<' and '>' by decrementing/incrementing slot
-            if vmod == dep_env.VMOD_LT:
-               slot -= 1
-            elif vmod == dep_env.VMOD_GT:
-               slot += 1
-
-            if not self.slot_restrict or self.slot_restrict.accepts ( slot ):
-               res = self._resolving_fmt.format (
-                  slot=slot,
-                  version=ver_str,
-                  vmod=fuzzy ['version_modifier'],
-               )
-         except ValueError:
-            pass
-      # -- end if vmod
+         if self.mode == 2:
+            res = self._resolving_str
+         elif vmod & dep_env.VMOD_EQ:
+            slot_str = None
+            slot     = self.slotparts.get_slot ( fuzzy )
+
+            if slot is not None:
+               if self.subslotparts:
+                  subslot = self.subslotparts.get_slot ( fuzzy )
+                  if subslot is not None:
+                     slot_str = slot + '/' + subslot
+               else:
+                  slot_str = slot
+
+               if slot_str and (
+                  not self.slot_restrict
+                  or self.slot_restrict.accepts ( slot )
+               ):
+                  res = self._resolving_fmt.format (
+                     slot=slot_str,
+                     version=fuzzy['version'], vmod=fuzzy['version_modifier']
+                  )
+
+      # -- end if vmod != NOT
 
       return res
    # --- end of handle_version_relative_match (...) ---

diff --git a/roverlay/depres/simpledeprule/util.py b/roverlay/depres/simpledeprule/util.py
new file mode 100644
index 0000000..0a8311c
--- /dev/null
+++ b/roverlay/depres/simpledeprule/util.py
@@ -0,0 +1,160 @@
+# R overlay -- simple dependency rules
+# -*- 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.
+
+
+class RuleFileSyntaxError ( Exception ):
+   pass
+
+
+def get_int_range_or_list (
+   value_str, default_low=0, default_high=1000, list_sepa=','
+):
+   low, sepa, high = value_str.partition ( '..' )
+   if sepa:
+      i_low  = int ( low ) if low else default_low
+      i_high = (
+         int ( high ) if high else (
+            i_low if default_high is True else default_high
+         )
+      )
+      return ( True, i_low, i_high )
+   else:
+      return ( False,
+         tuple ( int ( k ) for k in value_str.split ( list_sepa ) )
+      )
+# --- end get_int_range_or_list (...) ---
+
+
+
+class SlotRestrict ( object ):
+   def accepts ( self, k ):
+      """Returns True if k is allowed, else False.
+
+      arguments:
+      * k -- int
+      """
+      return True
+
+   def __bool__ ( self ):
+      return True
+
+   def noexport ( self ):
+      pass
+
+   def __str__ ( self ):
+      return ''
+# --- end of SlotRestrict ---
+
+class SlotSetRestrict ( SlotRestrict ):
+   def __init__ ( self, iterable ):
+      self._slotset = frozenset ( iterable )
+
+   def accepts ( self, k ):
+      """Returns True if k is allowed, else False.
+
+      arguments:
+      * k -- slot (str)
+      """
+      return k in self._slotset
+
+   def __str__ ( self ):
+      return ','.join ( sorted ( self._slotset ) )
+   # --- end of __str__ (...) ---
+
+# --- end of SlotSetRestrict ---
+
+class SlotValueCreatorBase ( object ):
+
+   def get_slot ( self, *args, **kwargs ):
+      raise NotImplementedError()
+   # --- end of get_slot (...) ---
+
+   def __str__ ( self ):
+      raise NotImplementedError()
+   # --- end of __str__ (...) ---
+
+
+class ImmediateSlotValueCreator ( SlotValueCreatorBase ):
+   def __init__ ( self, v_str ):
+      super ( ImmediateSlotValueCreator, self ).__init__()
+      self._value = v_str
+   # --- end of __init__ (...) ---
+
+   def get_slot ( self, *args, **kwargs ):
+      return self._value
+   # --- end of get_slot (...) ---
+
+   def __str__ ( self ):
+      return "i" + self._value
+
+class SingleIndexValueCreator ( SlotValueCreatorBase ):
+   def __init__ ( self, index ):
+      super ( SingleIndexValueCreator, self ).__init__()
+      self._index = index
+   # --- end of __init__ (...) ---
+
+   def get_slot ( self, fuzzy ):
+      version_components = fuzzy ['version_strlist']
+      if len ( version_components ) > self._index:
+         return version_components [self._index]
+      else:
+         return None
+   # --- end of get_slot (...) ---
+
+   def __str__ ( self ):
+      return str ( self._index )
+
+
+class IndexRangeSlotValueCreator ( SlotValueCreatorBase ):
+   def __init__ ( self, low, high ):
+      super ( IndexRangeSlotValueCreator, self ).__init__()
+      self._low  = low
+      self._high = high + 1 if high >= 0 else high
+
+   def get_slot ( self, fuzzy ):
+      # if self._low > self._high
+      # if self._high < 0: -- dont care
+      version_components = fuzzy ['version_strlist']
+      if len ( version_components ) >= self._high:
+         return '.'.join ( version_components [self._low:self._high] )
+      else:
+         return None
+   # --- end of get_slot (...) ---
+
+   def __str__ ( self ):
+      return str ( self._low ) + '..' + str (
+         ( self._high - 1 ) if self._high > 0 else self._high
+      )
+
+
+def get_slot_parser ( vstr ):
+   if vstr [0] == 'i':
+      # "immediate" value
+      s = vstr [1:]
+      return ImmediateSlotValueCreator ( v_str=s )
+   else:
+      range_or_list = get_int_range_or_list ( vstr, default_high=True )
+      if range_or_list [0]:
+         if range_or_list[1] == range_or_list[2]:
+            return SingleIndexValueCreator ( index=range_or_list[1] )
+         else:
+            return IndexRangeSlotValueCreator (
+               low=range_or_list[1], high=range_or_list[2]
+            )
+      elif len ( range_or_list[1] ) < 2:
+         return SingleIndexValueCreator ( index=range_or_list[1][0] )
+      else:
+         raise RuleFileSyntaxError (
+            "slot part selection must not be a list"
+         )
+# --- end of get_slot_parser (...) ---
+
+def get_slot_restrict ( vstr ):
+   if vstr:
+      return SlotSetRestrict ( vstr.split ( ',' ) )
+   else:
+      return None
+# --- end of get_slot_restrict (...) --


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [gentoo-commits] proj/R_overlay:master commit in: roverlay/depres/simpledeprule/, roverlay/depres/
@ 2013-07-03 10:05 André Erdmann
  2013-06-28  6:19 ` [gentoo-commits] proj/R_overlay:gsoc13/next " André Erdmann
  0 siblings, 1 reply; 4+ messages in thread
From: André Erdmann @ 2013-07-03 10:05 UTC (permalink / raw
  To: gentoo-commits

commit:     72af9d204837cbabf32c43ffcc50ebec93549f7f
Author:     André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Fri Jun 28 06:19:14 2013 +0000
Commit:     André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Fri Jun 28 06:19:14 2013 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=72af9d20

roverlay/depres: add SLOT handling to fuzzy depres

---
 roverlay/depres/depenv.py                      |  32 ++++-
 roverlay/depres/deprule.py                     |   2 +
 roverlay/depres/simpledeprule/abstractrules.py | 148 +++++++++----------
 roverlay/depres/simpledeprule/rulemaker.py     |  42 ++----
 roverlay/depres/simpledeprule/rules.py         | 192 +++++++++++++++++++++++--
 5 files changed, 303 insertions(+), 113 deletions(-)

diff --git a/roverlay/depres/depenv.py b/roverlay/depres/depenv.py
index 3021728..9371ef6 100644
--- a/roverlay/depres/depenv.py
+++ b/roverlay/depres/depenv.py
@@ -62,6 +62,27 @@ class DepEnv ( object ):
    # { <, >, ==, <=, >=, =, != }
    _VERMOD = '(?P<vmod>[<>]|[=<>!]?[=])'
 
+   # integer representation of version modifiers
+   VMOD_NONE  = 0
+   VMOD_UNDEF = 1
+   VMOD_NOT   = 2
+   VMOD_EQ    = 4
+   VMOD_NE    = VMOD_NOT | VMOD_EQ
+   VMOD_GT    = 8
+   VMOD_GE    = VMOD_EQ | VMOD_GT
+   VMOD_LT    = 16
+   VMOD_LE    = VMOD_EQ | VMOD_LT
+
+   VMOD = {
+      '!=' : VMOD_NE,
+      '='  : VMOD_EQ,
+      #'==' : VMOD_EQ, # normalized by _depslit()
+      '>'  : VMOD_GT,
+      '>=' : VMOD_GE,
+      '<'  : VMOD_LT,
+      '<=' : VMOD_LE,
+   }
+
    # name/version regexes used for fuzzy dep rules
    VERSION_REGEX = frozenset (
       re.compile ( r ) for r in ((
@@ -146,12 +167,19 @@ class DepEnv ( object ):
             if version [0] == '.': version = '0' + version
 
             vmod = m.group ( 'vmod' )
-            if vmod == '==' : vmod = '='
+
+            if not vmod:
+               # version required, but no modifier: set vmod to '>='
+               vmod = '>='
+            elif vmod == '==':
+               # "normalize"
+               vmod = '='
 
             result.append ( dict (
                name             = m.group ( 'name' ),
                version_modifier = vmod,
-               version          = version
+               version          = version,
+               vmod             = self.VMOD.get ( vmod, self.VMOD_UNDEF ),
             ) )
 
             if not self.try_all_regexes: break

diff --git a/roverlay/depres/deprule.py b/roverlay/depres/deprule.py
index b440d36..46c710d 100644
--- a/roverlay/depres/deprule.py
+++ b/roverlay/depres/deprule.py
@@ -19,6 +19,7 @@ class DependencyRule ( object ):
       arguments:
       * priority -- used for sorting rule pools, lower means more important
       """
+      super ( DependencyRule, self ).__init__()
       self.max_score = 1000
       self.priority  = priority
    # --- end of __init__ (...) ---
@@ -42,6 +43,7 @@ class DependencyRulePool ( object ):
       * name -- name of this rule pool
       * priority -- priority of this pool (lower is better)
       """
+      super ( DependencyRulePool, self ).__init__()
       if initial_rules is None:
          self.rules = list()
       else:

diff --git a/roverlay/depres/simpledeprule/abstractrules.py b/roverlay/depres/simpledeprule/abstractrules.py
index 1025b01..85c365d 100644
--- a/roverlay/depres/simpledeprule/abstractrules.py
+++ b/roverlay/depres/simpledeprule/abstractrules.py
@@ -107,7 +107,7 @@ class SimpleRule ( deprule.DependencyRule ):
          resolving = self.resolving_package
 
          if self.is_selfdep:
-            resolving = resolving.split ( '/', 1 ) [1]
+            resolving = resolving.rpartition ( '/' ) [2]
 
 
       if hasattr ( self.__class__, 'RULE_PREFIX' ):
@@ -132,86 +132,90 @@ class SimpleRule ( deprule.DependencyRule ):
       return '\n'.join ( self.export_rule() )
 
 
-
 class FuzzySimpleRule ( SimpleRule ):
 
+   # 0 : version-relative, 1 : name only, 2 : std
+   FUZZY_SCORE = ( 1250, 1000, 750 )
+   max_score   = max ( FUZZY_SCORE )
+
    def __init__ ( self, *args, **kw ):
-      super ( FuzzySimpleRule, self ) . __init__ ( *args, **kw )
+      super ( FuzzySimpleRule, self ).__init__ ( *args, **kw )
       self.prepare_lowercase_alias = True
+   # --- end of __init__ (...) ---
 
-      # 0 : version with modifier, 1 : version w/o mod, 2 : name only, 3 : std
-      self.fuzzy_score = ( 1250, 1000, 750, 500 )
-      self.max_score   = max ( self.fuzzy_score )
-
-   def matches ( self, dep_env ):
+   def match_prepare ( self, dep_env ):
       if self._find ( dep_env.dep_str_low, lowercase=True ):
-         # non-fuzzy match
-         self.logger.debug (
-            "matches {dep_str} with score {s} and priority {p}.".format (
-               dep_str=dep_env.dep_str, s=self.max_score, p=self.priority
-         ) )
-         return ( self.fuzzy_score[3], self.resolving_package )
-
-      elif hasattr ( dep_env, 'fuzzy' ):
-         for fuzzy in dep_env.fuzzy:
-            if 'name' in fuzzy:
-               if self._find ( fuzzy ['name'], lowercase=True ):
-                  # fuzzy match found
-
-                  if self.resolving_package is None:
-                     # ignore rule
-                     res   = None
-                     score = self.fuzzy_score [2]
-
-
-                  elif 'version' in fuzzy:
-
-                     ver_pkg = \
-                        self.resolving_package + '-' +  fuzzy ['version']
-
-                     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> )
-                           res = '( !=%s %s )' % (
-                              ver_pkg,
-                              self.resolving_package
-                           )
+         return ( 2, None )
 
-                        else:
-                           # std vmod: >=, <=, =, <, >
-                           res = vmod + ver_pkg
+      elif not hasattr ( dep_env, 'fuzzy' ):
+         return None
 
-                        score = self.fuzzy_score[0]
-
-                     else:
-                        # version required, but no modifier: defaults to '>='
-
-                        res   = '>=' + ver_pkg
-                        score = self.fuzzy_score[1]
-
-                  else:
-                     # substring match
-                     #  currently not possible (see DepEnv's regexes)
-                     score = fuzzy[2]
-                     res   = self.resolving_package
-                  # --- if resolving... elif version ... else
+      elif self.resolving_package is None:
+         # ignore rule
+         for fuzzy in dep_env.fuzzy:
+            if self._find ( fuzzy ['name'], lowercase=True ):
+               return ( 1, fuzzy )
+      else:
+         for fuzzy in dep_env.fuzzy:
+            if self._find ( fuzzy ['name'], lowercase=True ):
+               return ( 0, fuzzy )
+            # -- end if find (=match found)
+      # -- end if
+      return None
+   # --- end of match_prepare (...) ---
 
+   def log_fuzzy_match ( self, dep_env, dep, score ):
+      if dep is False:
+         return None
+      else:
+         self.logger.debug (
+            'fuzzy-match: {dep_str} resolved as '
+            '{dep!r} with score={s}'.format (
+               dep_str=dep_env.dep_str, dep=dep, s=score
+            )
+         )
+         return ( score, dep )
+   # --- end of log_fuzzy_match (...) ---
+
+   def log_standard_match ( self, dep_env, score ):
+      if dep is False:
+         return None
+      else:
+         self.logger.debug (
+            "matches {dep_str} with score {s} and priority {p}.".format (
+               dep_str=dep_env.dep_str, s=score, p=self.priority
+            )
+         )
+         return ( score, self.resolving_package )
+   # --- end of log_standard_match (...) ---
 
-                  self.logger.debug (
-                     'fuzzy-match: {dep_str} resolved as {dep!r} '
-                     'with score={s}.'.format (
-                        dep_str=dep_env.dep_str, dep=res, s=score
-                  ) )
-                  return ( score, res )
-               # --- if find (=match found)
-            # --- if name in
-         # --- for fuzzy
-      # --- elif hasattr
+   def handle_version_relative_match ( self, dep_env, fuzzy ):
+      raise NotImplementedError()
+   # --- end of handle_version_relative_match (...) ---
 
-      return None
+   def matches ( self, dep_env ):
+      partial_result = self.match_prepare ( dep_env )
+      if partial_result is None:
+         return None
+      else:
+         match_type, fuzzy = partial_result
+         score = self.FUZZY_SCORE [match_type]
+         if match_type == 0:
+            # real version-relative match
+            return self.log_fuzzy_match (
+               dep_env,
+               self.handle_version_relative_match ( dep_env, fuzzy ),
+               score
+            )
+         elif match_type == 1:
+            # name-only match (ignore rule?)
+            return self.log_fuzzy_match (
+               dep_env, self.resolving_package, score
+            )
+         else:
+            # non-fuzzy match
+            return self.log_standard_match ( dep_env, score )
+      # -- end if partial_result
    # --- end of matches (...) ---
+
+# --- end of FuzzySimpleRule ---

diff --git a/roverlay/depres/simpledeprule/rulemaker.py b/roverlay/depres/simpledeprule/rulemaker.py
index 6c3bc0e..a993341 100644
--- a/roverlay/depres/simpledeprule/rulemaker.py
+++ b/roverlay/depres/simpledeprule/rulemaker.py
@@ -23,29 +23,6 @@ from roverlay.depres.simpledeprule.abstractrules import *
 from roverlay.depres.simpledeprule.pool import SimpleDependencyRulePool
 
 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__ )
@@ -57,7 +34,9 @@ class SimpleRuleMaker ( object ):
       self.multiline_start = '{'
       self.multiline_stop  = '}'
       self.comment_char    = '#'
-      self._kw             = self.__class__.RuleKeywords()
+      self._kwmap          = rules.RuleConstructor (
+         eapi = config.get_or_fail ( 'EBUILD.eapi' )
+      )
       # deptype_kw is '#deptype' (this keyword requires comment 'mode')
       self.deptype_kw      = 'deptype'
       self._deptype        = deptype.ALL
@@ -113,26 +92,29 @@ class SimpleRuleMaker ( object ):
       #  or normal rule 'dev-lang/R :: R'
       # selfdeps are always single line statements (!)
 
-      rule_class, resolving = self._kw.lookup ( dep )
+      rule_class, resolving, kwargs = self._kwmap.lookup ( dep )
 
       if dep_str:
          # normal rule
          new_rule = rule_class (
             resolving_package=resolving,
             dep_str=dep_str,
-            is_selfdep=False
+            is_selfdep=False,
+            **kwargs
          )
 
       elif resolving is not None:
          # selfdep
          dep_str   = resolving
-         resolving = \
+         resolving = (
             config.get_or_fail ( 'OVERLAY.category' ) + '/' + resolving
+         )
 
          new_rule = rule_class (
             resolving_package=resolving,
             dep_str=dep_str,
-            is_selfdep=True
+            is_selfdep=True,
+            **kwargs
          )
       else:
          return False
@@ -175,11 +157,11 @@ class SimpleRuleMaker ( object ):
 
       elif len ( line ) > 1 and line [-1] == self.multiline_start:
          l = line [:-1].rstrip()
-         rule_class, resolving = self._kw.lookup ( l )
+         rule_class, resolving, kwargs = self._kwmap.lookup ( l )
 
          self._next = (
             self._deptype,
-            rule_class ( resolving_package=resolving )
+            rule_class ( resolving_package=resolving, **kwargs ),
          )
          return True
 

diff --git a/roverlay/depres/simpledeprule/rules.py b/roverlay/depres/simpledeprule/rules.py
index 6f006e6..db208d4 100644
--- a/roverlay/depres/simpledeprule/rules.py
+++ b/roverlay/depres/simpledeprule/rules.py
@@ -23,16 +23,85 @@ __all__ = (
 from roverlay.depres.simpledeprule.abstractrules import \
    SimpleRule, FuzzySimpleRule
 
-def get_rule_map():
-   kwmap = { c.RULE_PREFIX : c for c in (
-      SimpleIgnoreDependencyRule,
-      SimpleFuzzyDependencyRule,
-      SimpleFuzzyIgnoreDependencyRule
-   ) }
+class RuleConstructor ( object ):
 
-   return ( SimpleDependencyRule, kwmap )
-# --- end of get_rule_map (...) ---
+   def __init__ ( self, eapi ):
+      self.eapi = eapi
 
+      self.kw_ignore       = SimpleIgnoreDependencyRule.RULE_PREFIX
+      self.kw_fuzzy        = SimpleFuzzyDependencyRule.RULE_PREFIX
+      self.kw_fuzzy_ignore = SimpleFuzzyIgnoreDependencyRule.RULE_PREFIX
+   # --- end of __init__ (...) ---
+
+   def lookup ( self, keyworded_str ):
+      get_kwless = lambda : keyworded_str[1:].lstrip() or None
+
+      kw = keyworded_str[0]
+      if kw == self.kw_ignore:
+         return ( SimpleIgnoreDependencyRule, get_kwless(), {} )
+      elif kw == self.kw_fuzzy_ignore:
+         return ( SimpleFuzzyIgnoreDependencyRule, get_kwless(), {} )
+      elif kw == self.kw_fuzzy:
+         ##TODO
+         ## > "default"
+         ## > "slot only"
+         ## > "combined"
+   ## syntax
+   ## ~cat/pkg:<slot suffix>
+   ## ~cat/pkg:/<slot suffix>
+   ## ~cat/pkg:{major}/{minor}<slot suffix>
+   ##
+         kwless = get_kwless()
+         resolving, sepa, remainder = kwless.partition ( ':' )
+
+         if sepa:
+            # fuzzy slot rule
+            kwargs = { 'resolving_package_name' : resolving, }
+            slot_head, slot_sepa, slot_rem = remainder.partition ( ':' )
+
+            if slot_sepa:
+               # slot restriction
+               istart, isepa, istop = slot_head.partition ( '..' )
+               if isepa:
+                  kwargs ['slot_restrict'] = frozenset (
+                     range ( int ( istart or 0 ), int ( istop or 100 ) + 1 )
+                  )
+               else:
+                  kwargs ['slot_restrict'] = frozenset (
+                     int ( k ) for k in slot_head.split ( ',' )
+                  )
+
+               remainder = slot_rem
+            else:
+               remainder = slot_head
+            # -- end if;
+
+
+            if not remainder:
+               # <cat>/<pkg>:
+               kwargs ['slot_suffix'] = sepa + '{slot}'
+
+            elif remainder[0] in { '/', '*', '=' }:
+               # subslot, "any slot" operators
+               assert self.eapi >= 5
+               kwargs ['slot_suffix'] = sepa + '{slot}' + remainder
+            else:
+               kwargs ['slot_suffix'] = sepa + remainder
+
+
+            # verify that slot_suffix can be formatted properly
+##            if kwargs ['slot_suffix'] [0] != ':':
+##               kwargs ['slot_suffix'] = ':' + kwargs ['slot_suffix']
+
+            DONT_CARE = kwargs ['slot_suffix'].format ( slot='_', version='_' )
+            return ( SimpleFuzzySlotDependencyRule, resolving, kwargs )
+         else:
+            return ( SimpleFuzzyDependencyRule, kwless, {} )
+      else:
+         return ( SimpleDependencyRule, keyworded_str, {} )
+   # --- end of lookup (...) ---
+
+# --- end of RuleConstructor ---
 
 class SimpleIgnoreDependencyRule ( SimpleRule ):
 
@@ -90,14 +159,119 @@ class SimpleFuzzyIgnoreDependencyRule ( FuzzySimpleRule ):
       else:
          return super ( self.__class__, self ) . __str__()
 
+   def handle_version_relative_match ( self, *args, **kwargs ):
+      raise Exception ( "should-be unreachable code" )
+   # --- end of handle_version_relative_match (...) ---
+
+# --- end of SimpleFuzzyIgnoreDependencyRule ---
+
+
 class SimpleFuzzyDependencyRule ( FuzzySimpleRule ):
 
    RULE_PREFIX = '~'
 
-   def __init__ ( self, priority=71, resolving_package=None, **kw ):
+   def __init__ ( self, priority=72, resolving_package=None, **kw ):
       super ( SimpleFuzzyDependencyRule, self ) . __init__ (
          priority=priority,
          resolving_package=resolving_package,
          logger_name = 'FUZZY.' + resolving_package,
          **kw
       )
+   # --- end of __init__ (...) ---
+
+   def handle_version_relative_match ( self, dep_env, fuzzy ):
+      ver_pkg  = self.resolving_package + '-' + fuzzy ['version']
+      vmod_str = fuzzy ['version_modifier']
+      vmod     = fuzzy ['vmod']
+
+      #if vmod & dep_env.VMOD_NOT:
+      if vmod == dep_env.VMOD_NE:
+         # package matches, but specific version is forbidden
+         # ( !<package>-<specific verion> <package> )
+         return "( !={vres} {res} )".format (
+            vres=ver_pkg, res=self.resolving_package
+         )
+      else:
+         # std vmod: >=, <=, =, <, >
+         return vmod_str + ver_pkg
+   # --- end of handle_version_relative_match (...) ---
+
+# --- end of SimpleFuzzyDependencyRule ---
+
+
+class SimpleFuzzySlotDependencyRule ( FuzzySimpleRule ):
+   # 2 slot variants
+   # "slot only": resolve dep_str as <cat>/<pkg>:<slot>
+   # "combined": resolve dep_str as <vmod><cat>/<pkg>-<ver>:<slot>
+
+#   FMT_DICT = {
+#      'slot' : '{slot}',
+#   }
+
+   #RULE_PREFIX = '~'
+   RULE_PREFIX = SimpleFuzzyDependencyRule.RULE_PREFIX
+
+   def __init__ ( self,
+      priority               = 71,
+      resolving_package      = None,
+      resolving_package_name = None,
+      slot_suffix            = None,
+      slot_restrict          = None,
+      **kw
+   ):
+      super ( SimpleFuzzySlotDependencyRule, self ) . __init__ (
+         priority=priority,
+         resolving_package = resolving_package,
+         logger_name       = 'FUZZY_SLOT.' + (
+            resolving_package_name if resolving_package_name is not None
+            else resolving_package.partition ( ':' )[0]
+         ),
+         **kw
+      )
+
+      self.slot_suffix = slot_suffix
+
+      if slot_restrict:
+         self.slot_restrict = frozenset ( int ( k ) for k in slot_restrict )
+      else:
+         self.slot_restrict = None
+   # --- end of __init__ (...) ---
+
+   def __str__ ( self ):
+      # FIXME/TODO
+      return 'TODO! {low}..{high} {s}'.format (
+         low  = ( min ( self.slot_restrict ) if self.slot_restrict else 'X' ),
+         high = ( max ( self.slot_restrict ) if self.slot_restrict else 'X' ),
+         s    = ( super ( SimpleFuzzySlotDependencyRule, self ).__str__() ),
+      )
+   # --- end of __str__ (...) ---
+
+   def handle_version_relative_match ( self, dep_env, fuzzy ):
+      res  = False
+      vmod = fuzzy ['vmod']
+
+      if not ( vmod & dep_env.VMOD_NOT ):
+         # can be resolved as slot(ted) dep
+
+         ver_str = fuzzy ['version']
+         v_major, sepa, v_remainder = ver_str.partition ( '.' )
+         try:
+            slot = int ( v_major )
+
+            # resolve '<' and '>' by decrementing/incrementing slot
+            if vmod == dep_env.VMOD_LT:
+               slot -= 1
+            elif vmod == dep_env.VMOD_GT:
+               slot += 1
+
+            if not self.slot_restrict or slot in self.slot_restrict:
+               res = self.resolving_package + self.slot_suffix.format (
+                  slot=slot, version=ver_str,
+                  #vmod=fuzzy ['version_modifier']
+               )
+         except ValueError:
+            pass
+      # -- end if vmod
+
+      return res
+   # --- end of handle_version_relative_match (...) ---


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [gentoo-commits] proj/R_overlay:gsoc13/next commit in: roverlay/depres/simpledeprule/, roverlay/depres/
@ 2013-07-19 18:00 André Erdmann
  0 siblings, 0 replies; 4+ messages in thread
From: André Erdmann @ 2013-07-19 18:00 UTC (permalink / raw
  To: gentoo-commits

commit:     e328ea22ba0d41c4ccab358ae3df49486e6e4e62
Author:     André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Fri Jul 19 17:42:41 2013 +0000
Commit:     André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Fri Jul 19 17:42:41 2013 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=e328ea22

roverlay/depres/: replace rule pool export_rules()

---
 roverlay/depres/deprule.py            | 23 +++++++++++++++++++++++
 roverlay/depres/simpledeprule/pool.py | 14 +-------------
 2 files changed, 24 insertions(+), 13 deletions(-)

diff --git a/roverlay/depres/deprule.py b/roverlay/depres/deprule.py
index 1d36941..ed6084d 100644
--- a/roverlay/depres/deprule.py
+++ b/roverlay/depres/deprule.py
@@ -40,6 +40,10 @@ class DependencyRule ( object ):
 
    make_result = _make_result
 
+   def export_rule ( self ):
+      raise NotImplementedError()
+   # --- end of export_rule (...) ---
+
 # --- end of DependencyRule ---
 
 
@@ -149,3 +153,22 @@ class DependencyRulePool ( object ):
       # default return
       return None
    # --- end of matches (...) ---
+
+   def export_rules ( self ):
+      """Exports all rules. Typically, this generates text lines."""
+      for rule in self.rules:
+         for item in rule.export_rule():
+            yield item
+   # --- end of export_rules (...) ---
+
+   def export_rules_into ( self, fh ):
+      """Writes all rules into the given file handle.
+
+      arguments:
+      * fh --
+      """
+      NL = '\n'
+      for item in self.export_rules():
+         fh.write ( str ( item ) )
+         fh.write ( NL )
+# --- end of DependencyRulePool ---

diff --git a/roverlay/depres/simpledeprule/pool.py b/roverlay/depres/simpledeprule/pool.py
index 6fcb714..677ad20 100644
--- a/roverlay/depres/simpledeprule/pool.py
+++ b/roverlay/depres/simpledeprule/pool.py
@@ -16,6 +16,7 @@ from roverlay.depres import deprule
 from roverlay.depres.simpledeprule.abstractrules import SimpleRule
 
 class SimpleDependencyRulePool ( deprule.DependencyRulePool ):
+
    def __init__ ( self, name, priority=70, **kw ):
       """Initializes a SimpleDependencyRulePool, which is a DependencyRulePool
       specialized in simple dependency rules;
@@ -43,16 +44,3 @@ class SimpleDependencyRulePool ( deprule.DependencyRulePool ):
       else:
          raise Exception ( "bad usage (simple dependency rule expected)." )
    # --- end of add (...) ---
-
-   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 (...) ---


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2013-07-19 18:00 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-07-03 10:05 [gentoo-commits] proj/R_overlay:master commit in: roverlay/depres/simpledeprule/, roverlay/depres/ André Erdmann
2013-06-28  6:19 ` [gentoo-commits] proj/R_overlay:gsoc13/next " André Erdmann
  -- strict thread matches above, loose matches on Subject: below --
2013-07-19 18:00 André Erdmann
2013-07-02 21:09 André Erdmann

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