# Copyright 2020  Ternaris.
# SPDX-License-Identifier: AGPL-3.0-only

import warnings
from dataclasses import dataclass
from typing import Any


@dataclass
class Info:
    module: str
    version: str
    obj: Any
    msg: str = None


def make_getattr(module, dct):
    assert all(x.module == module for x in dct.values())

    def __getattr__(name):
        info = dct.get(name)
        if info is None:
            raise AttributeError(f'module {module} has no attribute {name}')

        msg = (
            f'{module}.{name} will be removed in {info.version}; '
            f'{info.msg or "please let us know if this is an issue for you."}'
        )
        warnings.warn(msg, FutureWarning, stacklevel=2)
        return info.obj

    return __getattr__

@@ -63,16 +63,33 @@
 0-only%0A%0A
+import functools%0A
 import w
@@ -770,8 +770,548 @@
 tattr__%0A
+%0A%0Adef deprecated(version, msg=None, name=None):%0A    %22%22%22Wrap function to trigger deprecated message upon call.%22%22%22%0A    def deco(func):%0A        @functools.wraps(func)%0A        def wrapper(*args, **kw):%0A            _msg = (%0A                f'%7Bfunc.__module__%7D.%7Bname or func.__name__%7D will be removed in %7Bversion%7D; '%0A                f'%7Bmsg or %22please let us know if this is an issue for you.%22%7D'%0A            )%0A            warnings.warn(_msg, FutureWarning, stacklevel=2)%0A            return func(*args, **kw)%0A        return wrapper%0A    return deco%0A

Add decorator to declare function deprecated