diff options
author | 2014-07-16 17:04:05 +0200 | |
---|---|---|
committer | 2014-07-16 17:04:05 +0200 | |
commit | f8a895f1c176f1b74f0f2c1b55e988c545be338f (patch) | |
tree | 8363105eae0471ffad4308208afe612b52c0c70a | |
parent | addition control rule gen: partial implementation (diff) | |
download | R_overlay-f8a895f1c176f1b74f0f2c1b55e988c545be338f.tar.gz R_overlay-f8a895f1c176f1b74f0f2c1b55e988c545be338f.tar.bz2 R_overlay-f8a895f1c176f1b74f0f2c1b55e988c545be338f.zip |
addition control rule gen: in-code documentation
-rw-r--r-- | roverlay/packagerules/generators/addition_control.py | 218 |
1 files changed, 194 insertions, 24 deletions
diff --git a/roverlay/packagerules/generators/addition_control.py b/roverlay/packagerules/generators/addition_control.py index 20c4b29..73040e0 100644 --- a/roverlay/packagerules/generators/addition_control.py +++ b/roverlay/packagerules/generators/addition_control.py @@ -66,19 +66,50 @@ from roverlay.overlay.abccontrol import AdditionControlResult class AbstractAdditionControlPackageRuleGenerator ( _AbstractObject ): + """(Abstract) object that takes cmdline/files as input and creates + add-policy package rules.""" - #CategoryToken = collections.namedtuple ( 'CategoryToken', '<attr>' ) - #PackageToken = collections.namedtuple ( 'PackageToken', '<attr>' ) + # Note that tokens are not totally abstract, + # the "match-all" (True) token is hardcoded + + #CategoryToken = collections.namedtuple ( 'CategoryToken', '<attr>*' ) + #PackageToken = collections.namedtuple ( 'PackageToken', '<attr>*' ) @abc.abstractmethod def category_token_to_acceptor ( self, category_token, priority ): + """Creates a package rule acceptor for the given category token. + + Returns: not-None acceptor (or nested acceptor) + + Must not return None. + If a token is meaningless, then don't create it in the first place. + + arguments: + * category_token -- a category token + * priority -- priority of the acceptor (int) + """ raise NotImplementedError() + # --- end of category_token_to_acceptor (...) --- @abc.abstractmethod - def package_token_to_acceptor ( self, category_token, priority ): + def package_token_to_acceptor ( self, package_token, priority ): + """Creates a package rule acceptor for the given package token. + + Returns: not-None acceptor (or nested acceptor) + + arguments: + * package_token -- a package token + * priority -- priority of the acceptor (int) + """ raise NotImplementedError() + # --- end of package_token_to_acceptor (...) --- def create_package_rules ( self, reduced_bitmask_acceptor_chain_map ): + """Creates a nested add-policy package rule object. + The rule object's priority has to be set manually afterwards. + + Returns: (nested) package rule or None + """ # create_package_rules() is defined/implemented below (step 5) return create_package_rules ( reduced_bitmask_acceptor_chain_map, @@ -87,16 +118,51 @@ class AbstractAdditionControlPackageRuleGenerator ( _AbstractObject ): ) # --- end of create_package_rules (...) --- -# --- end of AbstractAdditionControlPackageRuleGenerator --- + def prepare_bitmask_map ( self, acceptor_chain_bitmask_map ): + """Transforms the given "acceptor chain" -> "bitmask" map into the + reduced "effective bitmask" -> "acceptor chain" map. + Note: Involves in-place operations that modify + acceptor_chain_bitmask_map. + Pass a copy if the original map should remain unchanged. -def abstract_category_token_to_acceptor ( category_token, priority, namespace ): - raise NotImplementedError() -# --- end of abstract_category_token_to_acceptor (...) --- + Returns: reduced/optimized "effective bitmask" -> "acceptor chain" -def abstract_package_token_to_acceptor ( package_token, priority, namespace ): - raise NotImplementedError() -# --- end of abstract_package_token_to_acceptor (...) --- + arguments: + * acceptor_chain_bitmask_map -- "acceptor chain" -> "bitmask" map + """ + expand_acceptor_chain_bitmasks ( acceptor_chain_bitmask_map ) + + bitmask_acceptor_chain_map = ( + create_bitmask_acceptor_chain_map ( acceptor_chain_bitmask_map ) + ) + + reduce_bitmask_acceptor_chain_map ( bitmask_acceptor_chain_map ) + + return bitmask_acceptor_chain_map + # --- end of prepare_bitmask_map (...) --- + + def compile_bitmask_map ( self, acceptor_chain_bitmask_map ): + """Transforms the given "acceptor chain" -> "bitmask" map into a + (nested) package rule. + + This is equal to calling + obj.create_package_rules ( + obj.prepare_bitmask_map ( acceptor_chain_bitmask_map ) + ) + + Returns: (nested) rule object or None + + arguments: + * acceptor_chain_bitmask_map -- "acceptor chain" -> "bitmask" map + """ + return self.create_package_rules ( + prepare_bitmask_map ( acceptor_chain_bitmask_map ) + ) + # --- end of compile_bitmask_map (...) --- + + +# --- end of AbstractAdditionControlPackageRuleGenerator --- # @@ -122,19 +188,45 @@ def abstract_package_token_to_acceptor ( package_token, priority, namespace ): # def expand_acceptor_chain_bitmasks ( acceptor_chain_bitmask_map ): + """Expands a "acceptor chain" -> "bitmask" map. + (Sets the effective bitmask, propagates global bitmasks, ...) + + In-place operation that modifies the acceptor_chain_bitmask_map arg. + + Returns: None (implicit) + + arguments: + * acceptor_chain_bitmask_map -- "acceptor chain" -> "bitmask" map + """ # naming convention: >e<ffective bit>mask< => emask - # inplace operation (returns None and modifies the obj directly) get_emask = AdditionControlResult.get_effective_package_policy - def normalize_entry ( mapping, key, additional_emask=0 ): + """Determines and sets the effective bitmask of mapping->key. + + Returns: None (implicit) + + arguments: + * mapping -- dict-like object + * key -- dict key (has to exist) + * additional_emask -- effective bitmask that should be propagated to + mapping->key (global/category-wide bitmask) + """ new_value = get_emask ( mapping [key] | additional_emask ) mapping [key] = new_value return new_value # --- end of normalize_entry (...) --- def normalize_entry_maybe_missing ( mapping, key, additional_emask=0 ): + """Like normalize_entry(), but does not require the existence of + mapping->key (the entry will be created if necessary). + + arguments: + * mapping -- + * key -- + * additional_emask -- + """ if key in mapping: return normalize_entry ( mapping, key, additional_emask ) else: @@ -142,8 +234,6 @@ def expand_acceptor_chain_bitmasks ( acceptor_chain_bitmask_map ): return additional_emask # --- end of normalize_entry_maybe_missing (...) --- - - # propagate global/category-wide emask to package_token entries # acceptor_chain_bitmask_map->True->True is the global emask @@ -194,6 +284,17 @@ def expand_acceptor_chain_bitmasks ( acceptor_chain_bitmask_map ): # def create_bitmask_acceptor_chain_map ( acceptor_chain_bitmask_map ): + """Transforms a "acceptor chain" -> "[effective] bitmask" map + into a "[effective] bitmask" -> "acceptor chain" mask without applying + any optimization/reduction steps. + + Returns: "[effective] bitmask" -> "acceptor chain" map + + arguments: + * acceptor_chain_bitmask_map -- "acceptor chain" -> "bitmask" map + Should be in expanded form + (expand_acceptor_chain_bitmasks()) + """ bitmask_acceptor_chain_map = {} for category_token, package_token_map in acceptor_chain_bitmask_map.items(): @@ -264,14 +365,23 @@ def create_bitmask_acceptor_chain_map ( acceptor_chain_bitmask_map ): # def reduce_bitmask_acceptor_chain_map ( bitmask_acceptor_chain_map ): + """Reduces/Optimizes a "effective bitmask" -> "acceptor chain" map. + + In-place operation, the bitmask_acceptor_chain_map will be modified. + + Returns: None (implicit) + + arguments: + * bitmask_acceptor_chain_map -- "effective bitmask" -> "acceptor chain" map + + Implementation detail: + The reduced map uses empty sets/dicts for representing "match-all" + acceptors. + """ + # could be integrated in create_bitmask_acceptor_chain_map(), # but kept separate for better readability # - # Note that the actual implementation uses empty sets/dicts in the - # reduced bitmask->acceptor chain mask to represent "match-all". - # - - # ** inplace ** # emask==0 can be ignored bitmask_acceptor_chain_map.pop ( 0, True ) @@ -317,7 +427,12 @@ def reduce_bitmask_acceptor_chain_map ( bitmask_acceptor_chain_map ): # def create_packagerule_action_map(): - # dict < int~2**k => packagerule action > + """Helper function that creates all add-policy package rule actions. + + Returns: dict ( "bitmask atom" (2**k) -> "package rule action" ) + + arguments: None + """ return { action_cls.CONTROL_RESULT: action_cls ( priority=action_cls.CONTROL_RESULT @@ -334,12 +449,24 @@ def create_packagerule_action_map(): # --- end of create_packagerule_action_map (...) --- - def create_package_rules ( reduced_bitmask_acceptor_chain_map, convert_category_token_to_acceptor, convert_package_token_to_acceptor ): + """Converts the given "effective bitmask" -> "acceptor chain" map + into a nested package rule. + + Returns: (nested) package rule or None + + arguments: + * reduced_bitmask_acceptor_chain_map -- reduced/optimized + "bitmask" -> "acceptor chain" map + * convert_category_token_to_acceptor -- function(token,priority) + -> category acceptor + * convert_package_token_to_acceptor -- function(token,priority) + -> package acceptor + """ packagerule_actions = create_packagerule_action_map() # true acceptor with priority -1 always_true_acceptor = ( @@ -348,6 +475,18 @@ def create_package_rules ( def get_acceptor_recursive ( category_token_map, priority ): + """ + Creates a (possibly nested) acceptor for the given category_token_map. + + Returns: not-None acceptor + + arguments: + * category_token_map -- "category token" -> "package token" map + ("acceptor chain") + * priority -- "recommended" priority of the acceptor + Ignored when returning an always-true acceptor. + """ + # Note: it's illegal to set an acceptor's priority after its creation # this would violate namespace->get_object() # ==> use 0 as priority for objects where it doesn't matter much @@ -367,6 +506,16 @@ def create_package_rules ( # def get_package_acceptor ( package_tokens, prio ): + """Creates a (nested) acceptor for the given non-empty iterable + of package tokens. + + Returns: not-None acceptor + + arguments: + * package_tokens -- iterable of package tokens (not empty) + * prio -- advised priority of the top-most acceptor + (the object being returned) + """ if not package_tokens: raise ValueError ( "package token set must not be empty!" ) @@ -395,6 +544,16 @@ def create_package_rules ( # --- end of get_package_acceptor (...) --- def get_category_acceptor ( category_token, package_tokens, prio ): + """Creates a nested acceptor for the given category token and its + package tokens. + + Returns: not-None acceptor + + arguments: + * category_token -- category token (True or non-empty) + * package_tokens -- iterable of package tokens (can be empty) + """ + if category_token is True: return get_package_acceptor ( package_tokens, prio ) @@ -455,6 +614,17 @@ def create_package_rules ( # --- end of get_acceptor_recursive (...) --- def create_rule ( category_token_map, emask ): + """Creates a package rule for the given acceptor chain + ("category token" -> "package tokens" map) + + Returns: not-None not-nested package rule (with a nested match block) + + arguments: + * category_token_map -- acceptor chain + * emask -- effective bitmask that gets translated into + its corresponding package rule actions + """ + # wrap actual acceptor with Acceptor_AND, see above actual_acceptor = get_acceptor_recursive ( category_token_map, 0 ) and_acceptor = roverlay.packagerules.abstract.acceptors.Acceptor_AND (0) @@ -521,15 +691,15 @@ class SillyAdditionControlPackageRuleGenerator ( super ( SillyAdditionControlPackageRuleGenerator, self ).__init__() self.namespace = roverlay.util.namespace.SimpleNamespace() - def _get_true_accepor_from_namespace ( self, any_token, priority ): + def _get_true_acceptor_from_namespace ( self, any_token, priority ): return self.namespace.get_object_v ( roverlay.packagerules.acceptors.trivial.TrueAcceptor, ( priority, ), {} ) - category_token_to_acceptor = _get_true_accepor_from_namespace - package_token_to_acceptor = _get_true_accepor_from_namespace + category_token_to_acceptor = _get_true_acceptor_from_namespace + package_token_to_acceptor = _get_true_acceptor_from_namespace |