Ejemplo n.º 1
0
    def deprecated_wrapper(func):
        """Deprecation decorator."""
        decorator_utils.validate_callable(func, 'deprecated_arg_values')

        @functools.wraps(func)
        def new_func(*args, **kwargs):
            """Deprecation wrapper."""
            if _PRINT_DEPRECATION_WARNINGS:
                named_args = tf_inspect.getcallargs(func, *args, **kwargs)
                for arg_name, arg_value in deprecated_kwargs.items():
                    if arg_name in named_args and _safe_eq(
                            named_args[arg_name], arg_value):
                        if (func, arg_name) not in _PRINTED_WARNING:
                            if warn_once:
                                _PRINTED_WARNING[(func, arg_name)] = True
                            logging.warning(
                                'From %s: calling %s (from %s) with %s=%s is deprecated and '
                                'will be removed %s.\nInstructions for updating:\n%s',
                                _call_location(),
                                decorator_utils.get_qualified_name(func),
                                func.__module__, arg_name, arg_value,
                                'in a future version' if date is None else
                                ('after %s' % date), instructions)
            return func(*args, **kwargs)

        doc = _add_deprecated_arg_value_notice_to_docstring(
            func.__doc__, date, instructions, deprecated_kwargs)
        return tf_decorator.make_decorator(func, new_func, 'deprecated', doc)
Ejemplo n.º 2
0
def experimental(func):
  """Decorator for marking functions or methods experimental.

  This decorator logs an experimental warning whenever the decorated function is
  called. It has the following format:

    <function> (from <module>) is experimental and may change or be removed at
    any time, and without warning.

  <function> will include the class name if it is a method.

  It also edits the docstring of the function: ' (experimental)' is appended
  to the first line of the docstring and a notice is prepended to the rest of
  the docstring.

  Args:
    func: A function or method to mark experimental.

  Returns:
    Decorated function or method.
  """
  decorator_utils.validate_callable(func, 'experimental')
  @functools.wraps(func)
  def new_func(*args, **kwargs):
    logging.warning(
        '%s (from %s) is experimental and may change or be removed at '
        'any time, and without warning.',
        decorator_utils.get_qualified_name(func), func.__module__)
    return func(*args, **kwargs)
  new_func.__doc__ = _add_experimental_function_notice_to_docstring(
      func.__doc__)
  return new_func
Ejemplo n.º 3
0
def keyword_args_only(func):
  """Decorator for marking specific function accepting keyword args only.

  This decorator raises a `ValueError` if the input `func` is called with any
  non-keyword args. This prevents the caller from providing the arguments in
  wrong order.

  Args:
    func: The function or method needed to be decorated.

  Returns:
    Decorated function or method.

  Raises:
    ValueError: If `func` is not callable.
  """

  decorator_utils.validate_callable(func, "keyword_args_only")
  @functools.wraps(func)
  def new_func(*args, **kwargs):
    """Keyword args only wrapper."""
    if args:
      raise ValueError(
          "Must use keyword args to call {}.".format(func.__name__))
    return func(**kwargs)
  return new_func
Ejemplo n.º 4
0
def keyword_args_only(func):
    """Decorator for marking specific function accepting keyword args only.

  This decorator raises a `ValueError` if the input `func` is called with any
  non-keyword args. This prevents the caller from providing the arguments in
  wrong order.

  Args:
    func: The function or method needed to be decorated.

  Returns:
    Decorated function or method.

  Raises:
    ValueError: If `func` is not callable.
  """

    decorator_utils.validate_callable(func, "keyword_args_only")

    @functools.wraps(func)
    def new_func(*args, **kwargs):
        """Keyword args only wrapper."""
        if args:
            raise ValueError(
                f"The function {func.__name__} only accepts keyword arguments. "
                "Do not pass positional arguments. Received the following positional "
                f"arguments: {args}")
        return func(**kwargs)

    return new_func
Ejemplo n.º 5
0
    def deprecated_wrapper(func):
        """Deprecation decorator."""
        decorator_utils.validate_callable(func, "deprecated_arg_values")

        @functools.wraps(func)
        def new_func(*args, **kwargs):
            """Deprecation wrapper."""
            named_args = inspect.getcallargs(func, *args, **kwargs)
            for arg_name, arg_value in deprecated_kwargs.items():
                if arg_name in named_args and named_args[arg_name] == arg_value:
                    logging.warning(
                        "From %s: calling %s (from %s) with %s=%s is deprecated and will "
                        "be removed after %s.\nInstructions for updating:\n%s",
                        _call_location(),
                        decorator_utils.get_qualified_name(func),
                        func.__module__,
                        arg_name,
                        arg_value,
                        date,
                        instructions,
                    )
            return func(*args, **kwargs)

        new_func.__doc__ = _add_deprecated_arg_notice_to_docstring(func.__doc__, date, instructions)
        return new_func
Ejemplo n.º 6
0
def experimental(func):
    """Decorator for marking functions or methods experimental.

  This decorator logs an experimental warning whenever the decorated function is
  called. It has the following format:

    <function> (from <module>) is experimental and may change or be removed at
    any time, and without warning.

  <function> will include the class name if it is a method.

  It also edits the docstring of the function: ' (experimental)' is appended
  to the first line of the docstring and a notice is prepended to the rest of
  the docstring.

  Args:
    func: A function or method to mark experimental.

  Returns:
    Decorated function or method.
  """
    decorator_utils.validate_callable(func, 'experimental')

    @functools.wraps(func)
    def new_func(*args, **kwargs):
        logging.warning(
            '%s (from %s) is experimental and may change or be removed at '
            'any time, and without warning.',
            decorator_utils.get_qualified_name(func), func.__module__)
        return func(*args, **kwargs)

    new_func.__doc__ = _add_experimental_function_notice_to_docstring(
        func.__doc__)
    return new_func
Ejemplo n.º 7
0
  def test_callable(self):

    class TestClass(object):

      def __call__(self):
        pass

    decorator_utils.validate_callable(TestClass(), "test")
Ejemplo n.º 8
0
    def deprecated_wrapper(func):
        """Deprecation decorator."""
        decorator_utils.validate_callable(func, "deprecated_args")
        deprecated_arg_names = _get_arg_names_to_ok_vals()

        arg_spec = inspect.getargspec(func)
        deprecated_positions = _get_deprecated_positional_arguments(deprecated_arg_names, arg_spec)

        is_varargs_deprecated = arg_spec.varargs in deprecated_arg_names
        is_kwargs_deprecated = arg_spec.keywords in deprecated_arg_names

        if len(deprecated_positions) + is_varargs_deprecated + is_kwargs_deprecated != len(
            deprecated_arg_names_or_tuples
        ):
            known_args = arg_spec.args + [arg_spec.varargs, arg_spec.keywords]
            missing_args = [arg_name for arg_name in deprecated_arg_names if arg_name not in known_args]
            raise ValueError(
                "The following deprecated arguments are not present "
                "in the function signature: %s. "
                "Found next arguments: %s." % (missing_args, known_args)
            )

        @functools.wraps(func)
        def new_func(*args, **kwargs):
            """Deprecation wrapper."""
            invalid_args = []
            named_args = inspect.getcallargs(func, *args, **kwargs)
            for arg_name, spec in iter(deprecated_positions.items()):
                if spec.position < len(args) and not (spec.has_ok_value and named_args[arg_name] == spec.ok_value):
                    invalid_args.append(arg_name)
            if is_varargs_deprecated and len(args) > len(arg_spec.args):
                invalid_args.append(arg_spec.varargs)
            if is_kwargs_deprecated and kwargs:
                invalid_args.append(arg_spec.keywords)
            for arg_name in deprecated_arg_names:
                if arg_name in kwargs and not (
                    deprecated_positions[arg_name].has_ok_value
                    and (named_args[arg_name] == deprecated_positions[arg_name].ok_value)
                ):
                    invalid_args.append(arg_name)
            for arg_name in invalid_args:
                logging.warning(
                    "From %s: calling %s (from %s) with %s is deprecated and will "
                    "be removed after %s.\nInstructions for updating:\n%s",
                    _call_location(),
                    decorator_utils.get_qualified_name(func),
                    func.__module__,
                    arg_name,
                    date,
                    instructions,
                )
            return func(*args, **kwargs)

        new_func.__doc__ = _add_deprecated_arg_notice_to_docstring(func.__doc__, date, instructions)
        return new_func
Ejemplo n.º 9
0
    def deprecated_wrapper(func):
        """Deprecation decorator."""
        decorator_utils.validate_callable(func, 'deprecated_args')
        deprecated_arg_names = _get_arg_names_to_ok_vals()

        arg_spec = inspect.getargspec(func)
        deprecated_positions = _get_deprecated_positional_arguments(
            deprecated_arg_names, arg_spec)

        is_varargs_deprecated = arg_spec.varargs in deprecated_arg_names
        is_kwargs_deprecated = arg_spec.keywords in deprecated_arg_names

        if (len(deprecated_positions) + is_varargs_deprecated +
                is_kwargs_deprecated != len(deprecated_arg_names_or_tuples)):
            known_args = arg_spec.args + [arg_spec.varargs, arg_spec.keywords]
            missing_args = [
                arg_name for arg_name in deprecated_arg_names
                if arg_name not in known_args
            ]
            raise ValueError(
                'The following deprecated arguments are not present '
                'in the function signature: %s. '
                'Found next arguments: %s.' % (missing_args, known_args))

        @functools.wraps(func)
        def new_func(*args, **kwargs):
            """Deprecation wrapper."""
            invalid_args = []
            named_args = inspect.getcallargs(func, *args, **kwargs)
            for arg_name, spec in iter(deprecated_positions.items()):
                if (spec.position < len(args)
                        and not (spec.has_ok_value
                                 and named_args[arg_name] == spec.ok_value)):
                    invalid_args.append(arg_name)
            if is_varargs_deprecated and len(args) > len(arg_spec.args):
                invalid_args.append(arg_spec.varargs)
            if is_kwargs_deprecated and kwargs:
                invalid_args.append(arg_spec.keywords)
            for arg_name in deprecated_arg_names:
                if (arg_name in kwargs and
                        not (deprecated_positions[arg_name].has_ok_value and
                             (named_args[arg_name]
                              == deprecated_positions[arg_name].ok_value))):
                    invalid_args.append(arg_name)
            for arg_name in invalid_args:
                logging.warning(
                    'From %s: calling %s (from %s) with %s is deprecated and will '
                    'be removed after %s.\nInstructions for updating:\n%s',
                    _call_location(), decorator_utils.get_qualified_name(func),
                    func.__module__, arg_name, date, instructions)
            return func(*args, **kwargs)

        new_func.__doc__ = _add_deprecated_arg_notice_to_docstring(
            func.__doc__, date, instructions)
        return new_func
Ejemplo n.º 10
0
    def deprecated_wrapper(func_or_class):
        """Deprecation wrapper."""
        if isinstance(func_or_class, type):
            # If a class is deprecated, you actually want to wrap the constructor.
            cls = func_or_class
            if cls.__new__ is object.__new__:
                func = cls.__init__
                constructor_name = '__init__'
            else:
                func = cls.__new__
                constructor_name = '__new__'

        else:
            cls = None
            constructor_name = None
            func = func_or_class

        decorator_utils.validate_callable(func, 'deprecated')

        @functools.wraps(func)
        def new_func(*args, **kwargs):  # pylint: disable=missing-docstring
            if _PRINT_DEPRECATION_WARNINGS:
                if func not in _PRINTED_WARNING:
                    if warn_once:
                        _PRINTED_WARNING[func] = True
                    logging.warning(
                        'From %s: %s (from %s) is deprecated and will be removed %s.\n'
                        'Instructions for updating:\n%s', _call_location(),
                        decorator_utils.get_qualified_name(func),
                        func.__module__,
                        'in a future version' if date is None else
                        ('after %s' % date), instructions)
            return func(*args, **kwargs)

        doc_controls.set_deprecated(new_func)
        new_func = tf_decorator.make_decorator(
            func, new_func, 'deprecated',
            _add_deprecated_function_notice_to_docstring(
                func.__doc__, date, instructions))

        if cls is None:
            return new_func
        else:
            # Insert the wrapped function as the constructor
            setattr(cls, constructor_name, new_func)

            # And update the docstring of the class.
            cls.__doc__ = _add_deprecated_function_notice_to_docstring(
                cls.__doc__, date, instructions)

            return cls
Ejemplo n.º 11
0
 def deprecated_wrapper(func):
   """Deprecation wrapper."""
   decorator_utils.validate_callable(func, 'deprecated')
   @functools.wraps(func)
   def new_func(*args, **kwargs):
     logging.warning(
         '%s (from %s) is deprecated and will be removed after %s.\n'
         'Instructions for updating:\n%s',
         decorator_utils.get_qualified_name(func), func.__module__, date,
         instructions)
     return func(*args, **kwargs)
   new_func.__doc__ = _add_deprecated_function_notice_to_docstring(
       func.__doc__, date, instructions)
   return new_func
Ejemplo n.º 12
0
 def deprecated_wrapper(func):
   """Deprecation wrapper."""
   decorator_utils.validate_callable(func, 'deprecated')
   @functools.wraps(func)
   def new_func(*args, **kwargs):
     logging.warning(
         'From %s: %s (from %s) is deprecated and will be removed '
         'after %s.\n'
         'Instructions for updating:\n%s',
         _call_location(), decorator_utils.get_qualified_name(func),
         func.__module__, date, instructions)
     return func(*args, **kwargs)
   new_func.__doc__ = _add_deprecated_function_notice_to_docstring(
       func.__doc__, date, instructions)
   return new_func
Ejemplo n.º 13
0
    def deprecated_wrapper(func):
        """Deprecation decorator."""
        decorator_utils.validate_callable(func, 'deprecated_args')

        arg_spec = inspect.getargspec(func)
        deprecated_positions = [(i, arg_name)
                                for (i, arg_name) in enumerate(arg_spec.args)
                                if arg_name in deprecated_arg_names]
        is_varargs_deprecated = arg_spec.varargs in deprecated_arg_names
        is_kwargs_deprecated = arg_spec.keywords in deprecated_arg_names

        if (len(deprecated_positions) + is_varargs_deprecated +
                is_kwargs_deprecated != len(deprecated_arg_names)):
            known_args = arg_spec.args + [arg_spec.varargs, arg_spec.keywords]
            missing_args = [
                arg_name for arg_name in deprecated_arg_names
                if arg_name not in known_args
            ]
            raise ValueError(
                'The following deprecated arguments are not present '
                'in the function signature: %s' % missing_args)

        @functools.wraps(func)
        def new_func(*args, **kwargs):
            """Deprecation wrapper."""
            invalid_args = []
            for (i, arg_name) in deprecated_positions:
                if i < len(args):
                    invalid_args.append(arg_name)
            if is_varargs_deprecated and len(args) > len(arg_spec.args):
                invalid_args.append(arg_spec.varargs)
            if is_kwargs_deprecated and kwargs:
                invalid_args.append(arg_spec.keywords)
            for arg_name in deprecated_arg_names:
                if arg_name in kwargs:
                    invalid_args.append(arg_name)
            for arg_name in invalid_args:
                logging.warning(
                    'Calling %s (from %s) with %s is deprecated and will be removed '
                    'after %s.\nInstructions for updating:\n%s',
                    decorator_utils.get_qualified_name(func), func.__module__,
                    arg_name, date, instructions)
            return func(*args, **kwargs)

        new_func.__doc__ = _add_deprecated_arg_notice_to_docstring(
            func.__doc__, date, instructions)
        return new_func
Ejemplo n.º 14
0
 def deprecated_wrapper(func):
   """Deprecation wrapper."""
   decorator_utils.validate_callable(func, 'deprecated')
   @functools.wraps(func)
   def new_func(*args, **kwargs):
     logging.warning(
         'From %s: %s (from %s) is deprecated and will be removed %s.\n'
         'Instructions for updating:\n%s',
         _call_location(), decorator_utils.get_qualified_name(func),
         func.__module__,
         'in a future version' if date is None else ('after %s' % date),
         instructions)
     return func(*args, **kwargs)
   return tf_decorator.make_decorator(
       func, new_func, 'deprecated',
       _add_deprecated_function_notice_to_docstring(func.__doc__, date,
                                                    instructions))
Ejemplo n.º 15
0
 def deprecated_wrapper(func):
   """Deprecation decorator."""
   decorator_utils.validate_callable(func, 'deprecated_arg_values')
   @functools.wraps(func)
   def new_func(*args, **kwargs):
     """Deprecation wrapper."""
     named_args = inspect.getcallargs(func, *args, **kwargs)
     for arg_name, arg_value in deprecated_kwargs.items():
       if arg_name in named_args and named_args[arg_name] == arg_value:
         logging.warning(
             'From %s: calling %s (from %s) with %s=%s is deprecated and will '
             'be removed after %s.\nInstructions for updating:\n%s',
             _call_location(), decorator_utils.get_qualified_name(func),
             func.__module__, arg_name, arg_value, date, instructions)
     return func(*args, **kwargs)
   new_func.__doc__ = _add_deprecated_arg_notice_to_docstring(
       func.__doc__, date, instructions)
   return new_func
Ejemplo n.º 16
0
  def deprecated_wrapper(func):
    """Deprecation decorator."""
    decorator_utils.validate_callable(func, 'deprecated_args')

    arg_spec = inspect.getargspec(func)
    deprecated_positions = [
        (i, arg_name) for (i, arg_name) in enumerate(arg_spec.args)
        if arg_name in deprecated_arg_names]
    is_varargs_deprecated = arg_spec.varargs in deprecated_arg_names
    is_kwargs_deprecated = arg_spec.keywords in deprecated_arg_names

    if (len(deprecated_positions) + is_varargs_deprecated + is_kwargs_deprecated
        != len(deprecated_arg_names)):
      known_args = arg_spec.args + [arg_spec.varargs, arg_spec.keywords]
      missing_args = [arg_name for arg_name in deprecated_arg_names
                      if arg_name not in known_args]
      raise ValueError('The following deprecated arguments are not present '
                       'in the function signature: %s. '
                       'Found next arguments: %s.' % (missing_args, known_args))

    @functools.wraps(func)
    def new_func(*args, **kwargs):
      """Deprecation wrapper."""
      invalid_args = []
      for (i, arg_name) in deprecated_positions:
        if i < len(args):
          invalid_args.append(arg_name)
      if is_varargs_deprecated and len(args) > len(arg_spec.args):
        invalid_args.append(arg_spec.varargs)
      if is_kwargs_deprecated and kwargs:
        invalid_args.append(arg_spec.keywords)
      for arg_name in deprecated_arg_names:
        if arg_name in kwargs:
          invalid_args.append(arg_name)
      for arg_name in invalid_args:
        logging.warning(
            'From %s: calling %s (from %s) with %s is deprecated and will '
            'be removed after %s.\nInstructions for updating:\n%s',
            _call_location(), decorator_utils.get_qualified_name(func),
            func.__module__, arg_name, date, instructions)
      return func(*args, **kwargs)
    new_func.__doc__ = _add_deprecated_arg_notice_to_docstring(
        func.__doc__, date, instructions)
    return new_func
Ejemplo n.º 17
0
    def deprecated_wrapper(func):
        """Deprecation wrapper."""
        decorator_utils.validate_callable(func, 'deprecated')

        @functools.wraps(func)
        def new_func(*args, **kwargs):  # pylint: disable=missing-docstring
            if _PRINT_DEPRECATION_WARNINGS:
                logging.warning(
                    'From %s: %s (from %s) is deprecated and will be removed %s.\n'
                    'Instructions for updating:\n%s', _call_location(),
                    decorator_utils.get_qualified_name(func), func.__module__,
                    'in a future version' if date is None else
                    ('after %s' % date), instructions)
            return func(*args, **kwargs)

        return tf_decorator.make_decorator(
            func, new_func, 'deprecated',
            _add_deprecated_function_notice_to_docstring(
                func.__doc__, date, instructions))
Ejemplo n.º 18
0
 def deprecated_wrapper(func):
   """Deprecation decorator."""
   decorator_utils.validate_callable(func, 'deprecated_arg_values')
   @functools.wraps(func)
   def new_func(*args, **kwargs):
     """Deprecation wrapper."""
     named_args = tf_inspect.getcallargs(func, *args, **kwargs)
     for arg_name, arg_value in deprecated_kwargs.items():
       if arg_name in named_args and named_args[arg_name] == arg_value:
         logging.warning(
             'From %s: calling %s (from %s) with %s=%s is deprecated and will '
             'be removed %s.\nInstructions for updating:\n%s',
             _call_location(), decorator_utils.get_qualified_name(func),
             func.__module__, arg_name, arg_value,
             'in a future version' if date is None else ('after %s' % date),
             instructions)
     return func(*args, **kwargs)
   return tf_decorator.make_decorator(func, new_func, 'deprecated',
                                      _add_deprecated_arg_notice_to_docstring(
                                          func.__doc__, date, instructions))
Ejemplo n.º 19
0
 def deprecated_wrapper(func):
   """Deprecation wrapper."""
   decorator_utils.validate_callable(func, 'deprecated')
   @functools.wraps(func)
   def new_func(*args, **kwargs):  # pylint: disable=missing-docstring
     if _PRINT_DEPRECATION_WARNINGS:
       if func not in _PRINTED_WARNING:
         if warn_once:
           _PRINTED_WARNING[func] = True
         logging.warning(
             'From %s: %s (from %s) is deprecated and will be removed %s.\n'
             'Instructions for updating:\n%s',
             _call_location(), decorator_utils.get_qualified_name(func),
             func.__module__,
             'in a future version' if date is None else ('after %s' % date),
             instructions)
     return func(*args, **kwargs)
   return tf_decorator.make_decorator(
       func, new_func, 'deprecated',
       _add_deprecated_function_notice_to_docstring(func.__doc__, date,
                                                    instructions))
Ejemplo n.º 20
0
  def deprecated_wrapper(func):
    """Deprecation decorator."""
    decorator_utils.validate_callable(func, 'deprecated_args')

    arg_spec = tf_inspect.getfullargspec(func)
    deprecated_positions = _get_deprecated_positional_arguments(
        deprecated_arg_names, arg_spec)

    is_varargs_deprecated = arg_spec.varargs in deprecated_arg_names
    is_kwargs_deprecated = arg_spec.varkw in deprecated_arg_names

    if (len(deprecated_positions) + is_varargs_deprecated + is_kwargs_deprecated
        != len(deprecated_arg_names_or_tuples)):
      known_args = arg_spec.args + [arg_spec.varargs, arg_spec.varkw]
      missing_args = [arg_name for arg_name in deprecated_arg_names
                      if arg_name not in known_args]
      raise ValueError('The following deprecated arguments are not present '
                       'in the function signature: %s. '
                       'Found next arguments: %s.' % (missing_args, known_args))

    def _same_value(a, b):
      """A comparison operation that works for multiple object types.

      Returns True for two empty lists, two numeric values with the
      same value, etc.

      Returns False for (pd.DataFrame, None), and other pairs which
      should not be considered equivalent.

      Args:
        a: value one of the comparison.
        b: value two of the comparison.

      Returns:
        A boolean indicating whether the two inputs are the same value
        for the purposes of deprecation.
      """
      if a is b:
        return True
      try:
        equality = a == b
        if isinstance(equality, bool):
          return equality
      except TypeError:
        return False
      return False

    @functools.wraps(func)
    def new_func(*args, **kwargs):
      """Deprecation wrapper."""
      # TODO(apassos) figure out a way to have reasonable performance with
      # deprecation warnings and eager mode.
      if is_in_graph_mode.IS_IN_GRAPH_MODE() and _PRINT_DEPRECATION_WARNINGS:
        invalid_args = []
        named_args = tf_inspect.getcallargs(func, *args, **kwargs)
        for arg_name, spec in iter(deprecated_positions.items()):
          if (spec.position < len(args) and
              not (spec.has_ok_value and
                   _same_value(named_args[arg_name], spec.ok_value))):
            invalid_args.append(arg_name)
        if is_varargs_deprecated and len(args) > len(arg_spec.args):
          invalid_args.append(arg_spec.varargs)
        if is_kwargs_deprecated and kwargs:
          invalid_args.append(arg_spec.varkw)
        for arg_name in deprecated_arg_names:
          if (arg_name in kwargs and
              not (deprecated_positions[arg_name].has_ok_value and
                   _same_value(named_args[arg_name],
                               deprecated_positions[arg_name].ok_value))):
            invalid_args.append(arg_name)
        for arg_name in invalid_args:
          if (func, arg_name) not in _PRINTED_WARNING:
            if warn_once:
              _PRINTED_WARNING[(func, arg_name)] = True
            logging.warning(
                'From %s: calling %s (from %s) with %s is deprecated and will '
                'be removed %s.\nInstructions for updating:\n%s',
                _call_location(), decorator_utils.get_qualified_name(func),
                func.__module__, arg_name,
                'in a future version' if date is None else ('after %s' % date),
                instructions)
      return func(*args, **kwargs)

    doc = _add_deprecated_arg_notice_to_docstring(
        func.__doc__, date, instructions, sorted(deprecated_arg_names.keys()))
    return tf_decorator.make_decorator(func, new_func, 'deprecated', doc)
Ejemplo n.º 21
0
def deprecated_alias(deprecated_name, name, func_or_class, warn_once=True):
  """Deprecate a symbol in favor of a new name with identical semantics.

  This function is meant to be used when defining a backwards-compatibility
  alias for a symbol which has been moved. For example:

  module1.py:
  ```python
  class NewNameForClass: pass
  ```

  module2.py:
  ```python
  import module1

  DeprecatedNameForClass = deprecated_alias(
    deprecated_name='module2.DeprecatedNameForClass',
    name='module1.NewNameForClass',
    module1.NewNameForClass)
  ```

  This function works for classes and functions.

  For classes, it creates a new class which is functionally identical (it
  inherits from the original, and overrides its constructor), but which prints
  a deprecation warning when an instance is created. It also adds a deprecation
  notice to the class' docstring.

  For functions, it returns a function wrapped by `tf_decorator.make_decorator`.
  That function prints a warning when used, and has a deprecation notice in its
  docstring. This is more or less equivalent (the deprecation warning has
  slightly different text) to writing:

  ```python
  @deprecated
  def deprecated_alias(original_args):
    real_function(original_args)
  ```

  Args:
    deprecated_name: The name of the symbol that is being deprecated, to be used
      in the warning message. This should be its fully qualified name to avoid
      confusion.
    name: The name of the symbol that is to be used instead of the deprecated
      name. This should be a fully qualified name to avoid confusion.
    func_or_class: The (non-deprecated) class or function for which a deprecated
      alias should be created.
    warn_once: If True (the default), only print a deprecation warning the first
      time this function is used, or the class is instantiated.

  Returns:
    A wrapped version of `func_or_class` which prints a deprecation warning on
    use and has a modified docstring.
  """
  if tf_inspect.isclass(func_or_class):

    # Make a new class with __init__ wrapped in a warning.
    class _NewClass(func_or_class):  # pylint: disable=missing-docstring
      __doc__ = decorator_utils.add_notice_to_docstring(
          func_or_class.__doc__, 'Please use %s instead.' % name,
          'DEPRECATED CLASS',
          '(deprecated)', ['THIS CLASS IS DEPRECATED. '
                           'It will be removed in a future version. '])
      __name__ = func_or_class.__name__
      __module__ = _call_location(outer=True)

      @_wrap_decorator(func_or_class.__init__)
      def __init__(self, *args, **kwargs):
        if hasattr(_NewClass.__init__, '__func__'):
          # Python 2
          _NewClass.__init__.__func__.__doc__ = func_or_class.__init__.__doc__
        else:
          # Python 3
          _NewClass.__init__.__doc__ = func_or_class.__init__.__doc__

        if _PRINT_DEPRECATION_WARNINGS:
          # We're making the alias as we speak. The original may have other
          # aliases, so we cannot use it to check for whether it's already been
          # warned about.
          if _NewClass.__init__ not in _PRINTED_WARNING:
            if warn_once:
              _PRINTED_WARNING[_NewClass.__init__] = True
            logging.warning(
                'From %s: The name %s is deprecated. Please use %s instead.\n',
                _call_location(), deprecated_name, name)
        super(_NewClass, self).__init__(*args, **kwargs)

    return _NewClass
  else:
    decorator_utils.validate_callable(func_or_class, 'deprecated')

    # Make a wrapper for the original
    @functools.wraps(func_or_class)
    def new_func(*args, **kwargs):  # pylint: disable=missing-docstring
      if _PRINT_DEPRECATION_WARNINGS:
        # We're making the alias as we speak. The original may have other
        # aliases, so we cannot use it to check for whether it's already been
        # warned about.
        if new_func not in _PRINTED_WARNING:
          if warn_once:
            _PRINTED_WARNING[new_func] = True
          logging.warning(
              'From %s: The name %s is deprecated. Please use %s instead.\n',
              _call_location(), deprecated_name, name)
      return func_or_class(*args, **kwargs)
    return tf_decorator.make_decorator(
        func_or_class, new_func, 'deprecated',
        _add_deprecated_function_notice_to_docstring(
            func_or_class.__doc__, None, 'Please use %s instead.' % name))
Ejemplo n.º 22
0
  def test_callable(self):
    class TestClass(object):

      def __call__(self):
        pass
    decorator_utils.validate_callable(TestClass(), "test")
Ejemplo n.º 23
0
    def deprecated_wrapper(func):
        """Deprecation decorator."""
        decorator_utils.validate_callable(func, 'deprecated_args')
        deprecated_arg_names = _get_arg_names_to_ok_vals()

        arg_spec = tf_inspect.getargspec(func)
        deprecated_positions = _get_deprecated_positional_arguments(
            deprecated_arg_names, arg_spec)

        is_varargs_deprecated = arg_spec.varargs in deprecated_arg_names
        is_kwargs_deprecated = arg_spec.keywords in deprecated_arg_names

        if (len(deprecated_positions) + is_varargs_deprecated +
                is_kwargs_deprecated != len(deprecated_arg_names_or_tuples)):
            known_args = arg_spec.args + [arg_spec.varargs, arg_spec.keywords]
            missing_args = [
                arg_name for arg_name in deprecated_arg_names
                if arg_name not in known_args
            ]
            raise ValueError(
                'The following deprecated arguments are not present '
                'in the function signature: %s. '
                'Found next arguments: %s.' % (missing_args, known_args))

        def _same_value(a, b):
            """A comparison operation that works for multiple object types.

      Returns True for two empty lists, two numeric values with the
      same value, etc.

      Returns False for (pd.DataFrame, None), and other pairs which
      should not be considered equivalent.

      Args:
        a: value one of the comparison.
        b: value two of the comparison.

      Returns:
        A boolean indicating whether the two inputs are the same value
        for the purposes of deprecation.
      """
            if a is b:
                return True
            try:
                equality = a == b
                if isinstance(equality, bool):
                    return equality
            except TypeError:
                return False
            return False

        @functools.wraps(func)
        def new_func(*args, **kwargs):
            """Deprecation wrapper."""
            invalid_args = []
            named_args = tf_inspect.getcallargs(func, *args, **kwargs)
            for arg_name, spec in iter(deprecated_positions.items()):
                if (spec.position < len(args)
                        and not (spec.has_ok_value and _same_value(
                            named_args[arg_name], spec.ok_value))):
                    invalid_args.append(arg_name)
            if is_varargs_deprecated and len(args) > len(arg_spec.args):
                invalid_args.append(arg_spec.varargs)
            if is_kwargs_deprecated and kwargs:
                invalid_args.append(arg_spec.keywords)
            for arg_name in deprecated_arg_names:
                if (arg_name in kwargs and
                        not (deprecated_positions[arg_name].has_ok_value
                             and _same_value(
                                 named_args[arg_name],
                                 deprecated_positions[arg_name].ok_value))):
                    invalid_args.append(arg_name)
            for arg_name in invalid_args:
                logging.warning(
                    'From %s: calling %s (from %s) with %s is deprecated and will '
                    'be removed %s.\nInstructions for updating:\n%s',
                    _call_location(), decorator_utils.get_qualified_name(func),
                    func.__module__, arg_name,
                    'in a future version' if date is None else
                    ('after %s' % date), instructions)
            return func(*args, **kwargs)

        return tf_decorator.make_decorator(
            func, new_func, 'deprecated',
            _add_deprecated_arg_notice_to_docstring(func.__doc__, date,
                                                    instructions))
Ejemplo n.º 24
0
  def deprecated_wrapper(func):
    """Deprecation decorator."""
    decorator_utils.validate_callable(func, 'deprecated_args')
    deprecated_arg_names = _get_arg_names_to_ok_vals()

    arg_spec = inspect.getargspec(func)
    deprecated_positions = _get_deprecated_positional_arguments(
        deprecated_arg_names, arg_spec)

    is_varargs_deprecated = arg_spec.varargs in deprecated_arg_names
    is_kwargs_deprecated = arg_spec.keywords in deprecated_arg_names

    if (len(deprecated_positions) + is_varargs_deprecated + is_kwargs_deprecated
        != len(deprecated_arg_names_or_tuples)):
      known_args = arg_spec.args + [arg_spec.varargs, arg_spec.keywords]
      missing_args = [arg_name for arg_name in deprecated_arg_names
                      if arg_name not in known_args]
      raise ValueError('The following deprecated arguments are not present '
                       'in the function signature: %s. '
                       'Found next arguments: %s.' % (missing_args, known_args))

    def _same_value(a, b):
      """A comparison operation that works for multiple object types.

      Returns True for two empty lists, two numeric values with the
      same value, etc.

      Returns False for (pd.DataFrame, None), and other pairs which
      should not be considered equivalent.

      Args:
        a: value one of the comparison.
        b: value two of the comparison.

      Returns:
        A boolean indicating whether the two inputs are the same value
        for the purposes of deprecation.
      """
      if a is b:
        return True
      try:
        equality = a == b
        if isinstance(equality, bool):
          return equality
      except TypeError:
        return False
      return False

    @functools.wraps(func)
    def new_func(*args, **kwargs):
      """Deprecation wrapper."""
      invalid_args = []
      named_args = inspect.getcallargs(func, *args, **kwargs)
      for arg_name, spec in iter(deprecated_positions.items()):
        if (spec.position < len(args) and
            not (spec.has_ok_value and
                 _same_value(named_args[arg_name], spec.ok_value))):
          invalid_args.append(arg_name)
      if is_varargs_deprecated and len(args) > len(arg_spec.args):
        invalid_args.append(arg_spec.varargs)
      if is_kwargs_deprecated and kwargs:
        invalid_args.append(arg_spec.keywords)
      for arg_name in deprecated_arg_names:
        if (arg_name in kwargs and
            not (deprecated_positions[arg_name].has_ok_value and
                 _same_value(named_args[arg_name],
                             deprecated_positions[arg_name].ok_value))):
          invalid_args.append(arg_name)
      for arg_name in invalid_args:
        logging.warning(
            'From %s: calling %s (from %s) with %s is deprecated and will '
            'be removed after %s.\nInstructions for updating:\n%s',
            _call_location(), decorator_utils.get_qualified_name(func),
            func.__module__, arg_name, date, instructions)
      return func(*args, **kwargs)
    new_func.__doc__ = _add_deprecated_arg_notice_to_docstring(
        func.__doc__, date, instructions)
    return new_func
Ejemplo n.º 25
0
 def test_method(self):
   decorator_utils.validate_callable(self.test_method, "test")
Ejemplo n.º 26
0
    def deprecated_wrapper(func):
        """Deprecation decorator."""
        decorator_utils.validate_callable(func, 'deprecated_args')

        arg_spec = tf_inspect.getfullargspec(func)
        deprecated_positions = _get_deprecated_positional_arguments(
            deprecated_arg_names, arg_spec)

        is_varargs_deprecated = arg_spec.varargs in deprecated_arg_names
        is_kwargs_deprecated = arg_spec.varkw in deprecated_arg_names

        if (len(deprecated_positions) + is_varargs_deprecated +
                is_kwargs_deprecated != len(deprecated_arg_names_or_tuples)):
            known_args = (arg_spec.args + arg_spec.kwonlyargs +
                          [arg_spec.varargs, arg_spec.varkw])
            missing_args = [
                arg_name for arg_name in deprecated_arg_names
                if arg_name not in known_args
            ]
            raise ValueError(
                'The following deprecated arguments are not present '
                f'in the function signature: {missing_args}. '
                'Expected arguments from the following list: '
                f'{known_args}.')

        def _same_value(a, b):
            """A comparison operation that works for multiple object types.

      Returns True for two empty lists, two numeric values with the
      same value, etc.

      Returns False for (pd.DataFrame, None), and other pairs which
      should not be considered equivalent.

      Args:
        a: value one of the comparison.
        b: value two of the comparison.

      Returns:
        A boolean indicating whether the two inputs are the same value
        for the purposes of deprecation.
      """
            if a is b:
                return True
            try:
                equality = a == b
                if isinstance(equality, bool):
                    return equality
            except TypeError:
                return False
            return False

        @functools.wraps(func)
        def new_func(*args, **kwargs):
            """Deprecation wrapper."""
            # TODO(apassos) figure out a way to have reasonable performance with
            # deprecation warnings and eager mode.
            if is_in_graph_mode.IS_IN_GRAPH_MODE(
            ) and _PRINT_DEPRECATION_WARNINGS:
                invalid_args = []
                named_args = tf_inspect.getcallargs(func, *args, **kwargs)
                for arg_name, spec in iter(deprecated_positions.items()):
                    if (spec.position < len(args)
                            and not (spec.has_ok_value and _same_value(
                                named_args[arg_name], spec.ok_value))):
                        invalid_args.append(arg_name)
                if is_varargs_deprecated and len(args) > len(arg_spec.args):
                    invalid_args.append(arg_spec.varargs)
                if is_kwargs_deprecated and kwargs:
                    invalid_args.append(arg_spec.varkw)
                for arg_name in deprecated_arg_names:
                    if (arg_name in kwargs and not (
                            deprecated_positions[arg_name].has_ok_value
                            and _same_value(
                                named_args[arg_name],
                                deprecated_positions[arg_name].ok_value))):
                        invalid_args.append(arg_name)
                for arg_name in invalid_args:
                    if (func, arg_name) not in _PRINTED_WARNING:
                        if warn_once:
                            _PRINTED_WARNING[(func, arg_name)] = True
                        logging.warning(
                            'From %s: calling %s (from %s) with %s is deprecated and will '
                            'be removed %s.\nInstructions for updating:\n%s',
                            _call_location(),
                            decorator_utils.get_qualified_name(func),
                            func.__module__, arg_name,
                            'in a future version' if date is None else
                            ('after %s' % date), instructions)
            return func(*args, **kwargs)

        doc = _add_deprecated_arg_notice_to_docstring(
            func.__doc__, date, instructions,
            sorted(deprecated_arg_names.keys()))
        return tf_decorator.make_decorator(func, new_func, 'deprecated', doc)
Ejemplo n.º 27
0
 def test_method(self):
     decorator_utils.validate_callable(self.test_method, "test")
Ejemplo n.º 28
0
def deprecated_alias(deprecated_name, name, func_or_class, warn_once=True):
    """Deprecate a symbol in favor of a new name with identical semantics.

  This function is meant to be used when defining a backwards-compatibility
  alias for a symbol which has been moved. For example:

  module1.py:
  ```python
  class NewNameForClass: pass
  ```

  module2.py:
  ```python
  import module1

  DeprecatedNameForClass = deprecated_alias(
    deprecated_name='module2.DeprecatedNameForClass',
    name='module1.NewNameForClass',
    func_or_class=module1.NewNameForClass)
  ```

  This function works for classes and functions.

  For classes, it creates a new class which is functionally identical (it
  inherits from the original, and overrides its constructor), but which prints
  a deprecation warning when an instance is created. It also adds a deprecation
  notice to the class' docstring.

  For functions, it returns a function wrapped by `tf_decorator.make_decorator`.
  That function prints a warning when used, and has a deprecation notice in its
  docstring. This is more or less equivalent (the deprecation warning has
  slightly different text) to writing:

  ```python
  @deprecated
  def deprecated_alias(original_args):
    real_function(original_args)
  ```

  Args:
    deprecated_name: The name of the symbol that is being deprecated, to be used
      in the warning message. This should be its fully qualified name to avoid
      confusion.
    name: The name of the symbol that is to be used instead of the deprecated
      name. This should be a fully qualified name to avoid confusion.
    func_or_class: The (non-deprecated) class or function for which a deprecated
      alias should be created.
    warn_once: If True (the default), only print a deprecation warning the first
      time this function is used, or the class is instantiated.

  Returns:
    A wrapped version of `func_or_class` which prints a deprecation warning on
    use and has a modified docstring.
  """
    if tf_inspect.isclass(func_or_class):

        # Make a new class with __init__ wrapped in a warning.
        class _NewClass(func_or_class):  # pylint: disable=missing-docstring
            __doc__ = decorator_utils.add_notice_to_docstring(
                func_or_class.__doc__, 'Please use %s instead.' % name,
                'DEPRECATED CLASS', '(deprecated)', [
                    'THIS CLASS IS DEPRECATED. '
                    'It will be removed in a future version. '
                ])
            __name__ = func_or_class.__name__
            __module__ = _call_location(outer=True)

            @_wrap_decorator(func_or_class.__init__)
            def __init__(self, *args, **kwargs):
                if hasattr(_NewClass.__init__, '__func__'):
                    # Python 2
                    _NewClass.__init__.__func__.__doc__ = func_or_class.__init__.__doc__
                else:
                    # Python 3
                    _NewClass.__init__.__doc__ = func_or_class.__init__.__doc__

                if _PRINT_DEPRECATION_WARNINGS:
                    # We're making the alias as we speak. The original may have other
                    # aliases, so we cannot use it to check for whether it's already been
                    # warned about.
                    if _NewClass.__init__ not in _PRINTED_WARNING:
                        if warn_once:
                            _PRINTED_WARNING[_NewClass.__init__] = True
                        logging.warning(
                            'From %s: The name %s is deprecated. Please use %s instead.\n',
                            _call_location(), deprecated_name, name)
                super(_NewClass, self).__init__(*args, **kwargs)

        return _NewClass
    else:
        decorator_utils.validate_callable(func_or_class, 'deprecated')

        # Make a wrapper for the original
        @functools.wraps(func_or_class)
        def new_func(*args, **kwargs):  # pylint: disable=missing-docstring
            if _PRINT_DEPRECATION_WARNINGS:
                # We're making the alias as we speak. The original may have other
                # aliases, so we cannot use it to check for whether it's already been
                # warned about.
                if new_func not in _PRINTED_WARNING:
                    if warn_once:
                        _PRINTED_WARNING[new_func] = True
                    logging.warning(
                        'From %s: The name %s is deprecated. Please use %s instead.\n',
                        _call_location(), deprecated_name, name)
            return func_or_class(*args, **kwargs)

        return tf_decorator.make_decorator(
            func_or_class, new_func, 'deprecated',
            _add_deprecated_function_notice_to_docstring(
                func_or_class.__doc__, None, 'Please use %s instead.' % name))
Ejemplo n.º 29
0
 def test_function(self):
   decorator_utils.validate_callable(_test_function, "test")
Ejemplo n.º 30
0
 def test_partial(self):
   partial = functools.partial(_test_function, unused_arg=7)
   decorator_utils.validate_callable(partial, "test")
Ejemplo n.º 31
0
 def test_partial(self):
     partial = functools.partial(_test_function, unused_arg=7)
     decorator_utils.validate_callable(partial, "test")
Ejemplo n.º 32
0
 def test_function(self):
     decorator_utils.validate_callable(_test_function, "test")