feat: add deprecation dumpster

This commit is contained in:
David
2024-11-07 19:47:51 +01:00
parent 284fffe334
commit 1313d81c5f

View File

@@ -0,0 +1,127 @@
"""
Welcome to the Deprecation Dumpster: Where Old Code Goes to Party! 🎉🗑️
This file is the final resting place (or should we say, "retirement home"?) for all the deprecated functions and methods of the ERPNext app. It's like a code nursing home, but with more monkey-patching and less bingo.
Each function or method that checks in here comes with its own personalized decorator, complete with:
1. The date it was marked for deprecation (its "over the hill" birthday)
2. The ERPNext version in which it will be removed (its "graduation" to the great codebase in the sky)
3. A user-facing note on alternative solutions (its "parting wisdom")
Warning: The global namespace herein is more patched up than a sailor's favorite pair of jeans. Proceed with caution and a sense of humor!
Remember, deprecated doesn't mean useless - it just means these functions are enjoying their golden years before their final bow. Treat them with respect, and maybe bring them some virtual prune juice.
Enjoy your stay in the Deprecation Dumpster, where every function gets a second chance to shine (or at least, to not break everything).
"""
import inspect
import os
import sys
import warnings
def colorize(text, color_code):
if sys.stdout.isatty():
return f"\033[{color_code}m{text}\033[0m"
return text
class Color:
RED = 91
YELLOW = 93
CYAN = 96
class ERPNextDeprecationWarning(Warning):
...
try:
# since python 3.13, PEP 702
from warnings import deprecated as _deprecated
except ImportError:
import functools
import warnings
from collections.abc import Callable
from typing import Optional, TypeVar, Union, overload
T = TypeVar("T", bound=Callable)
def _deprecated(message: str, category=ERPNextDeprecationWarning, stacklevel=1) -> Callable[[T], T]:
def decorator(func: T) -> T:
@functools.wraps(func)
def wrapper(*args, **kwargs):
if message:
warning_msg = f"{func.__name__} is deprecated.\n{message}"
else:
warning_msg = f"{func.__name__} is deprecated."
warnings.warn(warning_msg, category=category, stacklevel=stacklevel + 1)
return func(*args, **kwargs)
return wrapper
wrapper.__deprecated__ = True # hint for the type checker
return decorator
def deprecated(original: str, marked: str, graduation: str, msg: str, stacklevel: int = 1):
"""Decorator to wrap a function/method as deprecated.
Arguments:
- original: frappe.utils.make_esc (fully qualified)
- marked: 2024-09-13 (the date it has been marked)
- graduation: v17 (generally: current version + 2)
- msg: additional instructions
"""
def decorator(func):
# Get the filename of the caller
frame = inspect.currentframe()
caller_filepath = frame.f_back.f_code.co_filename
if os.path.basename(caller_filepath) != "deprecation_dumpster.py":
raise RuntimeError(
colorize("The deprecated function ", Color.YELLOW)
+ colorize(func.__name__, Color.CYAN)
+ colorize(" can only be called from ", Color.YELLOW)
+ colorize("erpnext/deprecation_dumpster.py\n", Color.CYAN)
+ colorize("Move the entire function there and import it back via adding\n ", Color.YELLOW)
+ colorize(f"from erpnext.deprecation_dumpster import {func.__name__}\n", Color.CYAN)
+ colorize("to file\n ", Color.YELLOW)
+ colorize(caller_filepath, Color.CYAN)
)
func.__name__ = original
wrapper = _deprecated(
colorize(f"It was marked on {marked} for removal from {graduation} with note: ", Color.RED)
+ colorize(f"{msg}", Color.YELLOW),
stacklevel=stacklevel,
)
return functools.update_wrapper(wrapper, func)(func)
return decorator
def deprecation_warning(marked: str, graduation: str, msg: str):
"""Warn in-place from a deprecated code path, for objects use `@deprecated` decorator from the deprectation_dumpster"
Arguments:
- marked: 2024-09-13 (the date it has been marked)
- graduation: v17 (generally: current version + 2)
- msg: additional instructions
"""
warnings.warn(
colorize(
f"This codepath was marked (DATE: {marked}) deprecated"
f" for removal (from {graduation} onwards); note:\n ",
Color.RED,
)
+ colorize(f"{msg}\n", Color.YELLOW),
category=ERPNextDeprecationWarning,
stacklevel=2,
)
### Party starts here