Repository: numpy/numpy
File: numpy/_utils/__init__.py (Python)

Code before:
If a utility requires the import of NumPy, it probably belongs
in ``numpy._core``.
"""

import functools
import sys
import warnings
from ._convertions import asunicode, asbytes


def set_module(module):
    """Private decorator for overriding __module__ on a function or class.

    Example usage::

        @set_module('numpy')
        def example():
            pass

        assert example.__module__ == 'numpy'
    """
    def decorator(func):
        if module is not None:
            if isinstance(func, type):
                try:
                    func.__module_file__ = sys.modules.get(func.__module__).__file__
                except (AttributeError, KeyError):
                    pass
                
            func.__module__ = module
        return func
    return decorator


def _rename_parameter(old_names, new_names, dep_version=None):
    """
    Generate decorator for backward-compatible keyword renaming.

    Apply the decorator generated by `_rename_parameter` to functions with a
    renamed parameter to maintain backward-compatibility.

    After decoration, the function behaves as follows:
    If only the new parameter is passed into the function, behave as usual.
    If only the old parameter is passed into the function (as a keyword), raise
    a DeprecationWarning if `dep_version` is provided, and behave as usual
    otherwise.
    If both old and new parameters are passed into the function, raise a
    DeprecationWarning if `dep_version` is provided, and raise the appropriate
    TypeError (function got multiple values for argument).

    Parameters

Review comment (suggestion):
Let's just call this `_module_file`. Giving it a dunder name is confusing because someone might think it's a name for a real dunder attribute that CPython supports. Also Python itself could add a dunder attribute with this name in the future. Another way to think about it is the language itself owns the namespace for symbols with dunder names, but leaves the single leading underscore namespace available for private use by Python libraries.

Code after:
If a utility requires the import of NumPy, it probably belongs
in ``numpy._core``.
"""

import functools
import sys
import warnings
from ._convertions import asunicode, asbytes


def set_module(module):
    """Private decorator for overriding __module__ on a function or class.

    Example usage::

        @set_module('numpy')
        def example():
            pass

        assert example.__module__ == 'numpy'
    """
    def decorator(func):
        if module is not None:
            if isinstance(func, type):
                try:
                    func._module_file = sys.modules.get(func.__module__).__file__
                except (AttributeError, KeyError):
                    pass
                
            func.__module__ = module
        return func
    return decorator


def _rename_parameter(old_names, new_names, dep_version=None):
    """
    Generate decorator for backward-compatible keyword renaming.

    Apply the decorator generated by `_rename_parameter` to functions with a
    renamed parameter to maintain backward-compatibility.

    After decoration, the function behaves as follows:
    If only the new parameter is passed into the function, behave as usual.
    If only the old parameter is passed into the function (as a keyword), raise
    a DeprecationWarning if `dep_version` is provided, and behave as usual
    otherwise.
    If both old and new parameters are passed into the function, raise a
    DeprecationWarning if `dep_version` is provided, and raise the appropriate
    TypeError (function got multiple values for argument).

    Parameters