def test_value_ranking(self): o = OptionValueContainer() o.foo = RankedValue(RankedValue.CONFIG, 11) self.assertEqual(11, o.foo) self.assertEqual(RankedValue.CONFIG, o.get_rank('foo')) o.foo = RankedValue(RankedValue.HARDCODED, 22) self.assertEqual(11, o.foo) self.assertEqual(RankedValue.CONFIG, o.get_rank('foo')) o.foo = RankedValue(RankedValue.ENVIRONMENT, 33) self.assertEqual(33, o.foo) self.assertEqual(RankedValue.ENVIRONMENT, o.get_rank('foo')) o.foo = RankedValue(RankedValue.FLAG, 44) self.assertEqual(44, o.foo) self.assertEqual(RankedValue.FLAG, o.get_rank('foo'))
def test_value_ranking(self) -> None: o = OptionValueContainer() o.foo = RankedValue(RankedValue.CONFIG, 11) self.assertEqual(11, o.foo) self.assertEqual(RankedValue.CONFIG, o.get_rank("foo")) o.foo = RankedValue(RankedValue.HARDCODED, 22) self.assertEqual(11, o.foo) self.assertEqual(RankedValue.CONFIG, o.get_rank("foo")) o.foo = RankedValue(RankedValue.ENVIRONMENT, 33) self.assertEqual(33, o.foo) self.assertEqual(RankedValue.ENVIRONMENT, o.get_rank("foo")) o.foo = RankedValue(RankedValue.FLAG, 44) self.assertEqual(44, o.foo) self.assertEqual(RankedValue.FLAG, o.get_rank("foo"))
def test_value_ranking(self): o = OptionValueContainer() o.foo = RankedValue(RankedValue.CONFIG, 11) self.assertEqual(11, o.foo) self.assertEqual(RankedValue.CONFIG, o.get_rank('foo')) o.foo = RankedValue(RankedValue.HARDCODED, 22) self.assertEqual(11, o.foo) self.assertEqual(RankedValue.CONFIG, o.get_rank('foo')) o.foo = RankedValue(RankedValue.ENVIRONMENT, 33) self.assertEqual(33, o.foo) self.assertEqual(RankedValue.ENVIRONMENT, o.get_rank('foo')) o.foo = 44 # No explicit rank is assumed to be a FLAG. self.assertEqual(44, o.foo) self.assertEqual(RankedValue.FLAG, o.get_rank('foo'))
def test_value_ranking(self): o = OptionValueContainer() o.add_forwardings({'foo': 'bar'}) o.bar = RankedValue(RankedValue.CONFIG, 11) self.assertEqual(11, o.foo) self.assertEqual(RankedValue.CONFIG, o.get_rank('foo')) o.bar = RankedValue(RankedValue.HARDCODED, 22) self.assertEqual(11, o.foo) self.assertEqual(RankedValue.CONFIG, o.get_rank('foo')) o.bar = RankedValue(RankedValue.ENVIRONMENT, 33) self.assertEqual(33, o.foo) self.assertEqual(RankedValue.ENVIRONMENT, o.get_rank('foo')) o.bar = 44 # No explicit rank is assumed to be a FLAG. self.assertEqual(44, o.foo) self.assertEqual(RankedValue.FLAG, o.get_rank('foo'))
def for_scope(self, scope): """Return the option values for the given scope. Values are attributes of the returned object, e.g., options.foo. Computed lazily per scope. """ # Short-circuit, if already computed. if scope in self._values_by_scope: return self._values_by_scope[scope] # First get enclosing scope's option values, if any. if scope == GLOBAL_SCOPE: values = OptionValueContainer() else: values = copy.deepcopy(self.for_scope(enclosing_scope(scope))) # Now add our values. flags_in_scope = self._scope_to_flags.get(scope, []) self._parser_hierarchy.get_parser_by_scope(scope).parse_args(flags_in_scope, values) self._values_by_scope[scope] = values for option in values: self._option_tracker.record_option( scope=scope, option=option, value=values[option], rank=values.get_rank(option) ) return values
def for_scope(self, scope): """Return the option values for the given scope. Values are attributes of the returned object, e.g., options.foo. Computed lazily per scope. :API: public """ # Short-circuit, if already computed. if scope in self._values_by_scope: return self._values_by_scope[scope] # First get enclosing scope's option values, if any. if scope == GLOBAL_SCOPE: values = OptionValueContainer() else: values = copy.copy(self.for_scope(enclosing_scope(scope))) # Now add our values. flags_in_scope = self._scope_to_flags.get(scope, []) self._parser_hierarchy.get_parser_by_scope(scope).parse_args( flags_in_scope, values) self._values_by_scope[scope] = values for option in values: self._option_tracker.record_option(scope=scope, option=option, value=values[option], rank=values.get_rank(option)) return values
def for_scope(self, scope, inherit_from_enclosing_scope=True): """Return the option values for the given scope. Values are attributes of the returned object, e.g., options.foo. Computed lazily per scope. :API: public """ # Short-circuit, if already computed. if scope in self._values_by_scope: return self._values_by_scope[scope] # First get enclosing scope's option values, if any. if scope == GLOBAL_SCOPE or not inherit_from_enclosing_scope: values = OptionValueContainer() else: values = copy.copy(self.for_scope(enclosing_scope(scope))) # Now add our values. flags_in_scope = self._scope_to_flags.get(scope, []) self._parser_hierarchy.get_parser_by_scope(scope).parse_args( flags_in_scope, values) # If we're the new name of a deprecated scope, also get values from that scope. deprecated_scope = self.known_scope_to_info[scope].deprecated_scope # Note that deprecated_scope and scope share the same Optionable class, so deprecated_scope's # Optionable has a deprecated_options_scope equal to deprecated_scope. Therefore we must # check that scope != deprecated_scope to prevent infinite recursion. if deprecated_scope is not None and scope != deprecated_scope: # Do the deprecation check only on keys that were explicitly set on the deprecated scope # (and not on its enclosing scopes). explicit_keys = self.for_scope( deprecated_scope, inherit_from_enclosing_scope=False).get_explicit_keys() if explicit_keys: warn_or_error( self.known_scope_to_info[scope]. deprecated_scope_removal_version, 'scope {}'.format(deprecated_scope), 'Use scope {} instead (options: {})'.format( scope, ', '.join(explicit_keys))) # Update our values with those of the deprecated scope (now including values inherited # from its enclosing scope). # Note that a deprecated val will take precedence over a val of equal rank. # This makes the code a bit neater. values.update(self.for_scope(deprecated_scope)) # Record the value derivation. for option in values: self._option_tracker.record_option(scope=scope, option=option, value=values[option], rank=values.get_rank(option)) # Cache the values. self._values_by_scope[scope] = values return values
def for_scope(self, scope, inherit_from_enclosing_scope=True): """Return the option values for the given scope. Values are attributes of the returned object, e.g., options.foo. Computed lazily per scope. :API: public """ # Short-circuit, if already computed. if scope in self._values_by_scope: return self._values_by_scope[scope] # First get enclosing scope's option values, if any. if scope == GLOBAL_SCOPE or not inherit_from_enclosing_scope: values = OptionValueContainer() else: values = copy.copy(self.for_scope(enclosing_scope(scope))) # Now add our values. flags_in_scope = self._scope_to_flags.get(scope, []) self._parser_hierarchy.get_parser_by_scope(scope).parse_args(flags_in_scope, values) # If we're the new name of a deprecated scope, also get values from that scope. deprecated_scope = self.known_scope_to_info[scope].deprecated_scope # Note that deprecated_scope and scope share the same Optionable class, so deprecated_scope's # Optionable has a deprecated_options_scope equal to deprecated_scope. Therefore we must # check that scope != deprecated_scope to prevent infinite recursion. if deprecated_scope is not None and scope != deprecated_scope: # Do the deprecation check only on keys that were explicitly set on the deprecated scope # (and not on its enclosing scopes). explicit_keys = self.for_scope(deprecated_scope, inherit_from_enclosing_scope=False).get_explicit_keys() if explicit_keys: warn_or_error(self.known_scope_to_info[scope].deprecated_scope_removal_version, 'scope {}'.format(deprecated_scope), 'Use scope {} instead (options: {})'.format(scope, ', '.join(explicit_keys))) # Update our values with those of the deprecated scope (now including values inherited # from its enclosing scope). # Note that a deprecated val will take precedence over a val of equal rank. # This makes the code a bit neater. values.update(self.for_scope(deprecated_scope)) # Record the value derivation. for option in values: self._option_tracker.record_option(scope=scope, option=option, value=values[option], rank=values.get_rank(option)) # Cache the values. self._values_by_scope[scope] = values return values