Completed
Pull Request — master (#519)
by
unknown
59s
created

finalize()   A

Complexity

Conditions 1

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 1
c 3
b 0
f 0
dl 0
loc 9
rs 9.6666
1
# Copyright (c) 2008-2017 MetPy Developers.
2
# Distributed under the terms of the BSD 3-Clause License.
3
# SPDX-License-Identifier: BSD-3-Clause
4
5
"""Matplotlib license for the deprecation module.
6
7
License agreement for matplotlib versions 1.3.0 and later
8
=========================================================
9
10
1. This LICENSE AGREEMENT is between the Matplotlib Development Team
11
("MDT"), and the Individual or Organization ("Licensee") accessing and
12
otherwise using matplotlib software in source or binary form and its
13
associated documentation.
14
15
2. Subject to the terms and conditions of this License Agreement, MDT
16
hereby grants Licensee a nonexclusive, royalty-free, world-wide license
17
to reproduce, analyze, test, perform and/or display publicly, prepare
18
derivative works, distribute, and otherwise use matplotlib
19
alone or in any derivative version, provided, however, that MDT's
20
License Agreement and MDT's notice of copyright, i.e., "Copyright (c)
21
2012- Matplotlib Development Team; All Rights Reserved" are retained in
22
matplotlib  alone or in any derivative version prepared by
23
Licensee.
24
25
3. In the event Licensee prepares a derivative work that is based on or
26
incorporates matplotlib or any part thereof, and wants to
27
make the derivative work available to others as provided herein, then
28
Licensee hereby agrees to include in any such work a brief summary of
29
the changes made to matplotlib .
30
31
4. MDT is making matplotlib available to Licensee on an "AS
32
IS" basis.  MDT MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
33
IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, MDT MAKES NO AND
34
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
35
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF MATPLOTLIB
36
WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
37
38
5. MDT SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF MATPLOTLIB
39
 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR
40
LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING
41
MATPLOTLIB , OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF
42
THE POSSIBILITY THEREOF.
43
44
6. This License Agreement will automatically terminate upon a material
45
breach of its terms and conditions.
46
47
7. Nothing in this License Agreement shall be deemed to create any
48
relationship of agency, partnership, or joint venture between MDT and
49
Licensee.  This License Agreement does not grant permission to use MDT
50
trademarks or trade name in a trademark sense to endorse or promote
51
products or services of Licensee, or any third party.
52
53
8. By copying, installing or otherwise using matplotlib ,
54
Licensee agrees to be bound by the terms and conditions of this License
55
Agreement.
56
57
License agreement for matplotlib versions prior to 1.3.0
58
========================================================
59
60
1. This LICENSE AGREEMENT is between John D. Hunter ("JDH"), and the
61
Individual or Organization ("Licensee") accessing and otherwise using
62
matplotlib software in source or binary form and its associated
63
documentation.
64
65
2. Subject to the terms and conditions of this License Agreement, JDH
66
hereby grants Licensee a nonexclusive, royalty-free, world-wide license
67
to reproduce, analyze, test, perform and/or display publicly, prepare
68
derivative works, distribute, and otherwise use matplotlib
69
alone or in any derivative version, provided, however, that JDH's
70
License Agreement and JDH's notice of copyright, i.e., "Copyright (c)
71
2002-2011 John D. Hunter; All Rights Reserved" are retained in
72
matplotlib  alone or in any derivative version prepared by
73
Licensee.
74
75
3. In the event Licensee prepares a derivative work that is based on or
76
incorporates matplotlib  or any part thereof, and wants to
77
make the derivative work available to others as provided herein, then
78
Licensee hereby agrees to include in any such work a brief summary of
79
the changes made to matplotlib.
80
81
4. JDH is making matplotlib  available to Licensee on an "AS
82
IS" basis.  JDH MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
83
IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, JDH MAKES NO AND
84
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
85
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF MATPLOTLIB
86
WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
87
88
5. JDH SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF MATPLOTLIB
89
 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR
90
LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING
91
MATPLOTLIB , OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF
92
THE POSSIBILITY THEREOF.
93
94
6. This License Agreement will automatically terminate upon a material
95
breach of its terms and conditions.
96
97
7. Nothing in this License Agreement shall be deemed to create any
98
relationship of agency, partnership, or joint venture between JDH and
99
Licensee.  This License Agreement does not grant permission to use JDH
100
trademarks or trade name in a trademark sense to endorse or promote
101
products or services of Licensee, or any third party.
102
103
8. By copying, installing or otherwise using matplotlib,
104
Licensee agrees to be bound by the terms and conditions of this License
105
Agreement.
106
"""
107
108
import functools
109
import warnings
110
111
112
class MetpyDeprecationWarning(UserWarning):
113
    """A class for issuing deprecation warnings for MetPy users.
114
115
    In light of the fact that Python builtin DeprecationWarnings are ignored
116
    by default as of Python 2.7 (see link below), this class was put in to
117
    allow for the signaling of deprecation, but via UserWarnings which are not
118
    ignored by default. Borrowed with love from matplotlib.
119
120
    https://docs.python.org/dev/whatsnew/2.7.html#the-future-for-python-2-x
121
    """
122
123
    pass
124
125
126
metpyDeprecation = MetpyDeprecationWarning
127
128
129
def _generate_deprecation_message(since, message='', name='',
130
                                  alternative='', pending=False,
131
                                  obj_type='attribute',
132
                                  addendum=''):
133
134
    if not message:
135
136
        if pending:
137
            message = (
138
                'The {} {} will be deprecated in a '
139
                'future version.'.format(name, obj_type))
140
        else:
141
            message = (
142
                'The {} {} was deprecated in version '
143
                '{}.'.format(name, obj_type, since))
144
145
    altmessage = ''
146
    if alternative:
147
        altmessage = ' Use {} instead.'.format(alternative)
148
149
    message = message + altmessage
150
151
    if addendum:
152
        message += addendum
153
154
    return message
155
156
157
def warn_deprecated(since, message='', name='', alternative='', pending=False,
158
                    obj_type='attribute', addendum=''):
159
    """Display deprecation warning in a standard way.
160
161
    Parameters
162
    ----------
163
    since : str
164
        The release at which this API became deprecated.
165
166
    message : str, optional
167
        Override the default deprecation message.  The format
168
        specifier `%(name)s` may be used for the name of the function,
169
        and `%(alternative)s` may be used in the deprecation message
170
        to insert the name of an alternative to the deprecated
171
        function.  `%(obj_type)s` may be used to insert a friendly name
172
        for the type of object being deprecated.
173
174
    name : str, optional
175
        The name of the deprecated object.
176
177
    alternative : str, optional
178
        An alternative function that the user may use in place of the
179
        deprecated function.  The deprecation warning will tell the user
180
        about this alternative if provided.
181
182
    pending : bool, optional
183
        If True, uses a PendingDeprecationWarning instead of a
184
        DeprecationWarning.
185
186
    obj_type : str, optional
187
        The object type being deprecated.
188
189
    addendum : str, optional
190
        Additional text appended directly to the final message.
191
192
    Examples
193
    --------
194
        Basic example::
195
196
            # To warn of the deprecation of "metpy.name_of_module"
197
            warn_deprecated('0.6.0', name='metpy.name_of_module',
198
                            obj_type='module')
199
200
    """
201
    message = _generate_deprecation_message(since, message, name, alternative,
202
                                            pending, obj_type)
203
204
    warnings.warn(message, metpyDeprecation, stacklevel=1)
205
206
207
def deprecated(since, message='', name='', alternative='', pending=False,
208
               obj_type=None, addendum=''):
209
    """Mark a function or a class as deprecated.
210
211
    Parameters
212
    ----------
213
    since : str
214
        The release at which this API became deprecated.  This is
215
        required.
216
217
    message : str, optional
218
        Override the default deprecation message.  The format
219
        specifier `%(name)s` may be used for the name of the object,
220
        and `%(alternative)s` may be used in the deprecation message
221
        to insert the name of an alternative to the deprecated
222
        object.  `%(obj_type)s` may be used to insert a friendly name
223
        for the type of object being deprecated.
224
225
    name : str, optional
226
        The name of the deprecated object; if not provided the name
227
        is automatically determined from the passed in object,
228
        though this is useful in the case of renamed functions, where
229
        the new function is just assigned to the name of the
230
        deprecated function.  For example::
231
232
            def new_function():
233
                ...
234
            oldFunction = new_function
235
236
    alternative : str, optional
237
        An alternative object that the user may use in place of the
238
        deprecated object.  The deprecation warning will tell the user
239
        about this alternative if provided.
240
241
    pending : bool, optional
242
        If True, uses a PendingDeprecationWarning instead of a
243
        DeprecationWarning.
244
245
    addendum : str, optional
246
        Additional text appended directly to the final message.
247
248
    Examples
249
    --------
250
        Basic example::
251
252
            @deprecated('1.4.0')
253
            def the_function_to_deprecate():
254
                pass
255
256
    """
257
    def deprecate(obj, message=message, name=name, alternative=alternative,
258
                  pending=pending, addendum=addendum):
259
        import textwrap
260
261
        if not name:
262
            name = obj.__name__
263
264
        if isinstance(obj, type):
265
            obj_type = 'class'
266
            old_doc = obj.__doc__
267
            func = obj.__init__
268
269
            def finalize(wrapper, new_doc):
270
                try:
271
                    obj.__doc__ = new_doc
272
                except (AttributeError, TypeError):
273
                    # cls.__doc__ is not writeable on Py2.
274
                    # TypeError occurs on PyPy
275
                    pass
276
                obj.__init__ = wrapper
277
                return obj
278
        else:
279
            obj_type = 'function'
280
            if isinstance(obj, classmethod):
281
                func = obj.__func__
282
                old_doc = func.__doc__
283
284
                def finalize(wrapper, new_doc):
285
                    wrapper = functools.wraps(func)(wrapper)
286
                    wrapper.__doc__ = new_doc
287
                    return classmethod(wrapper)
288
            else:
289
                func = obj
290
                old_doc = func.__doc__
291
292
                def finalize(wrapper, new_doc):
293
                    wrapper = functools.wraps(func)(wrapper)
294
                    wrapper.__doc__ = new_doc
295
                    return wrapper
296
297
        message = _generate_deprecation_message(since, message, name,
298
                                                alternative, pending,
299
                                                obj_type, addendum)
300
301
        def wrapper(*args, **kwargs):
302
            warnings.warn(message, metpyDeprecation, stacklevel=2)
303
            return func(*args, **kwargs)
304
305
        old_doc = textwrap.dedent(old_doc or '').strip('\n')
306
        message = message.strip()
307
        new_doc = ('\n.. deprecated:: {}'
308
                   '\n    {}\n\n'.format(since, message) + old_doc)
309
        if not old_doc:
310
            # This is to prevent a spurious 'unexected unindent' warning from
311
            # docutils when the original docstring was blank.
312
            new_doc += r'\ '
313
314
        return finalize(wrapper, new_doc)
315
316
    return deprecate
317