| 190 | should_warn = any([is_deprecated, is_unsupported]) |
| 191 | |
| 192 | def _function_wrapper(function): |
| 193 | if should_warn: |
| 194 | # Everything *should* have a docstring, but just in case... |
| 195 | existing_docstring = function.__doc__ or "" |
| 196 | |
| 197 | # The various parts of this decorator being optional makes for |
| 198 | # a number of ways the deprecation notice could go. The following |
| 199 | # makes for a nicely constructed sentence with or without any |
| 200 | # of the parts. |
| 201 | |
| 202 | # If removed_in is a date, use "removed on" |
| 203 | # If removed_in is a version, use "removed in" |
| 204 | parts = { |
| 205 | "deprecated_in": |
| 206 | " %s" % deprecated_in if deprecated_in else "<unknown>", |
| 207 | "removed_in": |
| 208 | "\n This will be removed {} {}.".format("on" if isinstance(removed_in, date) else "in", |
| 209 | removed_in) if removed_in else "", |
| 210 | "details": |
| 211 | " %s" % details if details else ""} |
| 212 | |
| 213 | deprecation_note = (".. deprecated::{deprecated_in}" |
| 214 | "{removed_in}{details}".format(**parts)) |
| 215 | |
| 216 | # default location for insertion of deprecation note |
| 217 | loc = 1 |
| 218 | |
| 219 | # split docstring at first occurrence of newline |
| 220 | string_list = existing_docstring.split("\n", 1) |
| 221 | |
| 222 | if len(string_list) > 1: |
| 223 | # With a multi-line docstring, when we modify |
| 224 | # existing_docstring to add our deprecation_note, |
| 225 | # if we're not careful we'll interfere with the |
| 226 | # indentation levels of the contents below the |
| 227 | # first line, or as PEP 257 calls it, the summary |
| 228 | # line. Since the summary line can start on the |
| 229 | # same line as the """, dedenting the whole thing |
| 230 | # won't help. Split the summary and contents up, |
| 231 | # dedent the contents independently, then join |
| 232 | # summary, dedent'ed contents, and our |
| 233 | # deprecation_note. |
| 234 | |
| 235 | # in-place dedent docstring content |
| 236 | string_list[1] = textwrap.dedent(string_list[1]) |
| 237 | |
| 238 | # we need another newline |
| 239 | string_list.insert(loc, "\n") |
| 240 | |
| 241 | # change the message_location if we add to end of docstring |
| 242 | # do this always if not "top" |
| 243 | if message_location != "top": |
| 244 | loc = 3 |
| 245 | |
| 246 | # insert deprecation note and dual newline |
| 247 | string_list.insert(loc, deprecation_note) |
| 248 | string_list.insert(loc, "\n\n") |
| 249 | |