Example #1
0
    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
Example #2
0
  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)
Example #3
0
    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
Example #4
0
    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
Example #5
0
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
Example #6
0
def test_removal_version_same():
  with pytest.raises(PastRemovalVersionError):
    check_deprecated_semver(VERSION)

  with pytest.raises(PastRemovalVersionError):
    @deprecated(VERSION)
    def test_func():
      pass
Example #7
0
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
Example #8
0
def test_removal_version_same():
  with pytest.raises(PastRemovalVersionError):
    check_deprecated_semver(VERSION)

  with pytest.raises(PastRemovalVersionError):
    @deprecated(VERSION)
    def test_func():
      pass
Example #9
0
  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
Example #10
0
    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
Example #11
0
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
Example #12
0
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
Example #13
0
  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)
Example #14
0
  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
Example #15
0
  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
Example #16
0
    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)
Example #17
0
def test_removal_version_too_small_expiration_unchecked():
  check_deprecated_semver('0.0.27', check_expired=False)
Example #18
0
  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)
Example #19
0
def test_removal_version_too_small_expiration_unchecked():
  check_deprecated_semver('0.0.27', check_expired=False)
Example #20
0
  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)