# This code is part of Qiskit.
#
# (C) Copyright IBM 2017.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""Deprecation utilities"""

import functools
import warnings


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

    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            if kwargs:
                _rename_kwargs(func.__name__, kwargs, kwarg_map)
            return func(*args, **kwargs)

        return wrapper

    return decorator


def deprecate_function(msg, stacklevel=2):
    """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.

    Returns:
        Callable: The decorated, deprecated callable.
    """

    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            warnings.warn(msg, DeprecationWarning, stacklevel=stacklevel)
            return func(*args, **kwargs)

        return wrapper

    return decorator


def _rename_kwargs(func_name, kwargs, kwarg_map):
    for old_arg, new_arg in kwarg_map.items():
        if old_arg in kwargs:
            if new_arg in kwargs:
                raise TypeError(f"{func_name} received both {new_arg} and {old_arg} (deprecated).")

            warnings.warn(
                "{} keyword argument {} is deprecated and "
                "replaced with {}.".format(func_name, old_arg, new_arg),
                DeprecationWarning,
                stacklevel=3,
            )

            kwargs[new_arg] = kwargs.pop(old_arg)

@@ -1755,16 +1755,52 @@
 ed).%22)%0A%0A
+            if new_arg is None:%0A    
         
@@ -1834,18 +1834,32 @@
         
-%22%7B
+    f%22%7Bfunc_name
 %7D keywor
@@ -1870,16 +1870,23 @@
 gument %7B
+old_arg
 %7D is dep
@@ -1919,65 +1919,317 @@
     
-%22replaced with %7B%7D.%22.format(func_name, old_arg, new_arg),%0A
+    %22will in future be removed.%22,%0A                    DeprecationWarning,%0A                    stacklevel=3,%0A                )%0A            else:%0A                warnings.warn(%0A                    f%22%7Bfunc_name%7D keyword argument %7Bold_arg%7D is deprecated and %22%0A                    f%22replaced with %7Bnew_arg%7D.%22,%0A    
     
@@ -2268,32 +2268,36 @@
                 
+ 
+   
 stacklevel=3,%0A  
@@ -2306,19 +2306,27 @@
         
-)%0A%0A
+    )%0A%0A    
         

Support deprecate_arguments with new_arg None (#8613)