From 0a886b7ca89ba52bb60f0fd0a2e760f93ddf2954 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 19 Feb 2024 17:55:59 +0530 Subject: [PATCH] perf: defer imports during CLI --- frappe/commands/redis_utils.py | 2 +- frappe/core/doctype/file/file.py | 3 ++- frappe/core/doctype/file/utils.py | 10 ++++++---- frappe/query_builder/utils.py | 4 +--- frappe/translate.py | 16 +++++++++++++--- 5 files changed, 23 insertions(+), 12 deletions(-) diff --git a/frappe/commands/redis_utils.py b/frappe/commands/redis_utils.py index 5b558de126..884c4400ff 100644 --- a/frappe/commands/redis_utils.py +++ b/frappe/commands/redis_utils.py @@ -3,7 +3,6 @@ import os import click import frappe -from frappe.utils.redis_queue import RedisQueue @click.command("create-rq-users") @@ -21,6 +20,7 @@ def create_rq_users(set_admin_password=False, use_rq_auth=False): and app config is used by app while connecting to redis server. """ from frappe.installer import update_site_config + from frappe.utils.redis_queue import RedisQueue acl_file_path = os.path.abspath("../config/redis_queue.acl") diff --git a/frappe/core/doctype/file/file.py b/frappe/core/doctype/file/file.py index e207e24a2a..76a9bd4a88 100755 --- a/frappe/core/doctype/file/file.py +++ b/frappe/core/doctype/file/file.py @@ -10,7 +10,6 @@ import zipfile from urllib.parse import quote, unquote from PIL import Image, ImageFile, ImageOps -from requests.exceptions import HTTPError, SSLError import frappe from frappe import _ @@ -428,6 +427,8 @@ class File(Document): suffix: str = "small", crop: bool = False, ) -> str: + from requests.exceptions import HTTPError, SSLError + if not self.file_url: return diff --git a/frappe/core/doctype/file/utils.py b/frappe/core/doctype/file/utils.py index 9a0b4a8f5c..cca3f8586b 100644 --- a/frappe/core/doctype/file/utils.py +++ b/frappe/core/doctype/file/utils.py @@ -7,9 +7,6 @@ from typing import TYPE_CHECKING, Optional from urllib.parse import unquote import filetype -import requests -import requests.exceptions -from PIL import Image import frappe from frappe import _, safe_decode @@ -86,6 +83,8 @@ def get_extension( def get_local_image(file_url: str) -> tuple["ImageFile", str, str]: + from PIL import Image + if file_url.startswith("/private"): file_url_path = (file_url.lstrip("/"),) else: @@ -116,7 +115,10 @@ def get_local_image(file_url: str) -> tuple["ImageFile", str, str]: def get_web_image(file_url: str) -> tuple["ImageFile", str, str]: - # download + import requests + import requests.exceptions + from PIL import Image + file_url = frappe.utils.get_url(file_url) r = requests.get(file_url, stream=True) try: diff --git a/frappe/query_builder/utils.py b/frappe/query_builder/utils.py index 98cc0bd45e..fada6101ea 100644 --- a/frappe/query_builder/utils.py +++ b/frappe/query_builder/utils.py @@ -104,12 +104,10 @@ def patch_query_execute(): def prepare_query(query): import inspect - from frappe.utils.safe_exec import SERVER_SCRIPT_FILE_PREFIX - param_collector = NamedParameterWrapper() query = query.get_sql(param_wrapper=param_collector) if frappe.flags.in_safe_exec: - from frappe.utils.safe_exec import check_safe_sql_query + from frappe.utils.safe_exec import SERVER_SCRIPT_FILE_PREFIX, check_safe_sql_query if not check_safe_sql_query(query, throw=False): callstack = inspect.stack() diff --git a/frappe/translate.py b/frappe/translate.py index 2f8dc303b0..cf5c72bb10 100644 --- a/frappe/translate.py +++ b/frappe/translate.py @@ -19,9 +19,6 @@ from contextlib import contextmanager, suppress from csv import reader, writer import frappe -from frappe.gettext.extractors.javascript import extract_javascript -from frappe.gettext.extractors.utils import extract_messages_from_code, is_translatable -from frappe.gettext.translate import get_translations_from_mo from frappe.query_builder import DocType, Field from frappe.utils import cstr, get_bench_path, is_html, strip, strip_html_tags, unique @@ -174,6 +171,8 @@ def get_translations_from_apps(lang, apps=None): For derivative languages (es-GT), take translations from the base language (es) and then update translations from the child (es-GT)""" translations = {} + from frappe.gettext.translate import get_translations_from_mo + for app in apps or frappe.get_installed_apps(_ensure_on_bench=True): translations.update(get_translations_from_csv(lang, app) or {}) translations.update(get_translations_from_mo(lang, app) or {}) @@ -307,6 +306,8 @@ def get_messages_from_navbar(): def get_messages_from_doctype(name): """Extract all translatable messages for a doctype. Includes labels, Python code, Javascript code, html templates""" + from frappe.gettext.extractors.utils import is_translatable + messages = [] meta = frappe.get_meta(name) @@ -347,6 +348,7 @@ def get_messages_from_doctype(name): def get_messages_from_workflow(doctype=None, app_name=None): assert doctype or app_name, "doctype or app_name should be provided" + from frappe.gettext.extractors.utils import is_translatable # translations for Workflows workflows = [] @@ -416,6 +418,8 @@ def get_messages_from_workflow(doctype=None, app_name=None): def get_messages_from_custom_fields(app_name): + from frappe.gettext.extractors.utils import is_translatable + fixtures = frappe.get_hooks("fixtures", app_name=app_name) or [] custom_fields = [] @@ -456,6 +460,8 @@ def get_messages_from_page(name): def get_messages_from_report(name): """Return all translatable strings from a :class:`frappe.core.doctype.Report`.""" + from frappe.gettext.extractors.utils import is_translatable + report = frappe.get_doc("Report", name) messages = _get_messages_from_page_or_report( "Report", name, frappe.db.get_value("DocType", report.ref_doctype, "module") @@ -559,6 +565,9 @@ def get_messages_from_file(path: str) -> list[tuple[str, str, str | None, int]]: :param path: path of the code file """ + + from frappe.gettext.extractors.utils import extract_messages_from_code + frappe.flags.setdefault("scanned_files", set()) # TODO: Find better alternative # To avoid duplicate scan @@ -625,6 +634,7 @@ def extract_messages_from_javascript_code(code: str) -> list[tuple[int, str, str """Extracts translatable strings from JavaScript code using babel.""" messages = [] + from frappe.gettext.extractors.javascript import extract_javascript for message in extract_javascript( code,