How to warn about class (name) deprecation

后端 未结 7 1464
滥情空心
滥情空心 2020-12-13 12:21

I have renamed a python class that is part of a library. I am willing to leave a possibility to use its previous name for some time but would like to warn user that it\'s de

相关标签:
7条回答
  • 2020-12-13 13:07

    Since Python 3.7, you can provide a customization of module attribute access using __getattr__ (and __dir__). Everything is explained in PEP 562. In the bellow example, I implemented __getattr__ and __dir__ in order to deprecate the “OldClsName” in favor of “NewClsNam”:

    # your_lib.py
    
    import warnings
    
    __all__ = ["NewClsName"]
    
    DEPRECATED_NAMES = [('OldClsName', 'NewClsName')]
    
    
    class NewClsName:
        @classmethod
        def create_variant1(cls):
            return cls()
    
    
    def __getattr__(name):
        for old_name, new_name in DEPRECATED_NAMES:
            if name == old_name:
                warnings.warn(f"The '{old_name}' class or function is renamed '{new_name}'",
                              DeprecationWarning,
                              stacklevel=2)
                return globals()[new_name]
        raise AttributeError(f"module {__name__} has no attribute {name}")
    
    
    def __dir__():
        return sorted(__all__ + [names[0] for names in DEPRECATED_NAMES])
    

    In the __getattr__ function, if a deprecated class or function name is found, a warning message is emitted, showing the source file and line number of the caller (with stacklevel=2).

    In the user code, we could have:

    # your_lib_usage.py
    from your_lib import NewClsName
    from your_lib import OldClsName
    
    
    def use_new_class():
        obj = NewClsName.create_variant1()
        print(obj.__class__.__name__ + " is created in use_new_class")
    
    
    def use_old_class():
        obj = OldClsName.create_variant1()
        print(obj.__class__.__name__ + " is created in use_old_class")
    
    
    if __name__ == '__main__':
        use_new_class()
        use_old_class()
    

    When the user run his script your_lib_usage.py, it will get something like this:

    NewClsName is created in use_new_class
    NewClsName is created in use_old_class
    /path/to/your_lib_usage.py:3: DeprecationWarning: The 'OldClsName' class or function is renamed 'NewClsName'
      from your_lib import OldClsName
    

    Note: the stack trace is usually written in STDERR.

    To see the error warnings, you may need to add a “-W” flag in the Python command line, for instance:

    python -W always your_lib_usage.py
    
    0 讨论(0)
提交回复
热议问题