devx: add deprecation dumpster (#27887)
* feat: Add deprecation_dumpster.py file * docs: add jovial and jocose docstring for frappe/deprecation_dumpster.py * refactor: fill the dumpster with its own kind * refactor: move to the deprecation dumpster * chore: color coding class * fix: only check import error when import errors
This commit is contained in:
parent
e7776021aa
commit
8cfeb156df
15 changed files with 361 additions and 133 deletions
|
|
@ -326,19 +326,23 @@ def connect(site: str | None = None, db_name: str | None = None, set_admin_as_us
|
||||||
from frappe.database import get_db
|
from frappe.database import get_db
|
||||||
|
|
||||||
if site:
|
if site:
|
||||||
from frappe.utils.deprecations import deprecation_warning
|
from frappe.deprecation_dumpster import deprecation_warning
|
||||||
|
|
||||||
deprecation_warning(
|
deprecation_warning(
|
||||||
|
"unknown",
|
||||||
|
"v17",
|
||||||
"Calling frappe.connect with the site argument is deprecated and will be removed in next major version. "
|
"Calling frappe.connect with the site argument is deprecated and will be removed in next major version. "
|
||||||
"Instead, explicitly invoke frappe.init(site) prior to calling frappe.connect(), if initializing the site is necessary."
|
"Instead, explicitly invoke frappe.init(site) prior to calling frappe.connect(), if initializing the site is necessary.",
|
||||||
)
|
)
|
||||||
init(site)
|
init(site)
|
||||||
if db_name:
|
if db_name:
|
||||||
from frappe.utils.deprecations import deprecation_warning
|
from frappe.deprecation_dumpster import deprecation_warning
|
||||||
|
|
||||||
deprecation_warning(
|
deprecation_warning(
|
||||||
|
"unknown",
|
||||||
|
"v17",
|
||||||
"Calling frappe.connect with the db_name argument is deprecated and will be removed in next major version. "
|
"Calling frappe.connect with the db_name argument is deprecated and will be removed in next major version. "
|
||||||
"Instead, explicitly invoke frappe.init(site) with the right config prior to calling frappe.connect(), if necessary."
|
"Instead, explicitly invoke frappe.init(site) with the right config prior to calling frappe.connect(), if necessary.",
|
||||||
)
|
)
|
||||||
|
|
||||||
assert db_name or local.conf.db_user, "site must be fully initialized, db_user missing"
|
assert db_name or local.conf.db_user, "site must be fully initialized, db_user missing"
|
||||||
|
|
@ -1210,9 +1214,11 @@ def generate_hash(txt: str | None = None, length: int = 56) -> str:
|
||||||
import secrets
|
import secrets
|
||||||
|
|
||||||
if txt:
|
if txt:
|
||||||
from frappe.utils.deprecations import deprecation_warning
|
from frappe.deprecation_dumpster import deprecation_warning
|
||||||
|
|
||||||
deprecation_warning("The `txt` parameter is deprecated and will be removed in a future release.")
|
deprecation_warning(
|
||||||
|
"unknown", "v17", "The `txt` parameter is deprecated and will be removed in a future release."
|
||||||
|
)
|
||||||
|
|
||||||
return secrets.token_hex(math.ceil(length / 2))[:length]
|
return secrets.token_hex(math.ceil(length / 2))[:length]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ from frappe.auth import SAFE_HTTP_METHODS, UNSAFE_HTTP_METHODS, HTTPRequest, val
|
||||||
from frappe.middlewares import StaticDataMiddleware
|
from frappe.middlewares import StaticDataMiddleware
|
||||||
from frappe.utils import CallbackManager, cint, get_site_name
|
from frappe.utils import CallbackManager, cint, get_site_name
|
||||||
from frappe.utils.data import escape_html
|
from frappe.utils.data import escape_html
|
||||||
from frappe.utils.deprecations import deprecation_warning
|
|
||||||
from frappe.utils.error import log_error_snapshot
|
from frappe.utils.error import log_error_snapshot
|
||||||
from frappe.website.serve import get_response
|
from frappe.website.serve import get_response
|
||||||
|
|
||||||
|
|
@ -105,8 +104,12 @@ def application(request: Request):
|
||||||
response = Response()
|
response = Response()
|
||||||
|
|
||||||
elif frappe.form_dict.cmd:
|
elif frappe.form_dict.cmd:
|
||||||
|
from frappe.deprecation_dumpster import deprecation_warning
|
||||||
|
|
||||||
deprecation_warning(
|
deprecation_warning(
|
||||||
f"{frappe.form_dict.cmd}: Sending `cmd` for RPC calls is deprecated, call REST API instead `/api/method/cmd`"
|
"unknown",
|
||||||
|
"v17",
|
||||||
|
f"{frappe.form_dict.cmd}: Sending `cmd` for RPC calls is deprecated, call REST API instead `/api/method/cmd`",
|
||||||
)
|
)
|
||||||
frappe.handler.handle()
|
frappe.handler.handle()
|
||||||
response = frappe.utils.response.build_response("json")
|
response = frappe.utils.response.build_response("json")
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ from frappe.twofactor import (
|
||||||
should_run_2fa,
|
should_run_2fa,
|
||||||
)
|
)
|
||||||
from frappe.utils import cint, date_diff, datetime, get_datetime, today
|
from frappe.utils import cint, date_diff, datetime, get_datetime, today
|
||||||
from frappe.utils.deprecations import deprecation_warning
|
|
||||||
from frappe.utils.password import check_password, get_decrypted_password
|
from frappe.utils.password import check_password, get_decrypted_password
|
||||||
from frappe.website.utils import get_home_page
|
from frappe.website.utils import get_home_page
|
||||||
|
|
||||||
|
|
@ -518,7 +517,9 @@ class LoginAttemptTracker:
|
||||||
:param lock_interval: Locking interval incase of maximum failed attempts
|
:param lock_interval: Locking interval incase of maximum failed attempts
|
||||||
"""
|
"""
|
||||||
if user_name:
|
if user_name:
|
||||||
deprecation_warning("`username` parameter is deprecated, use `key` instead.")
|
from frappe.deprecation_dumpster import deprecation_warning
|
||||||
|
|
||||||
|
deprecation_warning("unknown", "v17", "`username` parameter is deprecated, use `key` instead.")
|
||||||
self.key = key or user_name
|
self.key = key or user_name
|
||||||
self.lock_interval = datetime.timedelta(seconds=lock_interval)
|
self.lock_interval = datetime.timedelta(seconds=lock_interval)
|
||||||
self.max_failed_logins = max_consecutive_login_attempts
|
self.max_failed_logins = max_consecutive_login_attempts
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ from frappe.desk.reportview import validate_args
|
||||||
from frappe.model.db_query import check_parent_permission
|
from frappe.model.db_query import check_parent_permission
|
||||||
from frappe.model.utils import is_virtual_doctype
|
from frappe.model.utils import is_virtual_doctype
|
||||||
from frappe.utils import get_safe_filters
|
from frappe.utils import get_safe_filters
|
||||||
from frappe.utils.deprecations import deprecated
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
@ -328,28 +327,9 @@ def get_password(doctype, name, fieldname):
|
||||||
return frappe.get_doc(doctype, name).get_password(fieldname)
|
return frappe.get_doc(doctype, name).get_password(fieldname)
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
from frappe.deprecation_dumpster import get_js as _get_js
|
||||||
@deprecated
|
|
||||||
def get_js(items):
|
|
||||||
"""Load JS code files. Will also append translations
|
|
||||||
and extend `frappe._messages`
|
|
||||||
|
|
||||||
:param items: JSON list of paths of the js files to be loaded."""
|
get_js = frappe.whitelist()(_get_js)
|
||||||
items = json.loads(items)
|
|
||||||
out = []
|
|
||||||
for src in items:
|
|
||||||
src = src.strip("/").split("/")
|
|
||||||
|
|
||||||
if ".." in src or src[0] != "assets":
|
|
||||||
frappe.throw(_("Invalid file path: {0}").format("/".join(src)))
|
|
||||||
|
|
||||||
contentpath = os.path.join(frappe.local.sites_path, *src)
|
|
||||||
with open(contentpath) as srcfile:
|
|
||||||
code = frappe.utils.cstr(srcfile.read())
|
|
||||||
|
|
||||||
out.append(code)
|
|
||||||
|
|
||||||
return out
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist(allow_guest=True)
|
@frappe.whitelist(allow_guest=True)
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ from frappe.utils import (
|
||||||
today,
|
today,
|
||||||
)
|
)
|
||||||
from frappe.utils.data import sha256_hash
|
from frappe.utils.data import sha256_hash
|
||||||
from frappe.utils.deprecations import deprecated, deprecation_warning
|
|
||||||
from frappe.utils.password import check_password, get_password_reset_limit
|
from frappe.utils.password import check_password, get_password_reset_limit
|
||||||
from frappe.utils.password import update_password as _update_password
|
from frappe.utils.password import update_password as _update_password
|
||||||
from frappe.utils.user import get_system_managers
|
from frappe.utils.user import get_system_managers
|
||||||
|
|
@ -227,9 +226,7 @@ class User(Document):
|
||||||
self.roles = [r for r in self.roles if r.role in new_roles]
|
self.roles = [r for r in self.roles if r.role in new_roles]
|
||||||
self.append_roles(*new_roles)
|
self.append_roles(*new_roles)
|
||||||
|
|
||||||
@deprecated
|
from frappe.deprecation_dumpster import validate_roles
|
||||||
def validate_roles(self):
|
|
||||||
self.populate_role_profile_roles()
|
|
||||||
|
|
||||||
def move_role_profile_name_to_role_profiles(self):
|
def move_role_profile_name_to_role_profiles(self):
|
||||||
"""This handles old role_profile_name field if programatically set.
|
"""This handles old role_profile_name field if programatically set.
|
||||||
|
|
@ -243,8 +240,12 @@ class User(Document):
|
||||||
self.role_profile_name = None
|
self.role_profile_name = None
|
||||||
return
|
return
|
||||||
|
|
||||||
|
from frappe.deprecation_dumpster import deprecation_warning
|
||||||
|
|
||||||
deprecation_warning(
|
deprecation_warning(
|
||||||
"The field `role_profile_name` is deprecated and will be removed in v16, use `role_profiles` child table instead."
|
"unknown",
|
||||||
|
"v16",
|
||||||
|
"The field `role_profile_name` is deprecated and will be removed in v16, use `role_profiles` child table instead.",
|
||||||
)
|
)
|
||||||
self.append("role_profiles", {"role_profile": self.role_profile_name})
|
self.append("role_profiles", {"role_profile": self.role_profile_name})
|
||||||
self.role_profile_name = None
|
self.role_profile_name = None
|
||||||
|
|
@ -908,12 +909,15 @@ def update_password(
|
||||||
|
|
||||||
@frappe.whitelist(allow_guest=True)
|
@frappe.whitelist(allow_guest=True)
|
||||||
def test_password_strength(new_password: str, key=None, old_password=None, user_data: tuple | None = None):
|
def test_password_strength(new_password: str, key=None, old_password=None, user_data: tuple | None = None):
|
||||||
from frappe.utils.deprecations import deprecation_warning
|
|
||||||
from frappe.utils.password_strength import test_password_strength as _test_password_strength
|
from frappe.utils.password_strength import test_password_strength as _test_password_strength
|
||||||
|
|
||||||
if key is not None or old_password is not None:
|
if key is not None or old_password is not None:
|
||||||
|
from frappe.deprecation_dumpster import deprecation_warning
|
||||||
|
|
||||||
deprecation_warning(
|
deprecation_warning(
|
||||||
"Arguments `key` and `old_password` are deprecated in function `test_password_strength`."
|
"unknown",
|
||||||
|
"v17",
|
||||||
|
"Arguments `key` and `old_password` are deprecated in function `test_password_strength`.",
|
||||||
)
|
)
|
||||||
|
|
||||||
enable_password_policy = frappe.get_system_settings("enable_password_policy")
|
enable_password_policy = frappe.get_system_settings("enable_password_policy")
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ from frappe.monitor import get_trace_id
|
||||||
from frappe.query_builder.functions import Count
|
from frappe.query_builder.functions import Count
|
||||||
from frappe.utils import CallbackManager, cint, get_datetime, get_table_name, getdate, now, sbool
|
from frappe.utils import CallbackManager, cint, get_datetime, get_table_name, getdate, now, sbool
|
||||||
from frappe.utils import cast as cast_fieldtype
|
from frappe.utils import cast as cast_fieldtype
|
||||||
from frappe.utils.deprecations import deprecated, deprecation_warning
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from psycopg2 import connection as PostgresConnection
|
from psycopg2 import connection as PostgresConnection
|
||||||
|
|
@ -962,8 +961,12 @@ class Database:
|
||||||
if dn is None or dt == dn:
|
if dn is None or dt == dn:
|
||||||
if not is_single_doctype(dt):
|
if not is_single_doctype(dt):
|
||||||
return
|
return
|
||||||
|
from frappe.deprecation_dumpster import deprecation_warning
|
||||||
|
|
||||||
deprecation_warning(
|
deprecation_warning(
|
||||||
"Calling db.set_value on single doctype is deprecated. This behaviour will be removed in future. Use db.set_single_value instead."
|
"unknown",
|
||||||
|
"v17",
|
||||||
|
"Calling db.set_value on single doctype is deprecated. This behaviour will be removed in future. Use db.set_single_value instead.",
|
||||||
)
|
)
|
||||||
self.set_single_value(
|
self.set_single_value(
|
||||||
doctype=dt,
|
doctype=dt,
|
||||||
|
|
@ -1243,10 +1246,9 @@ class Database:
|
||||||
# implemented in specific class
|
# implemented in specific class
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@staticmethod
|
from frappe.deprecation_dumpster import is_column_missing as _is_column_missing
|
||||||
@deprecated
|
|
||||||
def is_column_missing(e):
|
is_column_missing = staticmethod(_is_column_missing)
|
||||||
return frappe.db.is_missing_column(e)
|
|
||||||
|
|
||||||
def get_descendants(self, doctype, name):
|
def get_descendants(self, doctype, name):
|
||||||
"""Return descendants of the group node in tree"""
|
"""Return descendants of the group node in tree"""
|
||||||
|
|
|
||||||
290
frappe/deprecation_dumpster.py
Normal file
290
frappe/deprecation_dumpster.py
Normal file
|
|
@ -0,0 +1,290 @@
|
||||||
|
"""
|
||||||
|
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 Frappe framework. 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 Frappe 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
|
||||||
|
|
||||||
|
|
||||||
|
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=DeprecationWarning, 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)
|
||||||
|
"""
|
||||||
|
|
||||||
|
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("frappe/deprecation_dumpster.py\n", Color.CYAN)
|
||||||
|
+ colorize("Move the entire function there and import it back via adding\n ", Color.YELLOW)
|
||||||
|
+ colorize(f"from frappe.deprecation_dumpster import {func.__name__}\n", Color.CYAN)
|
||||||
|
+ colorize("to file\n ", Color.YELLOW)
|
||||||
|
+ colorize(caller_filepath, Color.CYAN)
|
||||||
|
)
|
||||||
|
|
||||||
|
return functools.wraps(func)(
|
||||||
|
_deprecated(
|
||||||
|
colorize(f"`{original}`", Color.CYAN)
|
||||||
|
+ colorize(
|
||||||
|
f" was moved (DATE: {marked}) to frappe/deprecation_dumpster.py"
|
||||||
|
f" for removal (from {graduation} onwards); note:\n ",
|
||||||
|
Color.RED,
|
||||||
|
)
|
||||||
|
+ colorize(f"{msg}\n", Color.YELLOW),
|
||||||
|
stacklevel=stacklevel,
|
||||||
|
)
|
||||||
|
)(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)
|
||||||
|
"""
|
||||||
|
|
||||||
|
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=DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
### Party starts here
|
||||||
|
def _old_deprecated(func):
|
||||||
|
return deprecated(
|
||||||
|
"frappe.deprecations.deprecated",
|
||||||
|
"2024-09-13",
|
||||||
|
"v17",
|
||||||
|
"Make use of the frappe/deprecation_dumpster.py file, instead. 🎉🗑️",
|
||||||
|
)(_deprecated("")(func))
|
||||||
|
|
||||||
|
|
||||||
|
def _old_deprecation_warning(msg):
|
||||||
|
@deprecated(
|
||||||
|
"frappe.deprecations.deprecation_warning",
|
||||||
|
"2024-09-13",
|
||||||
|
"v17",
|
||||||
|
"Use frappe.deprecation_dumpster.deprecation_warning, instead. 🎉🗑️",
|
||||||
|
)
|
||||||
|
def deprecation_warning(message, category=DeprecationWarning, stacklevel=1):
|
||||||
|
warnings.warn(message=message, category=category, stacklevel=stacklevel + 2)
|
||||||
|
|
||||||
|
return deprecation_warning(msg)
|
||||||
|
|
||||||
|
|
||||||
|
@deprecated("frappe.utils.make_esc", "unknown", "v17", "Not used anymore.")
|
||||||
|
def make_esc(esc_chars):
|
||||||
|
"""
|
||||||
|
Function generator for Escaping special characters
|
||||||
|
"""
|
||||||
|
return lambda s: "".join("\\" + c if c in esc_chars else c for c in s)
|
||||||
|
|
||||||
|
|
||||||
|
@deprecated(
|
||||||
|
"frappe.db.is_column_missing",
|
||||||
|
"unknown",
|
||||||
|
"v17",
|
||||||
|
"Renamed to frappe.db.is_missing_column.",
|
||||||
|
)
|
||||||
|
def is_column_missing(e):
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
return frappe.db.is_missing_column(e)
|
||||||
|
|
||||||
|
|
||||||
|
@deprecated(
|
||||||
|
"frappe.desk.doctype.bulk_update.bulk_update",
|
||||||
|
"unknown",
|
||||||
|
"v17",
|
||||||
|
"Unknown.",
|
||||||
|
)
|
||||||
|
def show_progress(docnames, message, i, description):
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
n = len(docnames)
|
||||||
|
frappe.publish_progress(float(i) * 100 / n, title=message, description=description)
|
||||||
|
|
||||||
|
|
||||||
|
@deprecated(
|
||||||
|
"frappe.client.get_js",
|
||||||
|
"unknown",
|
||||||
|
"v17",
|
||||||
|
"Unknown.",
|
||||||
|
)
|
||||||
|
def get_js(items):
|
||||||
|
"""Load JS code files. Will also append translations
|
||||||
|
and extend `frappe._messages`
|
||||||
|
|
||||||
|
:param items: JSON list of paths of the js files to be loaded."""
|
||||||
|
import json
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
items = json.loads(items)
|
||||||
|
out = []
|
||||||
|
for src in items:
|
||||||
|
src = src.strip("/").split("/")
|
||||||
|
|
||||||
|
if ".." in src or src[0] != "assets":
|
||||||
|
frappe.throw(_("Invalid file path: {0}").format("/".join(src)))
|
||||||
|
|
||||||
|
contentpath = os.path.join(frappe.local.sites_path, *src)
|
||||||
|
with open(contentpath) as srcfile:
|
||||||
|
code = frappe.utils.cstr(srcfile.read())
|
||||||
|
|
||||||
|
out.append(code)
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
@deprecated(
|
||||||
|
"frappe.utils.print_format.read_multi_pdf",
|
||||||
|
"unknown",
|
||||||
|
"v17",
|
||||||
|
"Unknown.",
|
||||||
|
)
|
||||||
|
def read_multi_pdf(output) -> bytes:
|
||||||
|
from io import BytesIO
|
||||||
|
|
||||||
|
with BytesIO() as merged_pdf:
|
||||||
|
output.write(merged_pdf)
|
||||||
|
return merged_pdf.getvalue()
|
||||||
|
|
||||||
|
|
||||||
|
@deprecated("frappe.gzip_compress", "unknown", "v17", "Use py3 methods directly (this was compat for py2).")
|
||||||
|
def gzip_compress(data, compresslevel=9):
|
||||||
|
"""Compress data in one shot and return the compressed string.
|
||||||
|
Optional argument is the compression level, in range of 0-9.
|
||||||
|
"""
|
||||||
|
import io
|
||||||
|
from gzip import GzipFile
|
||||||
|
|
||||||
|
buf = io.BytesIO()
|
||||||
|
with GzipFile(fileobj=buf, mode="wb", compresslevel=compresslevel) as f:
|
||||||
|
f.write(data)
|
||||||
|
return buf.getvalue()
|
||||||
|
|
||||||
|
|
||||||
|
@deprecated("frappe.gzip_decompress", "unknown", "v17", "Use py3 methods directly (this was compat for py2).")
|
||||||
|
def gzip_decompress(data):
|
||||||
|
"""Decompress a gzip compressed string in one shot.
|
||||||
|
Return the decompressed string.
|
||||||
|
"""
|
||||||
|
import io
|
||||||
|
from gzip import GzipFile
|
||||||
|
|
||||||
|
with GzipFile(fileobj=io.BytesIO(data)) as f:
|
||||||
|
return f.read()
|
||||||
|
|
||||||
|
|
||||||
|
@deprecated(
|
||||||
|
"frappe.email.doctype.email_queue.email_queue.send_mail",
|
||||||
|
"unknown",
|
||||||
|
"v17",
|
||||||
|
"Unknown.",
|
||||||
|
)
|
||||||
|
def send_mail(email_queue_name, smtp_server_instance=None):
|
||||||
|
"""This is equivalent to EmailQueue.send.
|
||||||
|
|
||||||
|
This provides a way to make sending mail as a background job.
|
||||||
|
"""
|
||||||
|
from frappe.email.doctype.email_queue.email_queue import EmailQueue
|
||||||
|
|
||||||
|
record = EmailQueue.find(email_queue_name)
|
||||||
|
record.send(smtp_server_instance=smtp_server_instance)
|
||||||
|
|
||||||
|
|
||||||
|
@deprecated(
|
||||||
|
"frappe.geo.country_info.get_translated_dict",
|
||||||
|
"unknown",
|
||||||
|
"v17",
|
||||||
|
"Use frappe.geo.country_info.get_translated_countries, instead.",
|
||||||
|
)
|
||||||
|
def get_translated_dict():
|
||||||
|
from frappe.geo.country_info import get_translated_countries
|
||||||
|
|
||||||
|
return get_translated_countries()
|
||||||
|
|
||||||
|
|
||||||
|
@deprecated(
|
||||||
|
"User.validate_roles",
|
||||||
|
"unknown",
|
||||||
|
"v17",
|
||||||
|
"Use User.populate_role_profile_roles, instead.",
|
||||||
|
)
|
||||||
|
def validate_roles(self):
|
||||||
|
self.populate_role_profile_roles()
|
||||||
|
|
@ -6,7 +6,6 @@ from frappe import _
|
||||||
from frappe.core.doctype.submission_queue.submission_queue import queue_submission
|
from frappe.core.doctype.submission_queue.submission_queue import queue_submission
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.utils import cint
|
from frappe.utils import cint
|
||||||
from frappe.utils.deprecations import deprecated
|
|
||||||
from frappe.utils.scheduler import is_scheduler_inactive
|
from frappe.utils.scheduler import is_scheduler_inactive
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -111,7 +110,4 @@ def _bulk_action(doctype, docnames, action, data, task_id=None):
|
||||||
return failed
|
return failed
|
||||||
|
|
||||||
|
|
||||||
@deprecated
|
from frappe.deprecation_dumpster import show_progress
|
||||||
def show_progress(docnames, message, i, description):
|
|
||||||
n = len(docnames)
|
|
||||||
frappe.publish_progress(float(i) * 100 / n, title=message, description=description)
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ from frappe.utils import (
|
||||||
sbool,
|
sbool,
|
||||||
split_emails,
|
split_emails,
|
||||||
)
|
)
|
||||||
from frappe.utils.deprecations import deprecated
|
|
||||||
from frappe.utils.verified_command import get_signed_params
|
from frappe.utils.verified_command import get_signed_params
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -223,15 +222,9 @@ class EmailQueue(Document):
|
||||||
).run()
|
).run()
|
||||||
|
|
||||||
|
|
||||||
@task(queue="short")
|
from frappe.deprecation_dumpster import send_mail as _send_mail
|
||||||
@deprecated
|
|
||||||
def send_mail(email_queue_name, smtp_server_instance: SMTPServer = None):
|
|
||||||
"""This is equivalent to EmailQueue.send.
|
|
||||||
|
|
||||||
This provides a way to make sending mail as a background job.
|
send_mail = task(queue="short")(_send_mail)
|
||||||
"""
|
|
||||||
record = EmailQueue.find(email_queue_name)
|
|
||||||
record.send(smtp_server_instance=smtp_server_instance)
|
|
||||||
|
|
||||||
|
|
||||||
class SendMailContext:
|
class SendMailContext:
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import os
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.utils.deprecations import deprecated
|
|
||||||
from frappe.utils.momentjs import get_all_timezones
|
from frappe.utils.momentjs import get_all_timezones
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -39,9 +38,7 @@ def _get_country_timezone_info():
|
||||||
return {"country_info": get_all(), "all_timezones": get_all_timezones()}
|
return {"country_info": get_all(), "all_timezones": get_all_timezones()}
|
||||||
|
|
||||||
|
|
||||||
@deprecated
|
from frappe.deprecation_dumpster import get_translated_dict
|
||||||
def get_translated_dict():
|
|
||||||
return get_translated_countries()
|
|
||||||
|
|
||||||
|
|
||||||
def get_translated_countries():
|
def get_translated_countries():
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ from frappe.core.doctype.server_script.server_script_utils import get_server_scr
|
||||||
from frappe.monitor import add_data_to_monitor
|
from frappe.monitor import add_data_to_monitor
|
||||||
from frappe.utils import cint
|
from frappe.utils import cint
|
||||||
from frappe.utils.csvutils import build_csv_response
|
from frappe.utils.csvutils import build_csv_response
|
||||||
from frappe.utils.deprecations import deprecated, deprecation_warning
|
from frappe.utils.deprecations import deprecated
|
||||||
from frappe.utils.image import optimize_image
|
from frappe.utils.image import optimize_image
|
||||||
from frappe.utils.response import build_response
|
from frappe.utils.response import build_response
|
||||||
|
|
||||||
|
|
@ -241,8 +241,12 @@ def get_attr(cmd):
|
||||||
if "." in cmd:
|
if "." in cmd:
|
||||||
method = frappe.get_attr(cmd)
|
method = frappe.get_attr(cmd)
|
||||||
else:
|
else:
|
||||||
|
from frappe.deprecation_dumpster import deprecation_warning
|
||||||
|
|
||||||
deprecation_warning(
|
deprecation_warning(
|
||||||
f"Calling shorthand for {cmd} is deprecated, please specify full path in RPC call."
|
"unknown",
|
||||||
|
"v17",
|
||||||
|
f"Calling shorthand for {cmd} is deprecated, please specify full path in RPC call.",
|
||||||
)
|
)
|
||||||
method = globals()[cmd]
|
method = globals()[cmd]
|
||||||
return method
|
return method
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,10 @@ from typing import TypedDict
|
||||||
|
|
||||||
from werkzeug.test import Client
|
from werkzeug.test import Client
|
||||||
|
|
||||||
|
from frappe.deprecation_dumpster import gzip_compress, gzip_decompress, make_esc
|
||||||
|
|
||||||
# utility functions like cint, int, flt, etc.
|
# utility functions like cint, int, flt, etc.
|
||||||
from frappe.utils.data import *
|
from frappe.utils.data import *
|
||||||
from frappe.utils.deprecations import deprecated
|
|
||||||
from frappe.utils.html_utils import sanitize_html
|
from frappe.utils.html_utils import sanitize_html
|
||||||
|
|
||||||
EMAIL_NAME_PATTERN = re.compile(r"[^A-Za-z0-9\u00C0-\u024F\/\_\' ]+")
|
EMAIL_NAME_PATTERN = re.compile(r"[^A-Za-z0-9\u00C0-\u024F\/\_\' ]+")
|
||||||
|
|
@ -423,14 +424,6 @@ def get_file_timestamp(fn):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
# to be deprecated
|
|
||||||
def make_esc(esc_chars):
|
|
||||||
"""
|
|
||||||
Function generator for Escaping special characters
|
|
||||||
"""
|
|
||||||
return lambda s: "".join("\\" + c if c in esc_chars else c for c in s)
|
|
||||||
|
|
||||||
|
|
||||||
# esc / unescape characters -- used for command line
|
# esc / unescape characters -- used for command line
|
||||||
def esc(s, esc_chars):
|
def esc(s, esc_chars):
|
||||||
"""
|
"""
|
||||||
|
|
@ -888,34 +881,6 @@ def call(fn, *args, **kwargs):
|
||||||
return json.loads(frappe.as_json(frappe.call(fn, *args, **kwargs)))
|
return json.loads(frappe.as_json(frappe.call(fn, *args, **kwargs)))
|
||||||
|
|
||||||
|
|
||||||
# Following methods are aken as-is from Python 3 codebase
|
|
||||||
# since gzip.compress and gzip.decompress are not available in Python 2.7
|
|
||||||
|
|
||||||
|
|
||||||
@deprecated
|
|
||||||
def gzip_compress(data, compresslevel=9):
|
|
||||||
"""Compress data in one shot and return the compressed string.
|
|
||||||
Optional argument is the compression level, in range of 0-9.
|
|
||||||
"""
|
|
||||||
from gzip import GzipFile
|
|
||||||
|
|
||||||
buf = io.BytesIO()
|
|
||||||
with GzipFile(fileobj=buf, mode="wb", compresslevel=compresslevel) as f:
|
|
||||||
f.write(data)
|
|
||||||
return buf.getvalue()
|
|
||||||
|
|
||||||
|
|
||||||
@deprecated
|
|
||||||
def gzip_decompress(data):
|
|
||||||
"""Decompress a gzip compressed string in one shot.
|
|
||||||
Return the decompressed string.
|
|
||||||
"""
|
|
||||||
from gzip import GzipFile
|
|
||||||
|
|
||||||
with GzipFile(fileobj=io.BytesIO(data)) as f:
|
|
||||||
return f.read()
|
|
||||||
|
|
||||||
|
|
||||||
def get_safe_filters(filters):
|
def get_safe_filters(filters):
|
||||||
try:
|
try:
|
||||||
filters = json.loads(filters)
|
filters = json.loads(filters)
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,6 @@ import frappe.monitor
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import CallbackManager, cint, get_bench_id
|
from frappe.utils import CallbackManager, cint, get_bench_id
|
||||||
from frappe.utils.commands import log
|
from frappe.utils.commands import log
|
||||||
from frappe.utils.deprecations import deprecation_warning
|
|
||||||
from frappe.utils.redis_queue import RedisQueue
|
from frappe.utils.redis_queue import RedisQueue
|
||||||
|
|
||||||
# TTL to keep RQ job logs in redis for.
|
# TTL to keep RQ job logs in redis for.
|
||||||
|
|
@ -119,11 +118,19 @@ def enqueue(
|
||||||
job_id = create_job_id(job_id)
|
job_id = create_job_id(job_id)
|
||||||
|
|
||||||
if job_name:
|
if job_name:
|
||||||
deprecation_warning("Using enqueue with `job_name` is deprecated, use `job_id` instead.")
|
from frappe.deprecation_dumpster import deprecation_warning
|
||||||
|
|
||||||
|
deprecation_warning(
|
||||||
|
"unknown", "v17", "Using enqueue with `job_name` is deprecated, use `job_id` instead."
|
||||||
|
)
|
||||||
|
|
||||||
if not is_async and not frappe.flags.in_test:
|
if not is_async and not frappe.flags.in_test:
|
||||||
|
from frappe.deprecation_dumpster import deprecation_warning
|
||||||
|
|
||||||
deprecation_warning(
|
deprecation_warning(
|
||||||
"Using enqueue with is_async=False outside of tests is not recommended, use now=True instead."
|
"unknown",
|
||||||
|
"v17",
|
||||||
|
"Using enqueue with is_async=False outside of tests is not recommended, use now=True instead.",
|
||||||
)
|
)
|
||||||
|
|
||||||
call_directly = now or (not is_async and not frappe.flags.in_test)
|
call_directly = now or (not is_async and not frappe.flags.in_test)
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,12 @@
|
||||||
""" Utils for deprecating functionality in Framework.
|
"""Utils for deprecating functionality in Framework.
|
||||||
|
|
||||||
WARNING: This file is internal, instead of depending just copy the code or use deprecation
|
WARNING: This file is internal, instead of depending just copy the code or use deprecation
|
||||||
libraries.
|
libraries.
|
||||||
"""
|
"""
|
||||||
import functools
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
|
from frappe.deprecation_dumpster import (
|
||||||
def deprecated(func):
|
_old_deprecated as deprecated,
|
||||||
"""Decorator to wrap a function/method as deprecated."""
|
)
|
||||||
|
from frappe.deprecation_dumpster import (
|
||||||
@functools.wraps(func)
|
_old_deprecation_warning as deprecation_warning,
|
||||||
def wrapper(*args, **kwargs):
|
)
|
||||||
deprecation_warning(
|
|
||||||
f"{func.__name__} is deprecated and will be removed in next major version.",
|
|
||||||
stacklevel=1,
|
|
||||||
)
|
|
||||||
return func(*args, **kwargs)
|
|
||||||
|
|
||||||
return wrapper
|
|
||||||
|
|
||||||
|
|
||||||
def deprecation_warning(message, category=DeprecationWarning, stacklevel=1):
|
|
||||||
"""like warnings.warn but with auto incremented sane stacklevel."""
|
|
||||||
|
|
||||||
warnings.warn(message=message, category=category, stacklevel=stacklevel + 2)
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.core.doctype.access_log.access_log import make_access_log
|
from frappe.core.doctype.access_log.access_log import make_access_log
|
||||||
from frappe.translate import print_language
|
from frappe.translate import print_language
|
||||||
from frappe.utils.deprecations import deprecated
|
|
||||||
from frappe.utils.pdf import get_pdf
|
from frappe.utils.pdf import get_pdf
|
||||||
|
|
||||||
no_cache = 1
|
no_cache = 1
|
||||||
|
|
@ -214,11 +213,7 @@ def _download_multi_pdf(
|
||||||
frappe.local.response.type = "pdf"
|
frappe.local.response.type = "pdf"
|
||||||
|
|
||||||
|
|
||||||
@deprecated
|
from frappe.deprecation_dumpster import read_multi_pdf
|
||||||
def read_multi_pdf(output: PdfWriter) -> bytes:
|
|
||||||
with BytesIO() as merged_pdf:
|
|
||||||
output.write(merged_pdf)
|
|
||||||
return merged_pdf.getvalue()
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist(allow_guest=True)
|
@frappe.whitelist(allow_guest=True)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue