File size: 2,465 Bytes
f5f3483
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# Copyright 2020 DeepMind Technologies Limited. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""Utilities to emit warnings."""

import functools
import warnings


def warn_only_n_pos_args_in_future(fun, n):
  """Warns if more than ``n`` positional arguments are passed to ``fun``.

  For instance:
  >>> @functools.partial(chex.warn_only_n_pos_args_in_future, n=1)
  ... def f(a, b, c=1):
  ...   return a + b + c

  Will raise a DeprecationWarning if ``f`` is called with more than one
  positional argument (e.g. both f(1, 2, 3) and f(1, 2, c=3) raise a warning).

  Args:
    fun: the function to wrap.
    n: the number of positional arguments to allow.

  Returns:
    A wrapped function that emits a warning if more than `n` positional
    arguments are passed.
  """

  @functools.wraps(fun)
  def wrapper(*args, **kwargs):
    if len(args) > n:
      warnings.warn(
          f'only the first {n} arguments can be passed positionally '
          'additional args will become keyword-only soon',
          DeprecationWarning,
          stacklevel=2
          )
    return fun(*args, **kwargs)

  return wrapper


warn_keyword_args_only_in_future = functools.partial(
    warn_only_n_pos_args_in_future, n=0
)


def warn_deprecated_function(fun, replacement):
  """A decorator to mark a function definition as deprecated.

  Example usage:
  @warn_deprecated_function(fun, replacement='g')
  def f(a, b):
    return a + b

  Args:
    fun: the deprecated function.
    replacement: the name of the function to be used instead.

  Returns:
    the wrapped function.
  """

  @functools.wraps(fun)
  def new_fun(*args, **kwargs):
    warnings.warn(
        f'The function {fun.__name__} is deprecated, '
        f'please use {replacement} instead.',
        category=DeprecationWarning,
        stacklevel=2)
    return fun(*args, **kwargs)
  return new_fun