fix: force type check in whitelisted methods 2 (#37086)

* fix(diff): add type hints to whitelisted methods

* fix(global_search): add type hints to whitelisted methods

* fix(custom_html_block): add type hints to whitelisted methods

* fix(deleted_document): add type hints to whitelisted methods

* fix(log_settings): add type hints to whitelisted methods

* fix(role): add type hints to whitelisted methods

* fix(user_type): add type hints to whitelisted methods

* fix(rq_job): add type hints to whitelisted methods

* fix(link_preview): add type hints to whitelisted methods

* fix(email_account): add type hints to whitelisted methods

* fix(web_form): add type hints to whitelisted methods

* fix(web_page_view): add type hints to whitelisted methods

* fix(csvutils): add type hints to whitelisted methods

* fix(file_manager): add type hints to whitelisted methods

* fix(email_body): add type hints to whitelisted methods

* fix(email_queue): add type hints to whitelisted methods

* fix(email_template): add type hints to whitelisted methods

* fix(notification): add type hints to whitelisted methods

* fix(email_group): add type hints to whitelisted methods

* fix(inbox): add type hints to whitelisted methods

* fix(recorder): add type hints to whitelisted methods

* fix(sms_settings): add type hints to whitelisted methods

* fix: tighten type hints

* fix(data_import): add type hints to whitelisted methods

* fix(user_permission): add type hints to whitelisted methods

* fix(gantt): add type hints to whitelisted methods

* fix(like): add type hints to whitelisted methods

* fix(search): add type hints to whitelisted methods

* fix(onboarding_step): add type hints to whitelisted methods

* fix(system_console): add type hints to whitelisted methods

* fix(workspace_sidebar): add type hints to whitelisted methods

* fix(todo): add type hints to whitelisted methods

* fix: correct type hints

* fix(print_format): add type hints to whitelisted methods

* fix(client): add type hints to whitelisted methods
This commit is contained in:
Aarol D'Souza 2026-02-19 14:58:16 +05:30 committed by GitHub
parent aee0295275
commit 08793c57f7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 121 additions and 68 deletions

View file

@ -2,6 +2,7 @@
# License: MIT. See LICENSE
import os
from typing import Any
from rq.command import send_stop_job_command
from rq.exceptions import InvalidJobOperation
@ -102,7 +103,7 @@ class DataImport(Document):
self.payload_count = len(payloads)
@frappe.whitelist()
def get_preview_from_template(self, import_file=None, google_sheets_url=None):
def get_preview_from_template(self, import_file: str | None = None, google_sheets_url: str | None = None):
if import_file:
self.import_file = import_file
self.set_delimiters_flag()
@ -203,7 +204,13 @@ def start_import(data_import):
@frappe.whitelist()
def download_template(doctype, export_fields=None, export_records=None, export_filters=None, file_type="CSV"):
def download_template(
doctype: str,
export_fields: str | dict[str, list[str]] | None = None,
export_records: str | None = None,
export_filters: str | dict[str, Any] | list[list[Any]] | None = None,
file_type: str = "CSV",
):
"""
Download template from Exporter
:param doctype: Document Type

View file

@ -38,7 +38,7 @@ class DeletedDocument(Document):
@frappe.whitelist()
def restore(name, alert=True):
def restore(name: str | int, alert: bool = True):
deleted = frappe.get_doc("Deleted Document", name)
if deleted.restored:
@ -69,7 +69,7 @@ def restore(name, alert=True):
@frappe.whitelist()
def bulk_restore(docnames):
def bulk_restore(docnames: str | list[str]):
docnames = frappe.parse_json(docnames)
message = _("Restoring Deleted Document")
restored, invalid, failed = [], [], []

View file

@ -130,7 +130,7 @@ def has_unseen_error_log():
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_log_doctypes(doctype, txt, searchfield, start, page_len, filters):
def get_log_doctypes(doctype: str, txt: str, searchfield: str, start: int, page_len: int, filters: list):
filters = filters or []
filters.extend(

View file

@ -116,7 +116,7 @@ def serialize_request(request):
@frappe.whitelist()
def add_indexes(indexes):
def add_indexes(indexes: str):
frappe.only_for("Administrator")
indexes = json.loads(indexes)

View file

@ -120,7 +120,9 @@ def get_users(role):
# searches for active employees
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def role_query(doctype, txt, searchfield, start, page_len, filters):
def role_query(
doctype: str, txt: str, searchfield: str, start: int, page_len: int, filters: list | dict | str
):
return frappe.get_all(
"Role",
limit_start=start,

View file

@ -241,7 +241,7 @@ def get_all_queued_jobs():
@frappe.whitelist()
def stop_job(job_id):
def stop_job(job_id: str):
frappe.get_doc("RQ Job", job_id).stop_job()

View file

@ -46,7 +46,7 @@ def validate_receiver_nos(receiver_list):
@frappe.whitelist()
def get_contact_number(contact_name, ref_doctype, ref_name):
def get_contact_number(contact_name: str, ref_doctype: str, ref_name: str):
"Return mobile number of the given contact."
number = frappe.db.sql(
"""select mobile_no, phone from tabContact
@ -62,7 +62,7 @@ def get_contact_number(contact_name, ref_doctype, ref_name):
@frappe.whitelist()
def send_sms(receiver_list, msg, sender_name="", success_msg=True):
def send_sms(receiver_list: str | list[str], msg: str, sender_name: str = "", success_msg: bool = True):
send_sms_hook_methods = frappe.get_hooks("send_sms")
if send_sms_hook_methods:
return frappe.get_attr(send_sms_hook_methods[-1])(receiver_list, msg, sender_name, success_msg)

View file

@ -2,6 +2,7 @@
# License: MIT. See LICENSE
import json
from typing import Any
import frappe
from frappe import _
@ -85,7 +86,7 @@ def send_user_permissions(bootinfo):
@frappe.whitelist()
def get_user_permissions(user=None):
def get_user_permissions(user: str | None = None):
"""Get all users permissions for the user as a dict of doctype"""
# if this is called from client-side,
# user can access only his/her user permissions
@ -160,7 +161,9 @@ def user_permission_exists(user, allow, for_value, applicable_for=None):
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_applicable_for_doctype_list(doctype, txt, searchfield, start, page_len, filters):
def get_applicable_for_doctype_list(
doctype: str, txt: str, searchfield: str, start: int, page_len: int, filters: dict[str, Any]
):
actual_doctype = filters.get("doctype")
linked_doctypes_map = get_linked_doctypes(actual_doctype, True)
@ -192,7 +195,7 @@ def get_permitted_documents(doctype):
@frappe.whitelist()
def check_applicable_doc_perm(user, doctype, docname):
def check_applicable_doc_perm(user: str, doctype: str, docname: str | int):
frappe.only_for("System Manager")
applicable = []
doc_exists = frappe.get_all(
@ -224,7 +227,7 @@ def check_applicable_doc_perm(user, doctype, docname):
@frappe.whitelist()
def clear_user_permissions(user, for_doctype):
def clear_user_permissions(user: str, for_doctype: str):
frappe.only_for("System Manager")
total = frappe.db.count("User Permission", {"user": user, "allow": for_doctype})
@ -242,7 +245,7 @@ def clear_user_permissions(user, for_doctype):
@frappe.whitelist()
def add_user_permissions(data):
def add_user_permissions(data: str | dict[str, Any]):
"""Add and update the user permissions"""
frappe.only_for("System Manager")
if isinstance(data, str):

View file

@ -218,7 +218,9 @@ def get_non_standard_user_types():
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_user_linked_doctypes(doctype, txt, searchfield, start, page_len, filters):
def get_user_linked_doctypes(
doctype: str, txt: str, searchfield: str, start: int, page_len: int, filters: dict | list | str
):
modules = [d.get("module_name") for d in get_modules_from_app("frappe")]
filters = [
@ -254,7 +256,7 @@ def get_user_linked_doctypes(doctype, txt, searchfield, start, page_len, filters
@frappe.whitelist()
def get_user_id(parent):
def get_user_id(parent: str):
data = (
frappe.get_all(
"DocField",

View file

@ -27,7 +27,9 @@ class CustomHTMLBlock(Document):
@frappe.whitelist()
def get_custom_blocks_for_user(doctype, txt, searchfield, start, page_len, filters):
def get_custom_blocks_for_user(
doctype: str, txt: str, searchfield: str, start: int, page_len: int, filters: dict | str | list
):
# return logged in users private blocks and all public blocks
customHTMLBlock = DocType("Custom HTML Block")

View file

@ -50,7 +50,7 @@ class OnboardingStep(Document):
@frappe.whitelist()
def get_onboarding_steps(ob_steps):
def get_onboarding_steps(ob_steps: str):
steps = []
for s in json.loads(ob_steps):
doc = frappe.get_doc("Onboarding Step", s.get("step"))

View file

@ -51,7 +51,7 @@ class SystemConsole(Document):
@frappe.whitelist(methods=["POST"])
def execute_code(doc):
def execute_code(doc: str):
console = frappe.get_doc(json.loads(doc))
console.run()
return console.as_dict()

View file

@ -173,5 +173,5 @@ def has_permission(doc, ptype="read", user=None):
@frappe.whitelist()
def new_todo(description):
def new_todo(description: str):
frappe.get_doc({"doctype": "ToDo", "description": description}).insert()

View file

@ -195,7 +195,7 @@ def create_workspace_sidebar_for_workspaces():
@frappe.whitelist()
def add_sidebar_items(sidebar_title, sidebar_items):
def add_sidebar_items(sidebar_title: str, sidebar_items: str):
sidebar_items = loads(sidebar_items)
title = f"{sidebar_title}-{frappe.session.user}"
w = frappe.get_doc("Workspace Sidebar", sidebar_title)

View file

@ -7,7 +7,7 @@ import frappe
@frappe.whitelist()
def update_task(args, field_map):
def update_task(args: str, field_map: str):
"""Updates Doc (called via gantt) based on passed `field_map`"""
args = frappe._dict(json.loads(args))
field_map = frappe._dict(json.loads(field_map))

View file

@ -13,7 +13,7 @@ from frappe.utils import get_link_to_form
@frappe.whitelist()
def toggle_like(doctype, name, add=False):
def toggle_like(doctype: str, name: str, add: str | bool = False):
"""Adds / removes the current user in the `__liked_by` property of the given document.
If column does not exist, will add it in the database.

View file

@ -6,7 +6,7 @@ from frappe.www.printview import set_title_values_for_link_and_dynamic_link_fiel
@frappe.whitelist()
@http_cache(max_age=60 * 10)
def get_preview_data(doctype, docname):
def get_preview_data(doctype: str, docname: str | int):
preview_fields = []
meta = frappe.get_meta(doctype)
if not meta.show_preview_popup:

View file

@ -72,7 +72,7 @@ def search_widget(
start: int = 0,
page_length: int = 10,
filters: str | None | dict | list = None,
filter_fields=None,
filter_fields: str | None = None,
as_dict: bool = False,
reference_doctype: str | None = None,
ignore_user_permissions: bool = False,
@ -372,7 +372,7 @@ def relevance_sorter(key, query, as_dict):
@frappe.whitelist()
def get_names_for_mentions(search_term):
def get_names_for_mentions(search_term: str):
users_for_mentions = frappe.cache.get_value("users_for_mentions", get_users_for_mentions)
user_groups = frappe.cache.get_value("user_groups", get_user_groups)
@ -408,7 +408,7 @@ def get_user_groups():
@frappe.whitelist()
def get_link_title(doctype, docname):
def get_link_title(doctype: str, docname: str | int):
meta = frappe.get_meta(doctype)
if meta.show_title_field_in_link:

View file

@ -821,7 +821,14 @@ class EmailAccount(Document):
@frappe.whitelist()
def get_append_to(doctype=None, txt=None, searchfield=None, start=None, page_len=None, filters=None):
def get_append_to(
doctype: str | None = None,
txt: str | None = None,
searchfield: str | None = None,
start: int | None = None,
page_len: int | None = None,
filters: list | dict | str | None = None,
):
txt = txt if txt else ""
filters = {"istable": 0, "issingle": 0, "email_append_to": 1}
@ -1054,7 +1061,7 @@ def remove_user_email_inbox(email_account):
@frappe.whitelist()
def set_email_password(email_account, password):
def set_email_password(email_account: str, password: str):
account = frappe.get_doc("Email Account", email_account)
if account.awaiting_password and account.auth_method != "OAuth":
account.awaiting_password = 0

View file

@ -106,14 +106,14 @@ class EmailGroup(Document):
@frappe.whitelist()
def import_from(name, doctype):
def import_from(name: str | int, doctype: str):
nlist = frappe.get_doc("Email Group", name)
if nlist.has_permission("write"):
return nlist.import_from(doctype)
@frappe.whitelist()
def add_subscribers(name, email_list):
def add_subscribers(name: str | int, email_list: str | list[str] | tuple[str, ...]):
if not isinstance(email_list, list | tuple):
email_list = email_list.replace(",", "\n").split("\n")

View file

@ -460,7 +460,7 @@ def retry_sending(queues: str | list[str]):
@frappe.whitelist()
def send_now(name, force_send: bool = False):
def send_now(name: str | int, force_send: bool = False):
record = EmailQueue.find(name)
if record:
record.check_permission()
@ -468,7 +468,7 @@ def send_now(name, force_send: bool = False):
@frappe.whitelist()
def toggle_sending(enable):
def toggle_sending(enable: bool | int | str):
frappe.only_for("System Manager")
frappe.db.set_default("suspend_email_queue", 0 if sbool(enable) else 1)

View file

@ -2,6 +2,7 @@
# License: MIT. See LICENSE
import json
from typing import Any
import frappe
from frappe.model.document import Document
@ -66,7 +67,7 @@ class EmailTemplate(Document):
@frappe.whitelist()
def get_email_template(template_name, doc, sender=None):
def get_email_template(template_name: str, doc: str | dict[str, Any], sender: str | None = None):
"""Return the processed HTML of a email template with the given doc"""
email_template = frappe.get_doc("Email Template", template_name)

View file

@ -92,7 +92,7 @@ class Notification(Document):
# START: PreviewRenderer API
@frappe.whitelist()
def preview_meets_condition(self, preview_document):
def preview_meets_condition(self, preview_document: str):
if not self.condition and not self.filters:
return _("Yes")
try:
@ -107,7 +107,7 @@ class Notification(Document):
return _("Failed to evaluate conditions: {}").format(e)
@frappe.whitelist()
def preview_message(self, preview_document):
def preview_message(self, preview_document: str):
try:
doc = frappe.get_cached_doc(self.document_type, preview_document)
context = get_context(doc)
@ -124,7 +124,7 @@ class Notification(Document):
return _("Failed to render message: {}").format(e)
@frappe.whitelist()
def preview_subject(self, preview_document):
def preview_subject(self, preview_document: str):
try:
doc = frappe.get_cached_doc(self.document_type, preview_document)
context = get_context(doc)
@ -730,7 +730,7 @@ def clear_notification_cache():
@frappe.whitelist()
def get_documents_for_today(notification):
def get_documents_for_today(notification: str):
notification = frappe.get_doc("Notification", notification)
notification.check_permission("read")
return [d.name for d in notification.get_documents_for_today()]

View file

@ -437,7 +437,13 @@ def get_formatted_html(
@frappe.whitelist()
def get_email_html(template, args, subject, header=None, with_container=False):
def get_email_html(
template: str,
args: str,
subject: str,
header: str | list | None = None,
with_container: str | int | bool = False,
):
import json
with_container = cint(with_container)

View file

@ -38,7 +38,7 @@ def get_email_accounts(user=None):
@frappe.whitelist()
def create_email_flag_queue(names, action):
def create_email_flag_queue(names: str, action: str):
"""create email flag queue to mark email either as read or unread"""
def mark_as_seen_unseen(name, action):

View file

@ -4,6 +4,7 @@ import csv
import json
from csv import Sniffer
from io import StringIO
from typing import Any
import requests
@ -104,7 +105,7 @@ def read_csv_content(fcontent, use_sniffer: bool = False):
@frappe.whitelist()
def send_csv_to_client(args):
def send_csv_to_client(args: str | dict[str, Any]):
if isinstance(args, str):
args = json.loads(args)

View file

@ -1,5 +1,6 @@
import json
from difflib import unified_diff
from typing import Any
import frappe
from frappe.utils import pretty_date
@ -44,7 +45,9 @@ def _get_value_from_version(version_name: int | str, fieldname: str):
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def version_query(doctype, txt, searchfield, start, page_len, filters):
def version_query(
doctype: str, txt: str, searchfield: str, start: int, page_len: int, filters: dict[str, Any]
):
version_filters = {
"docname": filters["docname"],
"ref_doctype": filters["ref_doctype"],

View file

@ -396,7 +396,7 @@ def get_file_name(fname, optional_suffix):
@frappe.whitelist()
def add_attachments(doctype, name, attachments):
def add_attachments(doctype: str, name: str | int, attachments: str | list[str]):
"""Add attachments to the given DocType"""
if isinstance(attachments, str):
attachments = json.loads(attachments)

View file

@ -477,7 +477,7 @@ def delete_for_document(doc):
@frappe.whitelist()
def search(text, start=0, limit=20, doctype=""):
def search(text: str, start: int = 0, limit: int = 20, doctype: str = ""):
"""
Search for given text in __global_search
:param text: phrase to be searched

View file

@ -11,6 +11,7 @@ from pypdf import PdfWriter
import frappe
from frappe import _
from frappe.core.doctype.access_log.access_log import make_access_log
from frappe.model.document import Document
from frappe.translate import print_language
from frappe.utils.jinja import render_template
from frappe.utils.pdf import get_pdf
@ -224,11 +225,11 @@ from frappe.deprecation_dumpster import read_multi_pdf
def download_pdf(
doctype: str,
name: str,
format=None,
doc=None,
no_letterhead=0,
language=None,
letterhead=None,
format: str | None = None,
doc: Document | None = None,
no_letterhead: bool | int = 0,
language: str | None = None,
letterhead: str | None = None,
pdf_generator: Literal["wkhtmltopdf", "chrome"] | None = None,
):
if pdf_generator is None:
@ -255,7 +256,7 @@ def download_pdf(
@frappe.whitelist()
def report_to_pdf(html, orientation="Landscape"):
def report_to_pdf(html: str, orientation: str = "Landscape"):
make_access_log(file_type="PDF", method="PDF", page=html)
frappe.local.response.filename = "report.pdf"
frappe.local.response.filecontent = get_pdf(
@ -313,7 +314,13 @@ def render_letterhead_for_print(letterhead: str | None = None, doc: dict | str |
@frappe.whitelist()
def print_by_server(
doctype, name, printer_setting, print_format=None, doc=None, no_letterhead=0, file_path=None
doctype: str,
name: str | int,
printer_setting: str,
print_format: str | None = None,
doc: Document | None = None,
no_letterhead: bool | int = 0,
file_path: str | None = None,
):
print_settings = frappe.get_doc("Network Printer Settings", printer_setting)
try:

View file

@ -1,5 +1,6 @@
import time
from contextlib import suppress
from typing import Any
from orjson import JSONDecodeError
@ -23,7 +24,15 @@ def is_enabled() -> bool:
@frappe.whitelist()
def capture(event_name, site=None, app=None, user=None, captured_at=None, properties=None, interval=None):
def capture(
event_name: str,
site: str | None = None,
app: str | None = None,
user: str | None = None,
captured_at: str | None = None,
properties: dict[str, Any] | None = None,
interval: int | str | None = None,
):
if not is_enabled():
return
@ -45,7 +54,7 @@ def capture(event_name, site=None, app=None, user=None, captured_at=None, proper
@frappe.whitelist()
def bulk_capture(events):
def bulk_capture(events: str | list[dict[str, Any]]):
if not is_enabled():
return
@ -226,7 +235,9 @@ class EventQueue:
@frappe.whitelist()
def get_debug_info(fetch_events=None, fetch_rate_limited_events=None):
def get_debug_info(
fetch_events: int | str | bool | None = None, fetch_rate_limited_events: int | str | bool | None = None
):
frappe.only_for("System Manager")
info = frappe._dict()

View file

@ -3,6 +3,7 @@
import json
import os
from typing import Any
import frappe
from frappe import _, scrub
@ -615,7 +616,7 @@ def get_web_form_module(doc):
@frappe.whitelist(allow_guest=True)
@rate_limit(key="web_form", limit=10, seconds=60)
def accept(web_form, data):
def accept(web_form: str, data: str):
"""Save the web form"""
data = frappe._dict(json.loads(data))
@ -732,7 +733,7 @@ def delete(web_form_name: str, docname: str | int):
@frappe.whitelist()
def delete_multiple(web_form_name: str, docnames):
def delete_multiple(web_form_name: str, docnames: str):
web_form = frappe.get_lazy_doc("Web Form", web_form_name)
docnames = json.loads(docnames)
@ -807,7 +808,7 @@ def get_form_data(doctype: str, docname: str | None = None, web_form_name: str |
@frappe.whitelist()
def get_in_list_view_fields(doctype):
def get_in_list_view_fields(doctype: str):
meta = frappe.get_meta(doctype)
fields = []

View file

@ -43,15 +43,15 @@ class WebPageView(Document):
@frappe.whitelist(allow_guest=True)
def make_view_log(
referrer=None,
browser=None,
version=None,
user_tz=None,
source=None,
campaign=None,
medium=None,
content=None,
visitor_id=None,
referrer: str | None = None,
browser: str | None = None,
version: str | None = None,
user_tz: str | None = None,
source: str | None = None,
campaign: str | None = None,
medium: str | None = None,
content: str | None = None,
visitor_id: str | None = None,
):
if not is_tracking_enabled():
return
@ -100,7 +100,7 @@ def make_view_log(
@frappe.whitelist()
@redis_cache(ttl=5 * 60)
def get_page_view_count(path):
def get_page_view_count(path: str):
return frappe.db.count("Web Page View", filters={"path": path})