public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/R_overlay:wip/addition_control commit in: roverlay/packagerules/generators/abstract/, roverlay/packagerules/generators/, ...
@ 2014-07-18 14:55 André Erdmann
  2014-07-18 16:20 ` [gentoo-commits] proj/R_overlay:master " André Erdmann
  0 siblings, 1 reply; 2+ messages in thread
From: André Erdmann @ 2014-07-18 14:55 UTC (permalink / raw
  To: gentoo-commits

commit:     617d1f739c35e8a4b4e10781a7eecfb11191f01c
Author:     André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Fri Jul 18 14:30:22 2014 +0000
Commit:     André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Fri Jul 18 14:30:22 2014 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=617d1f73

addition control: in-code __doc__

---
 roverlay/overlay/abccontrol.py                     |  19 ++
 roverlay/packagerules/actions/addition_control.py  |   4 +
 roverlay/packagerules/generators/abstract/base.py  |   3 +
 .../packagerules/generators/addition_control.py    | 262 ++++++++++++++++++++-
 roverlay/runtime.py                                |  31 +++
 5 files changed, 307 insertions(+), 12 deletions(-)

diff --git a/roverlay/overlay/abccontrol.py b/roverlay/overlay/abccontrol.py
index 991343e..e5f8764 100644
--- a/roverlay/overlay/abccontrol.py
+++ b/roverlay/overlay/abccontrol.py
@@ -25,6 +25,9 @@ import itertools
 _AbstractObject = abc.ABCMeta ( str("AbstractObject"), ( object, ), {} )
 
 def _gen_bits ( count ):
+   """Generator that creates a series of bits, including 0 and a combination
+   of all generated bits: 0,2**0,2**1,...,2**(count-1),(2**count)-1
+   """
    yield 0
    for k in range(count):
       yield 2**k
@@ -103,6 +106,16 @@ class AdditionControlResult ( object ):
 
    @classmethod
    def convert_str ( cls, s ):
+      """Converts a comma-separated list of words into a PKG_* mask.
+
+      Returns: int
+
+      arguments:
+      * s -- str, comma-separated list of words (see PKG_DESCRIPTION_MAP)
+
+
+      Raises: ValueError
+      """
       desc_rmap = cls.PKG_DESCRIPTION_REVMAP
 
       if not s:
@@ -133,6 +146,12 @@ class AdditionControlResult ( object ):
 
    @classmethod
    def get_effective_package_policy ( cls, pkg_policy ):
+      """Removes all/most overlapping bits from a add-policy bitmask (int)
+      and returns the result.
+
+      arguments:
+      * pkg_policy --
+      """
       # hardcoded for now
 
       if not pkg_policy:

diff --git a/roverlay/packagerules/actions/addition_control.py b/roverlay/packagerules/actions/addition_control.py
index 48e4999..bd07a55 100644
--- a/roverlay/packagerules/actions/addition_control.py
+++ b/roverlay/packagerules/actions/addition_control.py
@@ -28,6 +28,8 @@ __all__ = ACTIONS
 class PackageAdditionControlActionBase (
    roverlay.packagerules.abstract.actions.PackageRuleAction
 ):
+   """Base class for addition control actions."""
+
    KEYWORD         = "add-policy"
    CONTROL_KEYWORD = None
    CONTROL_RESULT  = None
@@ -56,6 +58,8 @@ class PackageAdditionControlActionBase (
 class PackageAdditionControlDefaultAction (
    PackageAdditionControlActionBase
 ):
+   """restore-default-behavior add-policy action"""
+
    CONTROL_KEYWORD = "default"
    CONTROL_RESULT  = AdditionControlResult.PKG_DEFAULT_BEHAVIOR
 

diff --git a/roverlay/packagerules/generators/abstract/base.py b/roverlay/packagerules/generators/abstract/base.py
index a254bc2..6f9e7ae 100644
--- a/roverlay/packagerules/generators/abstract/base.py
+++ b/roverlay/packagerules/generators/abstract/base.py
@@ -12,4 +12,7 @@ _AbstractObject = abc.ABCMeta ( str("AbstractObject"), ( object, ), {} )
 
 
 class AbstractPackageRuleGenerator ( _AbstractObject ):
+   """Base class for package rule generators."""
+
+   # declares/implements nothing, currently
    pass

diff --git a/roverlay/packagerules/generators/addition_control.py b/roverlay/packagerules/generators/addition_control.py
index db6f244..9aeada3 100644
--- a/roverlay/packagerules/generators/addition_control.py
+++ b/roverlay/packagerules/generators/addition_control.py
@@ -66,7 +66,15 @@ def _read_list_file (
    filepath,
    _read_text_file=roverlay.util.fileio.read_text_file
 ):
+   """Generator that reads a list file and yields its entries.
+
+   arguments:
+   * filepath        -- file to read, can be None
+   * _read_text_file -- private
+   """
+
    def strip_line ( s ):
+      """strip.line(s) -> s.strip()"""
       return s.strip()
 
    if filepath:
@@ -80,6 +88,10 @@ class AdditionControlPackageRuleGenerator (
    roverlay.packagerules.generators.abstract.addition_control.\
       AbstractAdditionControlPackageRuleGenerator
 ):
+   """Addition control package rule generator.
+
+   Extends the abstract base class by category/package tokens.
+   """
 
    #TOKEN_ITEM_IS_SPECIAL = 0 ## implicit
    TOKEN_ITEM_IS_STR      = 1
@@ -89,7 +101,7 @@ class AdditionControlPackageRuleGenerator (
       "TokenItemTuple", "item_type value"
    )
 
-   # PackageToken: tuple ( None|$PN, None|$PV, None|$PR )
+   # PackageToken: True | tuple ( True|None|$PN, True|None|$PV, True|None|$PR )
    #  (revision not implemented because it cannot be matched in package rules
    #   -- always 0)
    #  condition: not all ( item is None for item in <PackageToken> )
@@ -98,12 +110,13 @@ class AdditionControlPackageRuleGenerator (
    #
    PackageToken  = collections.namedtuple ( 'PackageToken', 'name version' )
 
-   # CategoryToken: tuple ( $CATEGORY )
+   # CategoryToken: True | tuple ( Tru|$CATEGORY )
    #  same conditions as for PackageToken apply,
    #   which effectively means that $CATEGORY must a non-empty str
    #
    CategoryToken = collections.namedtuple ( 'CategoryToken', 'name' )
 
+   # token for matching the default category ("@default")
    DEFAULT_CATEGORY_TOKEN = CategoryToken (
       TokenItemTuple (
          TOKEN_ITEM_IS_STR,
@@ -113,6 +126,13 @@ class AdditionControlPackageRuleGenerator (
 
 
    def create_token_item_from_str ( self, s ):
+      """Creates a token item for the given string.
+
+      Returns: None, True or a TokenItemTuple
+
+      arguments:
+      * s -- input str, can be empty/None
+      """
       get_obj = self.namespace.get_object_v
 
       if not s:
@@ -142,11 +162,18 @@ class AdditionControlPackageRuleGenerator (
          )
    # --- end of create_token_item_from_str (...) ---
 
-   def validate_token ( self, package_token ):
+   def validate_token ( self, token ):
+      """Validates and returns 'reduced' category or package token.
+
+      Returns None if the token is not valid, else True or the token.
+
+      arguments:
+      * token --
+      """
       all_none       = True
       any_nonspecial = False
 
-      for item in package_token:
+      for item in token:
          if item:
             all_none = False
             if item is not True:
@@ -157,14 +184,27 @@ class AdditionControlPackageRuleGenerator (
          assert not any_nonspecial
          return None
       elif any_nonspecial:
-         return package_token
+         return token
       else:
          # FIXME: remove assert
-         assert all ( item in ( True, None ) for item in package_token ), package_token
+         assert all ( item in ( True, None ) for item in token ), token
          return True
    # --- end of validate_token (...) ---
 
    def _create_package_token ( self, name_str, version_str, revision_str ):
+      """Creates a package token.
+
+      Returns: validated/reduced PackageToken or None
+
+      arguments:
+      * name_str     -- name     token item str (or empty)
+      * version_str  -- version  token item str (or empty)
+      * revision_str -- revision token item str (must be empty)
+
+
+      Raises: TokenItemNotSupported if revision_str is not empty
+
+      """
       if revision_str:
          raise TokenItemNotSupported (
             "revision {!s}".format ( revision_str )
@@ -183,6 +223,13 @@ class AdditionControlPackageRuleGenerator (
    # --- end of _create_package_token (...) ---
 
    def _create_category_token ( self, category_str ):
+      """Creates a category token.
+
+      Returns: validated/reduced CategoryToken or None
+
+      arguments:
+      * category_str -- category name str
+      """
       if category_str == self.default_category:
          # validate_token() not necessary (assumption)
          return self.DEFAULT_CATEGORY_TOKEN
@@ -198,6 +245,17 @@ class AdditionControlPackageRuleGenerator (
    # --- end of _create_category_token (...) ---
 
    def create_category_token ( self, input_str ):
+      """Creates a category token, validates and returns it.
+
+      Returns: CategoryToken
+
+      arguments:
+      * input_str -- string that should be converted to a token
+
+
+      Raises: InvalidTokenInputString if created token is not valid
+
+      """
       # input_str doesn't need much parsing,
       #  not using RE_WILDCARD_CATEGORY for now
 ##      re_match = RE_WILDCARD_CATEGORY.match ( input_str )
@@ -219,6 +277,25 @@ class AdditionControlPackageRuleGenerator (
    def create_token (
       self, input_str, with_category=True, package_regex=RE_WILDCARD_PACKAGE
    ):
+      """Creates a <category,package> token pair, validates and returns it.
+
+      Returns: tuple(CategoryToken,PackageToken) or PackageToken,
+                depending on the with_category parameter
+
+      arguments:
+      * input_str     -- string that should be converted to a token
+      * with_category -- whether to create a token pair or a single package
+                         token.
+                         Defaults to True (-> token pair)
+                         When set to False, input_str must not contain a
+                         category.
+      * package_regex -- compiled regex for parsing the input string
+                         Defaults to RE_WILDCARD_PACKAGE
+
+
+      Raises: InvalidTokenInputString if created token is not valid
+
+      """
       re_match = package_regex.match ( input_str )
 
       if not re_match:
@@ -266,34 +343,79 @@ class AdditionControlPackageRuleGenerator (
    # --- end of create_token (...) ---
 
    def create_token_for_ebuild_filepath ( self, efile ):
+      """Like create_token(), but passes a regex suitable for parsing
+      ebuild file paths.
+
+      Returns: tuple(CategoryToken,PackageToken)
+
+      arguments:
+      * efile -- ebuild file path
+
+
+      Raises: InvalidTokenInputString if created token is not valid
+
+      """
       return self.create_token (
          efile, with_category=True, package_regex=RE_PACKAGE_EBUILD_FILE
       )
    # --- end of create_token_for_ebuild_filepath (...) ---
 
    def create_package_token ( self, input_str ):
+      """Creates a package token, validates and returns it.
+
+      Returns: PackageToken
+
+      arguments:
+      * input_str -- string that should be converted to a token
+
+
+      Raises: InvalidTokenInputString if created token is not valid
+
+      """
       return self.create_token ( input_str, with_category=False )
    # --- end of create_package_token (...) ---
 
 
    def __init__ ( self, default_category ):
+      """AdditionControlPackageRuleGenerator constructor.
+
+      arguments:
+      * default_category -- name of the default overlay category, e.g. "sci-R"
+      """
       super ( AdditionControlPackageRuleGenerator, self ).__init__()
       self.namespace        = roverlay.util.namespace.SimpleNamespace()
       self.default_category = default_category
    # --- end of __init__ (...) ---
 
    def clear_object_cache ( self ):
+      """Clears the object cache (self.namespace)."""
       if self.namespace:
          self.namespace.zap(True)
    # --- end of clear_object_cache (...) ---
 
    def __del__ ( self ):
+      """on-delete: clear_object_cache()"""
       try:
          self.clear_object_cache()
       except NotImplementedError:
          pass
 
    def token_item_to_acceptor ( self, token_item, value_getter, priority ):
+      """Converts a token item (True, None or a TokenItemTuple) into a package
+      rule acceptor.
+
+      Returns: acceptor (StringAcceptor, ExactRegexAcceptor)
+               or None (no acceptor created)
+
+      arguments:
+      * token_item    -- token item
+      * value_getter  -- helper function for the acceptor that retrieves
+                         the value to be matched from a PackageInfo object
+      * priority      -- priority of the acceptor
+
+      Raises: AssertionError if the token item's value type is unknown.
+      """
+
       if token_item in ( True, None ):
          # should be catched elsewhere
          return None
@@ -317,6 +439,14 @@ class AdditionControlPackageRuleGenerator (
    # --- end of token_item_to_acceptor (...) ---
 
    def category_token_to_acceptor ( self, category_token, priority ):
+      """Converts a category token into a package rule acceptor.
+
+      Returns: acceptor
+
+      arguments:
+      * category_token -- must be valid
+      * priority       --
+      """
       assert category_token and category_token is not True
 
       return self.token_item_to_acceptor (
@@ -325,6 +455,18 @@ class AdditionControlPackageRuleGenerator (
    # --- end of category_token_to_acceptor (...) ---
 
    def package_token_to_acceptor ( self, package_token, priority ):
+      """Converts a package token into a package rule acceptor.
+
+      Returns: acceptor or acceptor compound
+
+      arguments:
+      * package_token -- must be valid
+      * priority      --
+
+
+      Raises: TokenValueError
+
+      """
       assert package_token and package_token is not True
 
       relevant_items = [
@@ -364,17 +506,41 @@ class BitmaskMapCreator ( object ):
    """creates a "bitmask" => "acceptor chain" map"""
 
    def __init__ ( self, rule_generator ):
+      """BitmaskMapCreator constructor.
+
+      arguments:
+      * rule_generator -- package rule generator object that this object
+                          should bind to.
+                          Responsible for creating tokens.
+      """
       super ( BitmaskMapCreator, self ).__init__()
       self.rule_generator = rule_generator
       self.data           = rule_generator.create_new_bitmask_map()
 
    def get_bitmask_map ( self ):
+      """Returns the bitmask map as reference."""
       return self.data
 
    def get_bitmask_map_copy ( self ):
+      """Returns a copy of the bitmask map."""
       return self.data.copy()
 
    def _insert_package ( self, bitmask_arg, package_str, package_regex ):
+      """Adds a package to the bitmask map.
+
+      Returns: None (implicit)
+
+      arguments:
+      * bitmask_arg   -- bitmask int or str (comma-separated list of words)
+      * package_str   -- package input string, e.g. "sci-R/seewave"
+                          (format depends on package_regex)
+      * package_regex -- regex for parsing package_str
+
+
+      Raises: ValueError if bitmask_arg not valid
+
+      """
+
       category_token, package_token = self.rule_generator.create_token (
          package_str, with_category=True, package_regex=package_regex
       )
@@ -385,6 +551,7 @@ class BitmaskMapCreator ( object ):
          bitmask_int = int ( bitmask_arg )
 
 
+      # self.data -> category_token -> package_token |= bitmask_int
       try:
          cat_entry = self.data [category_token]
       except KeyError:
@@ -401,12 +568,21 @@ class BitmaskMapCreator ( object ):
    # --- end of _insert_package (...) ---
 
    def _split_bitmask_line ( self, line, default_bitmask ):
+      """Splits a "[<bitmask> ]<package_str> line.
+
+      arguments:
+      * line            --
+      * default_bitmask -- default bitmask or None
+
+      Raises: ValueError if line contains no bitmask
+              and default_bitmask is not set
+      """
       # str<[bitmask,]arg> => ( bitmask||default_bitmask, arg )
       args = line.split ( None, 1 )
 
       if len(args) == 2:
          # convert bitmask str now
-         return ( AdditionControlResult.convert_str(args[0]), args[1] )
+         return ( AdditionControlResult.convert_str ( args[0] ), args[1] )
 
       elif default_bitmask or (
          default_bitmask == 0 and default_bitmask is not False
@@ -421,13 +597,19 @@ class BitmaskMapCreator ( object ):
    def _insert_packages_v (
       self, bitmask, arglist, package_regex, extended_format
    ):
+      """Adds zero or more package strings to the bitmask map.
+
+      arguments:
+      * bitmask         -- bitmask (or default bitmask in extended format)
+      * arglist         -- list of <package_str> (or <bitmask> <package_str>)
+      * package_regex   -- regex for parsing <package_str>
+      * extended_format -- whether arglist is in extended format or not
+                            (add-policy bitmask embedded in input string)
+      """
       insert_package = self._insert_package
 
       if extended_format:
-         split_bitmask_line = self._split_bitmask_line
-
-         for arg in arglist:
-            call_args = split_bitmask_line ( arg, bitmask )
+         for call_args in map ( self._split_bitmask_line, arglist ):
             insert_package ( call_args[0], call_args[1], package_regex )
 
       else:
@@ -436,31 +618,63 @@ class BitmaskMapCreator ( object ):
    # --- end of _insert_packages_v (...) ---
 
    def insert_packages_v ( self, bitmask, packages, extended_format=False ):
+      """Adds zero or more packages to the bitmask map.
+
+      arguments:
+      * bitmask         --
+      * packages        --
+      * extended_format --
+      """
+      # package in this context: ${CATEGORY}/${PF} or ${PF}
       self._insert_packages_v (
          bitmask, packages, RE_WILDCARD_PACKAGE, extended_format
       )
    # --- end of insert_packages_v (...) ---
 
    def insert_package ( self, bitmask, package, *args, **kwargs ):
+      """Adds a package to the bitmask map.
+
+      arguments:
+      * bitmask         --
+      * package         --
+      * *args, **kwargs -- passed to insert_packages_v()
+      """
       self.insert_packages_v ( bitmask, ( package, ), *args, **kwargs )
 
    def insert_packages ( self, bitmask, *packages, **kwargs ):
+      """varargs-variant f insert_packages_v()."""
       self.insert_packages_v ( bitmask, packages, **kwargs )
 
    def insert_ebuild_files_v (
       self, bitmask, ebuild_files, extended_format=False
    ):
+      """Adds zero or more ebuild file paths to the bitmask map.
+
+      arguments:
+      * bitmask         --
+      * ebuild_files    --
+      * extended_format --
+      """
+      # ebuild file: [<overlay>/]${CATEGORY}/${PN}/${PF}.ebuild
       self._insert_packages_v (
          bitmask, ebuild_files, RE_PACKAGE_EBUILD_FILE, extended_format
       )
    # --- end of insert_ebuild_files_v (...) ---
 
    def insert_ebuild_file ( self, bitmask, ebuild_file, *args, **kwargs ):
+      """Adds an ebuild file path to the bitmask map.
+
+      arguments:
+      * bitmask         --
+      * ebuild_file     --
+      * *args, **kwargs -- passed to insert_ebuild_files_v()
+      """
       self.insert_ebuild_files_v (
          bitmask, ( ebuild_file, ), *args, **kwargs
       )
 
    def insert_ebuild_files ( self, bitmask, *ebuild_files, **kwargs ):
+      """varargs-variant of insert_ebuild_files_v()."""
       self.insert_ebuild_files_v ( bitmask, ebuild_files, **kwargs )
 
 
@@ -468,6 +682,8 @@ class BitmaskMapCreator ( object ):
       bitmask, package_list=None, ebuild_file_list=None,
       extended_format=False
    ):
+      """combined insert_packages_v()/insert_ebuild_files_v()."""
+      # FIXME: CANDIDATE FOR REMOVAL (rev-dep: feed_from_file())
       if package_list:
          self.insert_packages_v ( bitmask, package_list, extended_format )
 
@@ -483,6 +699,7 @@ class BitmaskMapCreator ( object ):
       self, bitmask, package_list_file=None, ebuild_list_file=None,
       extended_format=False,
    ):
+      """Reads files and calls insert_packages_v()/insert_ebuild_files_v()."""
       # or ebuild_file_list_file
 
       self.feed (
@@ -499,6 +716,12 @@ class BitmaskMapCreator ( object ):
 
 def create_addition_control_package_rule (
    default_category,
+   # *,  ## force keyword-only, py3 only
+
+   extended_default_bitmask             = (
+      AdditionControlResult.PKG_REVBUMP_ON_COLLISION | \
+      AdditionControlResult.PKG_REPLACE_ONLY
+   ),
 
    cmdline_package_default              = None,
    cmdline_package_force_deny           = None,
@@ -533,7 +756,7 @@ def create_addition_control_package_rule (
    file_ebuild_revbump_on_collision     = None,
 
    file_package_extended                = None,
-   file_ebuild_extended                 = None,
+   file_ebuild_extended                 = None
 ):
    """All-in-one function that takes lists of packages, ebuild paths, list
    files, ... as input, creates a "bitmask" -> "acceptor chain" map and
@@ -553,10 +776,25 @@ def create_addition_control_package_rule (
    * cmdline_ebuild_<policy>  -- list of ebuilds  [None]
    * file_package_<policy>    -- package list file[s] [None]
    * file_ebuild_<policy>     -- ebuild  list file[s] [None]
+   * cmdline_package_extended -- package list in extended format [None]
+   * cmdline_ebuild_extended  -- ebuild  list in extended format [None]
    * file_package_extended    -- package list file[s] in extended format [None]
    * file_ebuild_extended     -- ebuild  list file[s] in extended format [None]
+   * extended_default_bitmask -- default bitmask for lists/files
+                                 in extended format list files. Can be None
+                                 Defaults to revbump-on-collision,replace-only
+
+
+   Raises:
+   * ValueError if default_category not valid
+   * passes exceptions from rule generator / bitmask map creator
+
 
    Note: file_* parameters support only a single input file, currently.
+
+   Note: cmdline_*, file_* should be passed as keyword arguments only!
+         (There's no good way to enforce this in python 2 except for **kwargs,
+          which in turn would accept invalid args...)
    """
    argv_locals = locals().copy()
    get_args    = lambda pre, attr_name: (

diff --git a/roverlay/runtime.py b/roverlay/runtime.py
index 521eb0e..fd45425 100644
--- a/roverlay/runtime.py
+++ b/roverlay/runtime.py
@@ -207,6 +207,16 @@ class RuntimeEnvironment ( RuntimeEnvironmentBase ):
    # --- end of get_overlay_creator (...) ---
 
    def create_addition_control_rules ( self, default_category=None ):
+      """Creates addition control package rules from cmdline/config.
+
+      Returns: a package rule object or None
+
+      arguments:
+      * default_category -- name of the default category
+                             Can be None/"false", in which case it is
+                             queried from self.config
+                             Defaults to None.
+      """
       kwargs = {}
       def add_key ( k, _kwargs=kwargs, _options=self.options ):
          _kwargs [k] = _options [k]
@@ -230,6 +240,17 @@ class RuntimeEnvironment ( RuntimeEnvironmentBase ):
    def add_addition_control_rules (
       self, package_rules, default_category=None
    ):
+      """Adds addition control rules to the given package rules object.
+
+      Returns True if add-policy rules have been added and False if not
+      (i.e. no rules configured).
+
+      See also create_addition_control_rules().
+
+      arguments:
+      * package_rules    --
+      * default_category --
+      """
       add_control_rule = self.create_addition_control_rules (
          default_category = default_category
       )
@@ -242,6 +263,16 @@ class RuntimeEnvironment ( RuntimeEnvironmentBase ):
    # --- end of add_addition_control_rules (...) ---
 
    def add_addition_control_to_overlay_creator ( self ):
+      """Adds addition control to the overlay creator.
+      Currently, this is limited to add-policy package rules.
+
+      The overlay creator and its package rules have to be initialized
+      with get_overlay_creator() before calling this method.
+
+      Returns True if any addition control has been added, else False.
+
+      arguments: none
+      """
       if not self._overlay_creator:
          raise AssertionError ( "overlay creator not initialized." )
       elif not getattr ( self._overlay_creator, 'package_rules', None ):


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

* [gentoo-commits] proj/R_overlay:master commit in: roverlay/packagerules/generators/abstract/, roverlay/packagerules/generators/, ...
  2014-07-18 14:55 [gentoo-commits] proj/R_overlay:wip/addition_control commit in: roverlay/packagerules/generators/abstract/, roverlay/packagerules/generators/, André Erdmann
@ 2014-07-18 16:20 ` André Erdmann
  0 siblings, 0 replies; 2+ messages in thread
From: André Erdmann @ 2014-07-18 16:20 UTC (permalink / raw
  To: gentoo-commits

commit:     617d1f739c35e8a4b4e10781a7eecfb11191f01c
Author:     André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Fri Jul 18 14:30:22 2014 +0000
Commit:     André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Fri Jul 18 14:30:22 2014 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=617d1f73

addition control: in-code __doc__

---
 roverlay/overlay/abccontrol.py                     |  19 ++
 roverlay/packagerules/actions/addition_control.py  |   4 +
 roverlay/packagerules/generators/abstract/base.py  |   3 +
 .../packagerules/generators/addition_control.py    | 262 ++++++++++++++++++++-
 roverlay/runtime.py                                |  31 +++
 5 files changed, 307 insertions(+), 12 deletions(-)

diff --git a/roverlay/overlay/abccontrol.py b/roverlay/overlay/abccontrol.py
index 991343e..e5f8764 100644
--- a/roverlay/overlay/abccontrol.py
+++ b/roverlay/overlay/abccontrol.py
@@ -25,6 +25,9 @@ import itertools
 _AbstractObject = abc.ABCMeta ( str("AbstractObject"), ( object, ), {} )
 
 def _gen_bits ( count ):
+   """Generator that creates a series of bits, including 0 and a combination
+   of all generated bits: 0,2**0,2**1,...,2**(count-1),(2**count)-1
+   """
    yield 0
    for k in range(count):
       yield 2**k
@@ -103,6 +106,16 @@ class AdditionControlResult ( object ):
 
    @classmethod
    def convert_str ( cls, s ):
+      """Converts a comma-separated list of words into a PKG_* mask.
+
+      Returns: int
+
+      arguments:
+      * s -- str, comma-separated list of words (see PKG_DESCRIPTION_MAP)
+
+
+      Raises: ValueError
+      """
       desc_rmap = cls.PKG_DESCRIPTION_REVMAP
 
       if not s:
@@ -133,6 +146,12 @@ class AdditionControlResult ( object ):
 
    @classmethod
    def get_effective_package_policy ( cls, pkg_policy ):
+      """Removes all/most overlapping bits from a add-policy bitmask (int)
+      and returns the result.
+
+      arguments:
+      * pkg_policy --
+      """
       # hardcoded for now
 
       if not pkg_policy:

diff --git a/roverlay/packagerules/actions/addition_control.py b/roverlay/packagerules/actions/addition_control.py
index 48e4999..bd07a55 100644
--- a/roverlay/packagerules/actions/addition_control.py
+++ b/roverlay/packagerules/actions/addition_control.py
@@ -28,6 +28,8 @@ __all__ = ACTIONS
 class PackageAdditionControlActionBase (
    roverlay.packagerules.abstract.actions.PackageRuleAction
 ):
+   """Base class for addition control actions."""
+
    KEYWORD         = "add-policy"
    CONTROL_KEYWORD = None
    CONTROL_RESULT  = None
@@ -56,6 +58,8 @@ class PackageAdditionControlActionBase (
 class PackageAdditionControlDefaultAction (
    PackageAdditionControlActionBase
 ):
+   """restore-default-behavior add-policy action"""
+
    CONTROL_KEYWORD = "default"
    CONTROL_RESULT  = AdditionControlResult.PKG_DEFAULT_BEHAVIOR
 

diff --git a/roverlay/packagerules/generators/abstract/base.py b/roverlay/packagerules/generators/abstract/base.py
index a254bc2..6f9e7ae 100644
--- a/roverlay/packagerules/generators/abstract/base.py
+++ b/roverlay/packagerules/generators/abstract/base.py
@@ -12,4 +12,7 @@ _AbstractObject = abc.ABCMeta ( str("AbstractObject"), ( object, ), {} )
 
 
 class AbstractPackageRuleGenerator ( _AbstractObject ):
+   """Base class for package rule generators."""
+
+   # declares/implements nothing, currently
    pass

diff --git a/roverlay/packagerules/generators/addition_control.py b/roverlay/packagerules/generators/addition_control.py
index db6f244..9aeada3 100644
--- a/roverlay/packagerules/generators/addition_control.py
+++ b/roverlay/packagerules/generators/addition_control.py
@@ -66,7 +66,15 @@ def _read_list_file (
    filepath,
    _read_text_file=roverlay.util.fileio.read_text_file
 ):
+   """Generator that reads a list file and yields its entries.
+
+   arguments:
+   * filepath        -- file to read, can be None
+   * _read_text_file -- private
+   """
+
    def strip_line ( s ):
+      """strip.line(s) -> s.strip()"""
       return s.strip()
 
    if filepath:
@@ -80,6 +88,10 @@ class AdditionControlPackageRuleGenerator (
    roverlay.packagerules.generators.abstract.addition_control.\
       AbstractAdditionControlPackageRuleGenerator
 ):
+   """Addition control package rule generator.
+
+   Extends the abstract base class by category/package tokens.
+   """
 
    #TOKEN_ITEM_IS_SPECIAL = 0 ## implicit
    TOKEN_ITEM_IS_STR      = 1
@@ -89,7 +101,7 @@ class AdditionControlPackageRuleGenerator (
       "TokenItemTuple", "item_type value"
    )
 
-   # PackageToken: tuple ( None|$PN, None|$PV, None|$PR )
+   # PackageToken: True | tuple ( True|None|$PN, True|None|$PV, True|None|$PR )
    #  (revision not implemented because it cannot be matched in package rules
    #   -- always 0)
    #  condition: not all ( item is None for item in <PackageToken> )
@@ -98,12 +110,13 @@ class AdditionControlPackageRuleGenerator (
    #
    PackageToken  = collections.namedtuple ( 'PackageToken', 'name version' )
 
-   # CategoryToken: tuple ( $CATEGORY )
+   # CategoryToken: True | tuple ( Tru|$CATEGORY )
    #  same conditions as for PackageToken apply,
    #   which effectively means that $CATEGORY must a non-empty str
    #
    CategoryToken = collections.namedtuple ( 'CategoryToken', 'name' )
 
+   # token for matching the default category ("@default")
    DEFAULT_CATEGORY_TOKEN = CategoryToken (
       TokenItemTuple (
          TOKEN_ITEM_IS_STR,
@@ -113,6 +126,13 @@ class AdditionControlPackageRuleGenerator (
 
 
    def create_token_item_from_str ( self, s ):
+      """Creates a token item for the given string.
+
+      Returns: None, True or a TokenItemTuple
+
+      arguments:
+      * s -- input str, can be empty/None
+      """
       get_obj = self.namespace.get_object_v
 
       if not s:
@@ -142,11 +162,18 @@ class AdditionControlPackageRuleGenerator (
          )
    # --- end of create_token_item_from_str (...) ---
 
-   def validate_token ( self, package_token ):
+   def validate_token ( self, token ):
+      """Validates and returns 'reduced' category or package token.
+
+      Returns None if the token is not valid, else True or the token.
+
+      arguments:
+      * token --
+      """
       all_none       = True
       any_nonspecial = False
 
-      for item in package_token:
+      for item in token:
          if item:
             all_none = False
             if item is not True:
@@ -157,14 +184,27 @@ class AdditionControlPackageRuleGenerator (
          assert not any_nonspecial
          return None
       elif any_nonspecial:
-         return package_token
+         return token
       else:
          # FIXME: remove assert
-         assert all ( item in ( True, None ) for item in package_token ), package_token
+         assert all ( item in ( True, None ) for item in token ), token
          return True
    # --- end of validate_token (...) ---
 
    def _create_package_token ( self, name_str, version_str, revision_str ):
+      """Creates a package token.
+
+      Returns: validated/reduced PackageToken or None
+
+      arguments:
+      * name_str     -- name     token item str (or empty)
+      * version_str  -- version  token item str (or empty)
+      * revision_str -- revision token item str (must be empty)
+
+
+      Raises: TokenItemNotSupported if revision_str is not empty
+
+      """
       if revision_str:
          raise TokenItemNotSupported (
             "revision {!s}".format ( revision_str )
@@ -183,6 +223,13 @@ class AdditionControlPackageRuleGenerator (
    # --- end of _create_package_token (...) ---
 
    def _create_category_token ( self, category_str ):
+      """Creates a category token.
+
+      Returns: validated/reduced CategoryToken or None
+
+      arguments:
+      * category_str -- category name str
+      """
       if category_str == self.default_category:
          # validate_token() not necessary (assumption)
          return self.DEFAULT_CATEGORY_TOKEN
@@ -198,6 +245,17 @@ class AdditionControlPackageRuleGenerator (
    # --- end of _create_category_token (...) ---
 
    def create_category_token ( self, input_str ):
+      """Creates a category token, validates and returns it.
+
+      Returns: CategoryToken
+
+      arguments:
+      * input_str -- string that should be converted to a token
+
+
+      Raises: InvalidTokenInputString if created token is not valid
+
+      """
       # input_str doesn't need much parsing,
       #  not using RE_WILDCARD_CATEGORY for now
 ##      re_match = RE_WILDCARD_CATEGORY.match ( input_str )
@@ -219,6 +277,25 @@ class AdditionControlPackageRuleGenerator (
    def create_token (
       self, input_str, with_category=True, package_regex=RE_WILDCARD_PACKAGE
    ):
+      """Creates a <category,package> token pair, validates and returns it.
+
+      Returns: tuple(CategoryToken,PackageToken) or PackageToken,
+                depending on the with_category parameter
+
+      arguments:
+      * input_str     -- string that should be converted to a token
+      * with_category -- whether to create a token pair or a single package
+                         token.
+                         Defaults to True (-> token pair)
+                         When set to False, input_str must not contain a
+                         category.
+      * package_regex -- compiled regex for parsing the input string
+                         Defaults to RE_WILDCARD_PACKAGE
+
+
+      Raises: InvalidTokenInputString if created token is not valid
+
+      """
       re_match = package_regex.match ( input_str )
 
       if not re_match:
@@ -266,34 +343,79 @@ class AdditionControlPackageRuleGenerator (
    # --- end of create_token (...) ---
 
    def create_token_for_ebuild_filepath ( self, efile ):
+      """Like create_token(), but passes a regex suitable for parsing
+      ebuild file paths.
+
+      Returns: tuple(CategoryToken,PackageToken)
+
+      arguments:
+      * efile -- ebuild file path
+
+
+      Raises: InvalidTokenInputString if created token is not valid
+
+      """
       return self.create_token (
          efile, with_category=True, package_regex=RE_PACKAGE_EBUILD_FILE
       )
    # --- end of create_token_for_ebuild_filepath (...) ---
 
    def create_package_token ( self, input_str ):
+      """Creates a package token, validates and returns it.
+
+      Returns: PackageToken
+
+      arguments:
+      * input_str -- string that should be converted to a token
+
+
+      Raises: InvalidTokenInputString if created token is not valid
+
+      """
       return self.create_token ( input_str, with_category=False )
    # --- end of create_package_token (...) ---
 
 
    def __init__ ( self, default_category ):
+      """AdditionControlPackageRuleGenerator constructor.
+
+      arguments:
+      * default_category -- name of the default overlay category, e.g. "sci-R"
+      """
       super ( AdditionControlPackageRuleGenerator, self ).__init__()
       self.namespace        = roverlay.util.namespace.SimpleNamespace()
       self.default_category = default_category
    # --- end of __init__ (...) ---
 
    def clear_object_cache ( self ):
+      """Clears the object cache (self.namespace)."""
       if self.namespace:
          self.namespace.zap(True)
    # --- end of clear_object_cache (...) ---
 
    def __del__ ( self ):
+      """on-delete: clear_object_cache()"""
       try:
          self.clear_object_cache()
       except NotImplementedError:
          pass
 
    def token_item_to_acceptor ( self, token_item, value_getter, priority ):
+      """Converts a token item (True, None or a TokenItemTuple) into a package
+      rule acceptor.
+
+      Returns: acceptor (StringAcceptor, ExactRegexAcceptor)
+               or None (no acceptor created)
+
+      arguments:
+      * token_item    -- token item
+      * value_getter  -- helper function for the acceptor that retrieves
+                         the value to be matched from a PackageInfo object
+      * priority      -- priority of the acceptor
+
+      Raises: AssertionError if the token item's value type is unknown.
+      """
+
       if token_item in ( True, None ):
          # should be catched elsewhere
          return None
@@ -317,6 +439,14 @@ class AdditionControlPackageRuleGenerator (
    # --- end of token_item_to_acceptor (...) ---
 
    def category_token_to_acceptor ( self, category_token, priority ):
+      """Converts a category token into a package rule acceptor.
+
+      Returns: acceptor
+
+      arguments:
+      * category_token -- must be valid
+      * priority       --
+      """
       assert category_token and category_token is not True
 
       return self.token_item_to_acceptor (
@@ -325,6 +455,18 @@ class AdditionControlPackageRuleGenerator (
    # --- end of category_token_to_acceptor (...) ---
 
    def package_token_to_acceptor ( self, package_token, priority ):
+      """Converts a package token into a package rule acceptor.
+
+      Returns: acceptor or acceptor compound
+
+      arguments:
+      * package_token -- must be valid
+      * priority      --
+
+
+      Raises: TokenValueError
+
+      """
       assert package_token and package_token is not True
 
       relevant_items = [
@@ -364,17 +506,41 @@ class BitmaskMapCreator ( object ):
    """creates a "bitmask" => "acceptor chain" map"""
 
    def __init__ ( self, rule_generator ):
+      """BitmaskMapCreator constructor.
+
+      arguments:
+      * rule_generator -- package rule generator object that this object
+                          should bind to.
+                          Responsible for creating tokens.
+      """
       super ( BitmaskMapCreator, self ).__init__()
       self.rule_generator = rule_generator
       self.data           = rule_generator.create_new_bitmask_map()
 
    def get_bitmask_map ( self ):
+      """Returns the bitmask map as reference."""
       return self.data
 
    def get_bitmask_map_copy ( self ):
+      """Returns a copy of the bitmask map."""
       return self.data.copy()
 
    def _insert_package ( self, bitmask_arg, package_str, package_regex ):
+      """Adds a package to the bitmask map.
+
+      Returns: None (implicit)
+
+      arguments:
+      * bitmask_arg   -- bitmask int or str (comma-separated list of words)
+      * package_str   -- package input string, e.g. "sci-R/seewave"
+                          (format depends on package_regex)
+      * package_regex -- regex for parsing package_str
+
+
+      Raises: ValueError if bitmask_arg not valid
+
+      """
+
       category_token, package_token = self.rule_generator.create_token (
          package_str, with_category=True, package_regex=package_regex
       )
@@ -385,6 +551,7 @@ class BitmaskMapCreator ( object ):
          bitmask_int = int ( bitmask_arg )
 
 
+      # self.data -> category_token -> package_token |= bitmask_int
       try:
          cat_entry = self.data [category_token]
       except KeyError:
@@ -401,12 +568,21 @@ class BitmaskMapCreator ( object ):
    # --- end of _insert_package (...) ---
 
    def _split_bitmask_line ( self, line, default_bitmask ):
+      """Splits a "[<bitmask> ]<package_str> line.
+
+      arguments:
+      * line            --
+      * default_bitmask -- default bitmask or None
+
+      Raises: ValueError if line contains no bitmask
+              and default_bitmask is not set
+      """
       # str<[bitmask,]arg> => ( bitmask||default_bitmask, arg )
       args = line.split ( None, 1 )
 
       if len(args) == 2:
          # convert bitmask str now
-         return ( AdditionControlResult.convert_str(args[0]), args[1] )
+         return ( AdditionControlResult.convert_str ( args[0] ), args[1] )
 
       elif default_bitmask or (
          default_bitmask == 0 and default_bitmask is not False
@@ -421,13 +597,19 @@ class BitmaskMapCreator ( object ):
    def _insert_packages_v (
       self, bitmask, arglist, package_regex, extended_format
    ):
+      """Adds zero or more package strings to the bitmask map.
+
+      arguments:
+      * bitmask         -- bitmask (or default bitmask in extended format)
+      * arglist         -- list of <package_str> (or <bitmask> <package_str>)
+      * package_regex   -- regex for parsing <package_str>
+      * extended_format -- whether arglist is in extended format or not
+                            (add-policy bitmask embedded in input string)
+      """
       insert_package = self._insert_package
 
       if extended_format:
-         split_bitmask_line = self._split_bitmask_line
-
-         for arg in arglist:
-            call_args = split_bitmask_line ( arg, bitmask )
+         for call_args in map ( self._split_bitmask_line, arglist ):
             insert_package ( call_args[0], call_args[1], package_regex )
 
       else:
@@ -436,31 +618,63 @@ class BitmaskMapCreator ( object ):
    # --- end of _insert_packages_v (...) ---
 
    def insert_packages_v ( self, bitmask, packages, extended_format=False ):
+      """Adds zero or more packages to the bitmask map.
+
+      arguments:
+      * bitmask         --
+      * packages        --
+      * extended_format --
+      """
+      # package in this context: ${CATEGORY}/${PF} or ${PF}
       self._insert_packages_v (
          bitmask, packages, RE_WILDCARD_PACKAGE, extended_format
       )
    # --- end of insert_packages_v (...) ---
 
    def insert_package ( self, bitmask, package, *args, **kwargs ):
+      """Adds a package to the bitmask map.
+
+      arguments:
+      * bitmask         --
+      * package         --
+      * *args, **kwargs -- passed to insert_packages_v()
+      """
       self.insert_packages_v ( bitmask, ( package, ), *args, **kwargs )
 
    def insert_packages ( self, bitmask, *packages, **kwargs ):
+      """varargs-variant f insert_packages_v()."""
       self.insert_packages_v ( bitmask, packages, **kwargs )
 
    def insert_ebuild_files_v (
       self, bitmask, ebuild_files, extended_format=False
    ):
+      """Adds zero or more ebuild file paths to the bitmask map.
+
+      arguments:
+      * bitmask         --
+      * ebuild_files    --
+      * extended_format --
+      """
+      # ebuild file: [<overlay>/]${CATEGORY}/${PN}/${PF}.ebuild
       self._insert_packages_v (
          bitmask, ebuild_files, RE_PACKAGE_EBUILD_FILE, extended_format
       )
    # --- end of insert_ebuild_files_v (...) ---
 
    def insert_ebuild_file ( self, bitmask, ebuild_file, *args, **kwargs ):
+      """Adds an ebuild file path to the bitmask map.
+
+      arguments:
+      * bitmask         --
+      * ebuild_file     --
+      * *args, **kwargs -- passed to insert_ebuild_files_v()
+      """
       self.insert_ebuild_files_v (
          bitmask, ( ebuild_file, ), *args, **kwargs
       )
 
    def insert_ebuild_files ( self, bitmask, *ebuild_files, **kwargs ):
+      """varargs-variant of insert_ebuild_files_v()."""
       self.insert_ebuild_files_v ( bitmask, ebuild_files, **kwargs )
 
 
@@ -468,6 +682,8 @@ class BitmaskMapCreator ( object ):
       bitmask, package_list=None, ebuild_file_list=None,
       extended_format=False
    ):
+      """combined insert_packages_v()/insert_ebuild_files_v()."""
+      # FIXME: CANDIDATE FOR REMOVAL (rev-dep: feed_from_file())
       if package_list:
          self.insert_packages_v ( bitmask, package_list, extended_format )
 
@@ -483,6 +699,7 @@ class BitmaskMapCreator ( object ):
       self, bitmask, package_list_file=None, ebuild_list_file=None,
       extended_format=False,
    ):
+      """Reads files and calls insert_packages_v()/insert_ebuild_files_v()."""
       # or ebuild_file_list_file
 
       self.feed (
@@ -499,6 +716,12 @@ class BitmaskMapCreator ( object ):
 
 def create_addition_control_package_rule (
    default_category,
+   # *,  ## force keyword-only, py3 only
+
+   extended_default_bitmask             = (
+      AdditionControlResult.PKG_REVBUMP_ON_COLLISION | \
+      AdditionControlResult.PKG_REPLACE_ONLY
+   ),
 
    cmdline_package_default              = None,
    cmdline_package_force_deny           = None,
@@ -533,7 +756,7 @@ def create_addition_control_package_rule (
    file_ebuild_revbump_on_collision     = None,
 
    file_package_extended                = None,
-   file_ebuild_extended                 = None,
+   file_ebuild_extended                 = None
 ):
    """All-in-one function that takes lists of packages, ebuild paths, list
    files, ... as input, creates a "bitmask" -> "acceptor chain" map and
@@ -553,10 +776,25 @@ def create_addition_control_package_rule (
    * cmdline_ebuild_<policy>  -- list of ebuilds  [None]
    * file_package_<policy>    -- package list file[s] [None]
    * file_ebuild_<policy>     -- ebuild  list file[s] [None]
+   * cmdline_package_extended -- package list in extended format [None]
+   * cmdline_ebuild_extended  -- ebuild  list in extended format [None]
    * file_package_extended    -- package list file[s] in extended format [None]
    * file_ebuild_extended     -- ebuild  list file[s] in extended format [None]
+   * extended_default_bitmask -- default bitmask for lists/files
+                                 in extended format list files. Can be None
+                                 Defaults to revbump-on-collision,replace-only
+
+
+   Raises:
+   * ValueError if default_category not valid
+   * passes exceptions from rule generator / bitmask map creator
+
 
    Note: file_* parameters support only a single input file, currently.
+
+   Note: cmdline_*, file_* should be passed as keyword arguments only!
+         (There's no good way to enforce this in python 2 except for **kwargs,
+          which in turn would accept invalid args...)
    """
    argv_locals = locals().copy()
    get_args    = lambda pre, attr_name: (

diff --git a/roverlay/runtime.py b/roverlay/runtime.py
index 521eb0e..fd45425 100644
--- a/roverlay/runtime.py
+++ b/roverlay/runtime.py
@@ -207,6 +207,16 @@ class RuntimeEnvironment ( RuntimeEnvironmentBase ):
    # --- end of get_overlay_creator (...) ---
 
    def create_addition_control_rules ( self, default_category=None ):
+      """Creates addition control package rules from cmdline/config.
+
+      Returns: a package rule object or None
+
+      arguments:
+      * default_category -- name of the default category
+                             Can be None/"false", in which case it is
+                             queried from self.config
+                             Defaults to None.
+      """
       kwargs = {}
       def add_key ( k, _kwargs=kwargs, _options=self.options ):
          _kwargs [k] = _options [k]
@@ -230,6 +240,17 @@ class RuntimeEnvironment ( RuntimeEnvironmentBase ):
    def add_addition_control_rules (
       self, package_rules, default_category=None
    ):
+      """Adds addition control rules to the given package rules object.
+
+      Returns True if add-policy rules have been added and False if not
+      (i.e. no rules configured).
+
+      See also create_addition_control_rules().
+
+      arguments:
+      * package_rules    --
+      * default_category --
+      """
       add_control_rule = self.create_addition_control_rules (
          default_category = default_category
       )
@@ -242,6 +263,16 @@ class RuntimeEnvironment ( RuntimeEnvironmentBase ):
    # --- end of add_addition_control_rules (...) ---
 
    def add_addition_control_to_overlay_creator ( self ):
+      """Adds addition control to the overlay creator.
+      Currently, this is limited to add-policy package rules.
+
+      The overlay creator and its package rules have to be initialized
+      with get_overlay_creator() before calling this method.
+
+      Returns True if any addition control has been added, else False.
+
+      arguments: none
+      """
       if not self._overlay_creator:
          raise AssertionError ( "overlay creator not initialized." )
       elif not getattr ( self._overlay_creator, 'package_rules', None ):


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

end of thread, other threads:[~2014-07-18 16:20 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-07-18 14:55 [gentoo-commits] proj/R_overlay:wip/addition_control commit in: roverlay/packagerules/generators/abstract/, roverlay/packagerules/generators/, André Erdmann
2014-07-18 16:20 ` [gentoo-commits] proj/R_overlay:master " André Erdmann

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