def _clean_argparse_kwargs(self, dest, args, kwargs): ranked_default = self._compute_default(dest, kwargs=kwargs) kwargs_with_default = dict(kwargs, default=ranked_default) args_copy = list(args) for arg in args_copy: shadowed_arg_list = self._arg_lists_by_arg.get(arg) if shadowed_arg_list is not None: shadowed_arg_list.remove(arg) self._arg_lists_by_arg[arg] = args_copy self._registration_args.append((args_copy, kwargs_with_default)) # For argparse registration, remove our custom kwargs. argparse_kwargs = dict(kwargs_with_default) argparse_kwargs.pop('advanced', False) recursive = argparse_kwargs.pop('recursive', False) argparse_kwargs.pop('recursive_root', False) argparse_kwargs.pop('registering_class', None) argparse_kwargs.pop('fingerprint', False) deprecated_version = argparse_kwargs.pop('deprecated_version', None) deprecated_hint = argparse_kwargs.pop('deprecated_hint', '') if deprecated_version is not None: check_deprecated_semver(deprecated_version) self._deprecated_option_dests[dest] = (deprecated_version, deprecated_hint) return argparse_kwargs, recursive
def _validate(self, args, kwargs): """Validate option registration arguments.""" def error(exception_type, arg_name=None, **msg_kwargs): if arg_name is None: arg_name = args[0] if args else '<unknown>' raise exception_type(self.scope, arg_name, **msg_kwargs) if not args: error(NoOptionNames) # validate args. for arg in args: if not arg.startswith('-'): error(OptionNameDash, arg_name=arg) if not arg.startswith('--') and len(arg) > 2: error(OptionNameDoubleDash, arg_name=arg) # Validate kwargs. if kwargs.get('action', 'store') not in self._allowed_actions: error(InvalidAction, action=kwargs['action']) if is_boolean_flag(kwargs) and 'type' in kwargs: error(BooleanOptionType) if 'implicit_value' in kwargs: if is_boolean_flag(kwargs): error(BooleanOptionImplicitVal) elif kwargs['implicit_value'] is None: error(ImplicitValIsNone) for kwarg in kwargs: if kwarg not in self._allowed_registration_kwargs: error(InvalidKwarg, kwarg=kwarg) deprecated_ver = kwargs.get('deprecated_version') if deprecated_ver is not None: check_deprecated_semver(deprecated_ver, check_expired=False)
def _clean_argparse_kwargs(self, dest, args, kwargs): ranked_default = self._compute_default(dest, kwargs=kwargs) kwargs_with_default = dict(kwargs, default=ranked_default) args_copy = list(args) for arg in args_copy: shadowed_arg_list = self._arg_lists_by_arg.get(arg) if shadowed_arg_list is not None: shadowed_arg_list.remove(arg) self._arg_lists_by_arg[arg] = args_copy self._registration_args.append((args_copy, kwargs_with_default)) deprecated_version = kwargs.get('deprecated_version', None) deprecated_hint = kwargs.get('deprecated_hint', '') if deprecated_version is not None: check_deprecated_semver(deprecated_version) self._deprecated_option_dests[dest] = (deprecated_version, deprecated_hint) # For argparse registration, remove our custom kwargs. argparse_kwargs = dict(kwargs_with_default) for custom_kwarg in self._custom_kwargs: argparse_kwargs.pop(custom_kwarg, None) return argparse_kwargs
def _clean_argparse_kwargs(self, dest, args, kwargs): ranked_default = self._compute_default(dest, kwargs=kwargs) kwargs_with_default = dict(kwargs, default=ranked_default) args_copy = list(args) for arg in args_copy: shadowed_arg_list = self._arg_lists_by_arg.get(arg) if shadowed_arg_list is not None: shadowed_arg_list.remove(arg) self._arg_lists_by_arg[arg] = args_copy self._registration_args.append((args_copy, kwargs_with_default)) # For argparse registration, remove our custom kwargs. argparse_kwargs = dict(kwargs_with_default) argparse_kwargs.pop("advanced", False) recursive = argparse_kwargs.pop("recursive", False) argparse_kwargs.pop("recursive_root", False) argparse_kwargs.pop("registering_class", None) argparse_kwargs.pop("fingerprint", False) deprecated_version = argparse_kwargs.pop("deprecated_version", None) deprecated_hint = argparse_kwargs.pop("deprecated_hint", "") if deprecated_version is not None: check_deprecated_semver(deprecated_version) self._deprecated_option_dests[dest] = (deprecated_version, deprecated_hint) return argparse_kwargs, recursive
def test_removal_version_too_small(): with pytest.raises(PastRemovalVersionError): check_deprecated_semver('0.0.27') with pytest.raises(PastRemovalVersionError): @deprecated('0.0.27') def test_func(): pass
def test_removal_version_same(): with pytest.raises(PastRemovalVersionError): check_deprecated_semver(VERSION) with pytest.raises(PastRemovalVersionError): @deprecated(VERSION) def test_func(): pass
def _clean_argparse_kwargs(self, kwargs): deprecated_version = kwargs.get('deprecated_version', None) deprecated_hint = kwargs.get('deprecated_hint', '') if deprecated_version is not None: check_deprecated_semver(deprecated_version) self._deprecated_option_dests[kwargs['dest']] = (deprecated_version, deprecated_hint) # For argparse registration, remove our custom kwargs. argparse_kwargs = dict(kwargs) for custom_kwarg in self._custom_kwargs: argparse_kwargs.pop(custom_kwarg, None) return argparse_kwargs
def _clean_argparse_kwargs(self, kwargs): deprecated_version = kwargs.get('deprecated_version', None) deprecated_hint = kwargs.get('deprecated_hint', '') if deprecated_version is not None: check_deprecated_semver(deprecated_version) self._deprecated_option_dests[kwargs['dest']] = ( deprecated_version, deprecated_hint) # For argparse registration, remove our custom kwargs. argparse_kwargs = dict(kwargs) for custom_kwarg in self._custom_kwargs: argparse_kwargs.pop(custom_kwarg, None) return argparse_kwargs
def test_removal_version_bad(): with pytest.raises(BadRemovalVersionError): check_deprecated_semver(1.0) with pytest.raises(BadRemovalVersionError): @deprecated(1.0) def test_func(): pass with pytest.raises(BadRemovalVersionError): check_deprecated_semver('1.a.0') with pytest.raises(BadRemovalVersionError): @deprecated('1.a.0') def test_func(): pass
def test_removal_version_bad(): with pytest.raises(BadRemovalVersionError): check_deprecated_semver(1.0) with pytest.raises(BadRemovalVersionError): @deprecated(1.0) def test_func1(): pass with pytest.raises(BadRemovalVersionError): check_deprecated_semver('1.a.0') with pytest.raises(BadRemovalVersionError): @deprecated('1.a.0') def test_func1a(): pass
def _validate(self, args, kwargs): """Validate option registration arguments.""" def error(exception_type, arg_name=None, **msg_kwargs): if arg_name is None: arg_name = args[0] if args else '<unknown>' raise exception_type(self.scope, arg_name, **msg_kwargs) if not args: error(NoOptionNames) # validate args. for arg in args: if not arg.startswith('-'): error(OptionNameDash, arg_name=arg) if not arg.startswith('--') and len(arg) > 2: error(OptionNameDoubleDash, arg_name=arg) # Validate kwargs. if kwargs.get('action', 'store') not in self._allowed_actions: error(InvalidAction, action=kwargs['action']) if is_boolean_option(kwargs) and 'type' in kwargs: error(BooleanOptionType) if 'implicit_value' in kwargs: if is_boolean_option(kwargs): error(BooleanOptionImplicitVal) elif kwargs['implicit_value'] is None: error(ImplicitValIsNone) # Note: we check for list here, not list_option, because we validate the provided kwargs, # not the ones we modified. However we temporarily also allow list_option, until the # deprecation is complete. if 'member_type' in kwargs and kwargs.get('type', str) not in [list, list_option]: error(MemberTypeNotAllowed, type_=kwargs.get('type', str).__name__) if kwargs.get('member_type', str) not in self._allowed_member_types: error(InvalidMemberType, member_type=kwargs.get('member_type', str).__name__) for kwarg in kwargs: if kwarg not in self._allowed_registration_kwargs: error(InvalidKwarg, kwarg=kwarg) deprecated_ver = kwargs.get('deprecated_version') if deprecated_ver is not None: check_deprecated_semver(deprecated_ver, check_expired=False)
def _clean_argparse_kwargs(self, dest, args, kwargs): ranked_default = self._compute_default(dest, kwargs=kwargs) kwargs_with_default = dict(kwargs, default=ranked_default) args_copy = list(args) self._registration_args.append((args_copy, kwargs_with_default)) deprecated_version = kwargs.get('deprecated_version', None) deprecated_hint = kwargs.get('deprecated_hint', '') if deprecated_version is not None: check_deprecated_semver(deprecated_version) self._deprecated_option_dests[dest] = (deprecated_version, deprecated_hint) # For argparse registration, remove our custom kwargs. argparse_kwargs = dict(kwargs_with_default) for custom_kwarg in self._custom_kwargs: argparse_kwargs.pop(custom_kwarg, None) return argparse_kwargs
def _clean_argparse_kwargs(self, dest, args, kwargs): ranked_default = self._compute_default(dest, kwargs=kwargs) kwargs_with_default = dict(kwargs, default=ranked_default) self._registration_args.append((args, kwargs_with_default)) # For argparse registration, remove our custom kwargs. argparse_kwargs = dict(kwargs_with_default) argparse_kwargs.pop('advanced', False) recursive = argparse_kwargs.pop('recursive', False) argparse_kwargs.pop('recursive_root', False) argparse_kwargs.pop('registering_class', None) deprecated_version = argparse_kwargs.pop('deprecated_version', None) deprecated_hint = argparse_kwargs.pop('deprecated_hint', '') if deprecated_version is not None: check_deprecated_semver(deprecated_version) self._deprecated_option_dests[dest] = (deprecated_version, deprecated_hint) return argparse_kwargs, recursive
def _validate(self, args, kwargs): """Validate option registration arguments.""" def error(exception_type, arg_name=None, **msg_kwargs): if arg_name is None: arg_name = args[0] if args else '<unknown>' raise exception_type(self.scope, arg_name, **msg_kwargs) if not args: error(NoOptionNames) # validate args. for arg in args: if not arg.startswith('-'): error(OptionNameDash, arg_name=arg) if not arg.startswith('--') and len(arg) > 2: error(OptionNameDoubleDash, arg_name=arg) # Validate kwargs. if 'implicit_value' in kwargs and kwargs['implicit_value'] is None: error(ImplicitValIsNone) # Note: we check for list here, not list_option, because we validate the provided kwargs, # not the ones we modified. However we temporarily also allow list_option, until the # deprecation is complete. if 'member_type' in kwargs and kwargs.get( 'type', str) not in [list, list_option]: error(MemberTypeNotAllowed, type_=kwargs.get('type', str).__name__) if kwargs.get('member_type', str) not in self._allowed_member_types: error(InvalidMemberType, member_type=kwargs.get('member_type', str).__name__) for kwarg in kwargs: if kwarg not in self._allowed_registration_kwargs: error(InvalidKwarg, kwarg=kwarg) deprecated_ver = kwargs.get('deprecated_version') if deprecated_ver is not None: check_deprecated_semver(deprecated_ver, check_expired=False)
def test_removal_version_too_small_expiration_unchecked(): check_deprecated_semver('0.0.27', check_expired=False)
def register(self, *args, **kwargs): """Register an option, using argparse params. Custom extensions to argparse params: :param advanced: if True, the option willally be suppressed when displaying help. :param deprecated_version: Mark an option as deprecated. The value is a semver that indicates the release at which the option should be removed from the code. :param deprecated_hint: A message to display to the user when displaying help for or invoking a deprecated option. """ if self._frozen: raise RegistrationError('Cannot register option {0} in scope {1} after registering options ' 'in any of its inner scopes.'.format(args[0], self._scope)) # Prevent further registration in enclosing scopes. ancestor = self._parent_parser while ancestor: ancestor._freeze() ancestor = ancestor._parent_parser # Pull out our custom arguments, they aren't valid for argparse. advanced = kwargs.pop('advanced', False) self._validate(args, kwargs) dest = self._set_dest(args, kwargs) deprecated_version = kwargs.pop('deprecated_version', None) deprecated_hint = kwargs.pop('deprecated_hint', '') if deprecated_version is not None: check_deprecated_semver(deprecated_version) flag = '--' + dest.replace('_', '-') self._deprecated_flags[flag] = (deprecated_version, deprecated_hint) help = kwargs.pop('help', '') kwargs['help'] = 'DEPRECATED: {}\n{}'.format(self.deprecated_message(flag), help) inverse_args = [] help_args = [] for flag in self.expand_flags(*args, **kwargs): if flag.inverse_name: inverse_args.append(flag.inverse_name) if deprecated_version: self._deprecated_flags[flag.inverse_name] = (deprecated_version, deprecated_hint) help_args.append(flag.help_arg) is_invertible = len(inverse_args) > 0 # Register the option, only on this scope, for the purpose of displaying help. # Note that we'll only display the default value for this scope, even though the # default may be overridden in inner scopes. raw_default = self._compute_default(dest, is_invertible, kwargs).value kwargs_with_default = dict(kwargs, default=raw_default) if advanced: arg_group = self._help_argparser_advanced_group else: arg_group = self._help_argparser_group arg_group.add_argument(*help_args, **kwargs_with_default) self._has_help_options = True # Register the option for the purpose of parsing, on this and all enclosed scopes. if is_invertible: inverse_kwargs = self._create_inverse_kwargs(kwargs) self._register_boolean(dest, args, kwargs, inverse_args, inverse_kwargs) else: self._register(dest, args, kwargs)
def register(self, *args, **kwargs): """Register an option, using argparse params. Custom extensions to argparse params: :param advanced: if True, the option willally be suppressed when displaying help. :param deprecated_version: Mark an option as deprecated. The value is a semver that indicates the release at which the option should be removed from the code. :param deprecated_hint: A message to display to the user when displaying help for or invoking a deprecated option. """ if self._frozen: raise RegistrationError('Cannot register option {0} in scope {1} after registering options ' 'in any of its inner scopes.'.format(args[0], self._scope)) # Prevent further registration in enclosing scopes. ancestor = self._parent_parser while ancestor: ancestor._freeze() ancestor = ancestor._parent_parser # Pull out our custom arguments, they aren't valid for argparse. recursive = kwargs.pop('recursive', False) advanced = kwargs.pop('advanced', False) self._validate(args, kwargs) dest = self._set_dest(args, kwargs) deprecated_version = kwargs.pop('deprecated_version', None) deprecated_hint = kwargs.pop('deprecated_hint', '') if deprecated_version is not None: check_deprecated_semver(deprecated_version) flag = '--' + dest.replace('_', '-') self._deprecated_flags[flag] = (deprecated_version, deprecated_hint) help = kwargs.pop('help', '') kwargs['help'] = 'DEPRECATED: {}\n{}'.format(self.deprecated_message(flag), help) inverse_args = [] help_args = [] for flag in self.expand_flags(*args, **kwargs): if flag.inverse_name: inverse_args.append(flag.inverse_name) if deprecated_version: self._deprecated_flags[flag.inverse_name] = (deprecated_version, deprecated_hint) help_args.append(flag.help_arg) is_invertible = len(inverse_args) > 0 # Register the option, only on this scope, for the purpose of displaying help. # Note that we'll only display the default value for this scope, even though the # default may be overridden in inner scopes. raw_default = self._compute_default(dest, is_invertible, kwargs).value kwargs_with_default = dict(kwargs, default=raw_default) if advanced: arg_group = self._help_argparser_advanced_group else: arg_group = self._help_argparser_group arg_group.add_argument(*help_args, **kwargs_with_default) self._has_help_options = True # Register the option for the purpose of parsing, on this and all enclosed scopes. if is_invertible: inverse_kwargs = self._create_inverse_kwargs(kwargs) self._register_boolean(dest, args, kwargs, inverse_args, inverse_kwargs, recursive) else: self._register(dest, args, kwargs, recursive)