diff options
Diffstat (limited to 'tensorflow/python/util/deprecation.py')
-rw-r--r-- | tensorflow/python/util/deprecation.py | 72 |
1 files changed, 64 insertions, 8 deletions
diff --git a/tensorflow/python/util/deprecation.py b/tensorflow/python/util/deprecation.py index 376be39978..9e2202eaf8 100644 --- a/tensorflow/python/util/deprecation.py +++ b/tensorflow/python/util/deprecation.py @@ -37,6 +37,11 @@ _PRINT_DEPRECATION_WARNINGS = True _PRINTED_WARNING = {} +class DeprecatedNamesAlreadySet(Exception): + """Raised when setting deprecated names multiple times for the same symbol.""" + pass + + def _add_deprecated_function_notice_to_docstring(doc, date, instructions): """Adds a deprecation notice to a docstring for deprecated functions.""" main_text = ['THIS FUNCTION IS DEPRECATED. It will be removed %s.' % @@ -87,6 +92,27 @@ def _call_location(outer=False): return '%s:%d' % (entry[1], entry[2]) +def _wrap_decorator(wrapped_function): + """Indicate that one function wraps another. + + This decorator wraps a function using `tf_decorator.make_decorator` + so that doc generation scripts can pick up original function + signature. + It would be better to use @functools.wrap decorator, but it would + not update function signature to match wrapped function in Python 2. + + Args: + wrapped_function: The function that decorated function wraps. + + Returns: + Function that accepts wrapper function as an argument and returns + `TFDecorator` instance. + """ + def wrapper(wrapper_func): + return tf_decorator.make_decorator(wrapped_function, wrapper_func) + return wrapper + + def deprecated_alias(deprecated_name, name, func_or_class, warn_once=True): """Deprecate a symbol in favor of a new name with identical semantics. @@ -144,7 +170,7 @@ def deprecated_alias(deprecated_name, name, func_or_class, warn_once=True): 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 + 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', @@ -153,27 +179,28 @@ def deprecated_alias(deprecated_name, name, func_or_class, warn_once=True): __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__'): + if hasattr(_NewClass.__init__, '__func__'): # Python 2 - NewClass.__init__.__func__.__doc__ = func_or_class.__init__.__doc__ + _NewClass.__init__.__func__.__doc__ = func_or_class.__init__.__doc__ else: # Python 3 - NewClass.__init__.__doc__ = func_or_class.__init__.__doc__ + _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 _NewClass.__init__ not in _PRINTED_WARNING: if warn_once: - _PRINTED_WARNING[NewClass.__init__] = True + _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) + super(_NewClass, self).__init__(*args, **kwargs) - return NewClass + return _NewClass else: decorator_utils.validate_callable(func_or_class, 'deprecated') @@ -197,6 +224,35 @@ def deprecated_alias(deprecated_name, name, func_or_class, warn_once=True): func_or_class.__doc__, None, 'Please use %s instead.' % name)) +def deprecated_endpoints(*args): + """Decorator for marking endpoints deprecated. + + This decorator does not print deprecation messages. + TODO(annarev): eventually start printing deprecation warnings when + @deprecation_endpoints decorator is added. + + Args: + *args: Deprecated endpoint names. + + Returns: + A function that takes symbol as an argument and adds + _tf_deprecated_api_names to that symbol. + _tf_deprecated_api_names would be set to a list of deprecated + endpoint names for the symbol. + """ + def deprecated_wrapper(func): + # pylint: disable=protected-access + if '_tf_deprecated_api_names' in func.__dict__: + raise DeprecatedNamesAlreadySet( + 'Cannot set deprecated names for %s to %s. ' + 'Deprecated names are already set to %s.' % ( + func.__name__, str(args), str(func._tf_deprecated_api_names))) + func._tf_deprecated_api_names = args + # pylint: disable=protected-access + return func + return deprecated_wrapper + + def deprecated(date, instructions, warn_once=True): """Decorator for marking functions or methods deprecated. |