diff options
author | André Erdmann <dywi@mailerd.de> | 2014-07-18 16:30:22 +0200 |
---|---|---|
committer | André Erdmann <dywi@mailerd.de> | 2014-07-18 16:30:22 +0200 |
commit | 617d1f739c35e8a4b4e10781a7eecfb11191f01c (patch) | |
tree | 3f8d706dc87096d756f965ca4b50fa337ee16a44 /roverlay | |
parent | roverlay/runtime: fix add_addition_control_rules() (diff) | |
download | R_overlay-617d1f739c35e8a4b4e10781a7eecfb11191f01c.tar.gz R_overlay-617d1f739c35e8a4b4e10781a7eecfb11191f01c.tar.bz2 R_overlay-617d1f739c35e8a4b4e10781a7eecfb11191f01c.zip |
addition control: in-code __doc__
Diffstat (limited to 'roverlay')
-rw-r--r-- | roverlay/overlay/abccontrol.py | 19 | ||||
-rw-r--r-- | roverlay/packagerules/actions/addition_control.py | 4 | ||||
-rw-r--r-- | roverlay/packagerules/generators/abstract/base.py | 3 | ||||
-rw-r--r-- | roverlay/packagerules/generators/addition_control.py | 262 | ||||
-rw-r--r-- | 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 ): |