Skip to content

Commit

Permalink
deprecate_arguments and deprecate_function: add a deprecation note box
Browse files Browse the repository at this point in the history
  • Loading branch information
1ucian0 committed Aug 28, 2022
1 parent 9f5f8fb commit 2dd1af7
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 4 deletions.
5 changes: 3 additions & 2 deletions qiskit/circuit/quantumcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -716,10 +716,11 @@ def control(
@deprecate_function(
"The QuantumCircuit.combine() method is being deprecated. "
"Use the compose() method which is more flexible w.r.t "
"circuit register compatibility."
"circuit register compatibility.",
docstring_version="0.17.0",
)
def combine(self, rhs: "QuantumCircuit") -> "QuantumCircuit":
"""DEPRECATED - Returns rhs appended to self if self contains compatible registers.
"""Returns rhs appended to self if self contains compatible registers.
Two circuits are compatible if they contain the same registers
or if they contain different registers with unique names. The
Expand Down
46 changes: 44 additions & 2 deletions qiskit/utils/deprecation.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,17 @@
import warnings


def deprecate_arguments(kwarg_map):
def deprecate_arguments(kwarg_map, docstring_version=None):
"""Decorator to automatically alias deprecated argument names and warn upon use."""

def decorator(func):
if docstring_version and kwarg_map:
msg = ["One or more keyword argument are being deprecated:", ""]
for old_arg, new_arg in kwarg_map.items():
msg.append("* The argument {} is being replaced with {}".format(old_arg, new_arg))
msg.append("") # Finish with an empty line
_extend_docstring(func, msg, docstring_version)

@functools.wraps(func)
def wrapper(*args, **kwargs):
if kwargs:
Expand All @@ -31,18 +38,23 @@ def wrapper(*args, **kwargs):
return decorator


def deprecate_function(msg, stacklevel=2):
def deprecate_function(msg, stacklevel=2, docstring_version=None):
"""Emit a warning prior to calling decorated function.
Args:
msg (str): Warning message to emit.
stacklevel (int): The warning stackevel to use, defaults to 2.
docstring_version (str): If a version number, extends the docstring with a deprecation warning
box. If `None`, no docstring box will be added. Default: None
Returns:
Callable: The decorated, deprecated callable.
"""

def decorator(func):
if docstring_version:
_extend_docstring(func, msg.expandtabs().splitlines(), docstring_version)

@functools.wraps(func)
def wrapper(*args, **kwargs):
warnings.warn(msg, DeprecationWarning, stacklevel=stacklevel)
Expand All @@ -67,3 +79,33 @@ def _rename_kwargs(func_name, kwargs, kwarg_map):
)

kwargs[new_arg] = kwargs.pop(old_arg)


def _extend_docstring(func, msg_lines, version):
docstr = func.__doc__
if docstr:
docstr_lines = docstr.expandtabs().splitlines()
else:
docstr_lines = ["DEPRECATED"]
indent = 1000
first_empty_line = None
for line_no, line in enumerate(docstr_lines[1:], start=1):
stripped = line.lstrip()
if stripped:
indent = min(indent, len(line) - len(stripped))
else:
if first_empty_line is None:
first_empty_line = line_no
if first_empty_line is None:
first_empty_line = len(docstr_lines)
spaces = ""
if indent != 1000:
spaces = " " * indent

new_doc_str_lines = docstr_lines[:first_empty_line] + [
"",
spaces + f".. deprecated:: {version}",
]
for msg_line in msg_lines:
new_doc_str_lines.append(spaces + " " + msg_line)
func.__doc__ = "\n".join(new_doc_str_lines + docstr_lines[first_empty_line:])

0 comments on commit 2dd1af7

Please sign in to comment.