/
experimental.py
104 lines (70 loc) · 2.91 KB
/
experimental.py
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import chainer
import warnings
def experimental(api_name):
"""Declares that user is using an experimental feature.
The developer of an API can mark it as *experimental* by calling
this function. When users call experimental APIs, :class:`FutureWarning`
is issued.
The presentation of :class:`FutureWarning` is disabled by setting
``chainer.disable_experimental_feature_warning`` to ``True``,
which is ``False`` by default.
The basic usage is to call it in the function or method we want to
mark as experimental along with the API name.
.. testsetup::
import sys
import warnings
warnings.simplefilter('always')
def wrapper(message, category, filename, lineno, file=None, line=None):
sys.stdout.write(warnings.formatwarning(
message, category, filename, lineno))
showwarning_orig = warnings.showwarning
warnings.showwarning = wrapper
.. testcleanup::
warnings.showwarning = showwarning_orig
.. testcode::
from chainer import utils
def f(x):
utils.experimental('chainer.foo.bar.f')
# concrete implementation of f follows
f(1)
.. testoutput::
:options: +ELLIPSIS, +NORMALIZE_WHITESPACE
... FutureWarning: chainer.foo.bar.f is experimental. \
The interface can change in the future. ...
We can also make a whole class experimental. In that case,
we should call this function in its ``__init__`` method.
.. testcode::
class C():
def __init__(self):
utils.experimental('chainer.foo.C')
C()
.. testoutput::
:options: +ELLIPSIS, +NORMALIZE_WHITESPACE
... FutureWarning: chainer.foo.C is experimental. \
The interface can change in the future. ...
If we want to mark ``__init__`` method only, rather than class itself,
it is recommended that we explicitly feed its API name.
.. testcode::
class D():
def __init__(self):
utils.experimental('D.__init__')
D()
.. testoutput::
:options: +ELLIPSIS, +NORMALIZE_WHITESPACE
... FutureWarning: D.__init__ is experimental. \
The interface can change in the future. ...
Currently, we do not have any sophisticated way to mark some usage of
non-experimental function as experimental.
But we can support such usage by explicitly branching it.
.. testcode::
def g(x, experimental_arg=None):
if experimental_arg is not None:
utils.experimental('experimental_arg of chainer.foo.g')
Args:
api_name(str): The name of an API marked as experimental.
"""
if not chainer.disable_experimental_feature_warning:
warnings.warn('{} is experimental. '
'The interface can change in the future.'.format(
api_name),
FutureWarning)