mirror of
https://github.com/frappe/erpnext.git
synced 2026-04-29 03:28:32 +00:00
feat: add deprecation dumpster
This commit is contained in:
127
erpnext/deprecation_dumpster.py
Normal file
127
erpnext/deprecation_dumpster.py
Normal 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
|
||||
Reference in New Issue
Block a user