def DEFINE_flag(flag, flag_values=_flagvalues.FLAGS, module_name=None): """Registers a 'Flag' object with a 'FlagValues' object. By default, the global FLAGS 'FlagValue' object is used. Typical users will use one of the more specialized DEFINE_xxx functions, such as DEFINE_string or DEFINE_integer. But developers who need to create Flag objects themselves should use this function to register their flags. Args: flag: Flag, a flag that is key to the module. flag_values: FlagValues, the FlagValues instance with which the flag will be registered. This should almost never need to be overridden. module_name: str, the name of the Python module declaring this flag. If not provided, it will be computed using the stack trace of this call. """ # Copying the reference to flag_values prevents pychecker warnings. fv = flag_values fv[flag.name] = flag # Tell flag_values who's defining the flag. if module_name: module = sys.modules.get(module_name) else: module, module_name = _helpers.get_calling_module_object_and_name() flag_values.register_flag_by_module(module_name, flag) flag_values.register_flag_by_module_id(id(module), flag)
def DEFINE_flag(flag, flag_values=_flagvalues.FLAGS, module_name=None): # pylint: disable=invalid-name """Registers a 'Flag' object with a 'FlagValues' object. By default, the global FLAGS 'FlagValue' object is used. Typical users will use one of the more specialized DEFINE_xxx functions, such as DEFINE_string or DEFINE_integer. But developers who need to create Flag objects themselves should use this function to register their flags. Args: flag: Flag, a flag that is key to the module. flag_values: FlagValues, the FlagValues instance with which the flag will be registered. This should almost never need to be overridden. module_name: str, the name of the Python module declaring this flag. If not provided, it will be computed using the stack trace of this call. """ # Copying the reference to flag_values prevents pychecker warnings. fv = flag_values fv[flag.name] = flag # Tell flag_values who's defining the flag. if module_name: module = sys.modules.get(module_name) else: module, module_name = _helpers.get_calling_module_object_and_name() flag_values.register_flag_by_module(module_name, flag) flag_values.register_flag_by_module_id(id(module), flag)
def __setitem__(self, name, flag): """Registers a new flag variable.""" fl = self._flags() if not isinstance(flag, _flag.Flag): raise _exceptions.IllegalFlagValueError(flag) if str is bytes and isinstance(name, unicode): # When using Python 2 with unicode_literals, allow it but encode it # into the bytes type we require. name = name.encode('utf-8') if not isinstance(name, type('')): raise _exceptions.Error('Flag name must be a string') if not name: raise _exceptions.Error('Flag name cannot be empty') if ' ' in name: raise _exceptions.Error('Flag name cannot contain a space') self._check_method_name_conflicts(name, flag) if name in fl and not flag.allow_override and not fl[ name].allow_override: module, module_name = _helpers.get_calling_module_object_and_name() if (self.find_module_defining_flag(name) == module_name and id(module) != self.find_module_id_defining_flag(name)): # If the flag has already been defined by a module with the same name, # but a different ID, we can stop here because it indicates that the # module is simply being imported a subsequent time. return raise _exceptions.DuplicateFlagError.from_flag(name, self) short_name = flag.short_name # If a new flag overrides an old one, we need to cleanup the old flag's # modules if it's not registered. flags_to_cleanup = set() if short_name is not None: if (short_name in fl and not flag.allow_override and not fl[short_name].allow_override): raise _exceptions.DuplicateFlagError.from_flag( short_name, self) if short_name in fl and fl[short_name] != flag: flags_to_cleanup.add(fl[short_name]) fl[short_name] = flag if (name not in fl # new flag or fl[name].using_default_value or not flag.using_default_value): if name in fl and fl[name] != flag: flags_to_cleanup.add(fl[name]) fl[name] = flag for f in flags_to_cleanup: self._cleanup_unregistered_flag_from_module_dicts(f)
def DEFINE_flag( # pylint: disable=invalid-name flag, flag_values=_flagvalues.FLAGS, module_name=None, required=False): """Registers a 'Flag' object with a 'FlagValues' object. By default, the global FLAGS 'FlagValue' object is used. Typical users will use one of the more specialized DEFINE_xxx functions, such as DEFINE_string or DEFINE_integer. But developers who need to create Flag objects themselves should use this function to register their flags. Args: flag: Flag, a flag that is key to the module. flag_values: FlagValues, the FlagValues instance with which the flag will be registered. This should almost never need to be overridden. module_name: str, the name of the Python module declaring this flag. If not provided, it will be computed using the stack trace of this call. required: bool, is this a required flag. This must be used as a keyword argument. Returns: a handle to defined flag. """ if required and flag.default is not None: raise ValueError('Required flag --%s cannot have a non-None default' % flag.name) # Copying the reference to flag_values prevents pychecker warnings. fv = flag_values fv[flag.name] = flag # Tell flag_values who's defining the flag. if module_name: module = sys.modules.get(module_name) else: module, module_name = _helpers.get_calling_module_object_and_name() flag_values.register_flag_by_module(module_name, flag) flag_values.register_flag_by_module_id(id(module), flag) if required: _validators.mark_flag_as_required(flag.name, fv) ensure_non_none_value = (flag.default is not None) or required return _flagvalues.FlagHolder(fv, flag, ensure_non_none_value=ensure_non_none_value)
def __setitem__(self, name, flag): """Registers a new flag variable.""" fl = self._flags() if not isinstance(flag, _flag.Flag): raise _exceptions.IllegalFlagValueError(flag) if str is bytes and isinstance(name, unicode): # When using Python 2 with unicode_literals, allow it but encode it # into the bytes type we require. name = name.encode('utf-8') if not isinstance(name, type('')): raise _exceptions.Error('Flag name must be a string') if not name: raise _exceptions.Error('Flag name cannot be empty') if ' ' in name: raise _exceptions.Error('Flag name cannot contain a space') self._check_method_name_conflicts(name, flag) if name in fl and not flag.allow_override and not fl[name].allow_override: module, module_name = _helpers.get_calling_module_object_and_name() if (self.find_module_defining_flag(name) == module_name and id(module) != self.find_module_id_defining_flag(name)): # If the flag has already been defined by a module with the same name, # but a different ID, we can stop here because it indicates that the # module is simply being imported a subsequent time. return raise _exceptions.DuplicateFlagError.from_flag(name, self) short_name = flag.short_name # If a new flag overrides an old one, we need to cleanup the old flag's # modules if it's not registered. flags_to_cleanup = set() if short_name is not None: if (short_name in fl and not flag.allow_override and not fl[short_name].allow_override): raise _exceptions.DuplicateFlagError.from_flag(short_name, self) if short_name in fl and fl[short_name] != flag: flags_to_cleanup.add(fl[short_name]) fl[short_name] = flag if (name not in fl # new flag or fl[name].using_default_value or not flag.using_default_value): if name in fl and fl[name] != flag: flags_to_cleanup.add(fl[name]) fl[name] = flag for f in flags_to_cleanup: self._cleanup_unregistered_flag_from_module_dicts(f)
def test_unregistered_flags_are_cleaned_up(self): fv = _flagvalues.FlagValues() module, module_name = _helpers.get_calling_module_object_and_name() # Define first flag. _defines.DEFINE_integer('cores', 4, '', flag_values=fv, short_name='c') old_cores_flag = fv['cores'] fv.register_key_flag_for_module(module_name, old_cores_flag) self.assertEqual(fv.flags_by_module_dict(), {module_name: [old_cores_flag]}) self.assertEqual(fv.flags_by_module_id_dict(), {id(module): [old_cores_flag]}) self.assertEqual(fv.key_flags_by_module_dict(), {module_name: [old_cores_flag]}) # Redefine the same flag. _defines.DEFINE_integer('cores', 4, '', flag_values=fv, short_name='c', allow_override=True) new_cores_flag = fv['cores'] self.assertNotEqual(old_cores_flag, new_cores_flag) self.assertEqual(fv.flags_by_module_dict(), {module_name: [new_cores_flag]}) self.assertEqual(fv.flags_by_module_id_dict(), {id(module): [new_cores_flag]}) # old_cores_flag is removed from key flags, and the new_cores_flag is # not automatically added because it must be registered explicitly. self.assertEqual(fv.key_flags_by_module_dict(), {module_name: []}) # Define a new flag but with the same short_name. _defines.DEFINE_integer('changelist', 0, '', flag_values=fv, short_name='c', allow_override=True) old_changelist_flag = fv['changelist'] fv.register_key_flag_for_module(module_name, old_changelist_flag) # The short named flag -c is overridden to be the old_changelist_flag. self.assertEqual(fv['c'], old_changelist_flag) self.assertNotEqual(fv['c'], new_cores_flag) self.assertEqual(fv.flags_by_module_dict(), {module_name: [new_cores_flag, old_changelist_flag]}) self.assertEqual(fv.flags_by_module_id_dict(), {id(module): [new_cores_flag, old_changelist_flag]}) self.assertEqual(fv.key_flags_by_module_dict(), {module_name: [old_changelist_flag]}) # Define a flag only with the same long name. _defines.DEFINE_integer('changelist', 0, '', flag_values=fv, short_name='l', allow_override=True) new_changelist_flag = fv['changelist'] self.assertNotEqual(old_changelist_flag, new_changelist_flag) self.assertEqual( fv.flags_by_module_dict(), { module_name: [new_cores_flag, old_changelist_flag, new_changelist_flag] }) self.assertEqual(fv.flags_by_module_id_dict(), { id(module): [new_cores_flag, old_changelist_flag, new_changelist_flag] }) self.assertEqual(fv.key_flags_by_module_dict(), {module_name: [old_changelist_flag]}) # Delete the new changelist's long name, it should still be registered # because of its short name. del fv.changelist self.assertNotIn('changelist', fv) self.assertEqual( fv.flags_by_module_dict(), { module_name: [new_cores_flag, old_changelist_flag, new_changelist_flag] }) self.assertEqual(fv.flags_by_module_id_dict(), { id(module): [new_cores_flag, old_changelist_flag, new_changelist_flag] }) self.assertEqual(fv.key_flags_by_module_dict(), {module_name: [old_changelist_flag]}) # Delete the new changelist's short name, it should be removed. del fv.l self.assertNotIn('l', fv) self.assertEqual(fv.flags_by_module_dict(), {module_name: [new_cores_flag, old_changelist_flag]}) self.assertEqual(fv.flags_by_module_id_dict(), {id(module): [new_cores_flag, old_changelist_flag]}) self.assertEqual(fv.key_flags_by_module_dict(), {module_name: [old_changelist_flag]})
def _test_find_module_or_id_defining_flag(self, test_id): """Tests for find_module_defining_flag and find_module_id_defining_flag. Args: test_id: True to test find_module_id_defining_flag, False to test find_module_defining_flag. """ fv = _flagvalues.FlagValues() current_module, current_module_name = ( _helpers.get_calling_module_object_and_name()) alt_module_name = _flagvalues.__name__ if test_id: current_module_or_id = id(current_module) alt_module_or_id = id(_flagvalues) testing_fn = fv.find_module_id_defining_flag else: current_module_or_id = current_module_name alt_module_or_id = alt_module_name testing_fn = fv.find_module_defining_flag # Define first flag. _defines.DEFINE_integer('cores', 4, '', flag_values=fv, short_name='c') module_or_id_cores = testing_fn('cores') self.assertEqual(module_or_id_cores, current_module_or_id) module_or_id_c = testing_fn('c') self.assertEqual(module_or_id_c, current_module_or_id) # Redefine the same flag in another module. _defines.DEFINE_integer('cores', 4, '', flag_values=fv, module_name=alt_module_name, short_name='c', allow_override=True) module_or_id_cores = testing_fn('cores') self.assertEqual(module_or_id_cores, alt_module_or_id) module_or_id_c = testing_fn('c') self.assertEqual(module_or_id_c, alt_module_or_id) # Define a new flag but with the same short_name. _defines.DEFINE_integer('changelist', 0, '', flag_values=fv, short_name='c', allow_override=True) module_or_id_cores = testing_fn('cores') self.assertEqual(module_or_id_cores, alt_module_or_id) module_or_id_changelist = testing_fn('changelist') self.assertEqual(module_or_id_changelist, current_module_or_id) module_or_id_c = testing_fn('c') self.assertEqual(module_or_id_c, current_module_or_id) # Define a flag in another module only with the same long name. _defines.DEFINE_integer('changelist', 0, '', flag_values=fv, module_name=alt_module_name, short_name='l', allow_override=True) module_or_id_cores = testing_fn('cores') self.assertEqual(module_or_id_cores, alt_module_or_id) module_or_id_changelist = testing_fn('changelist') self.assertEqual(module_or_id_changelist, alt_module_or_id) module_or_id_c = testing_fn('c') self.assertEqual(module_or_id_c, current_module_or_id) module_or_id_l = testing_fn('l') self.assertEqual(module_or_id_l, alt_module_or_id) # Delete the changelist flag, its short name should still be registered. del fv.changelist module_or_id_changelist = testing_fn('changelist') self.assertEqual(module_or_id_changelist, None) module_or_id_c = testing_fn('c') self.assertEqual(module_or_id_c, current_module_or_id) module_or_id_l = testing_fn('l') self.assertEqual(module_or_id_l, alt_module_or_id)