diff --git a/frappe/commands/utils.py b/frappe/commands/utils.py index c156d65a1f..afafadcbaf 100644 --- a/frappe/commands/utils.py +++ b/frappe/commands/utils.py @@ -13,7 +13,6 @@ from frappe.coverage import CodeCoverage from frappe.exceptions import SiteNotSpecifiedError from frappe.utils import cint, update_progress_bar from frappe.utils.bench_helper import CliCtxObj -from frappe.utils.print_utils import setup_chromium EXTRA_ARGS_CTX = {"ignore_unknown_options": True, "allow_extra_args": True} @@ -1030,6 +1029,8 @@ def list_sites(context: CliCtxObj, output_json=False): @click.command("setup-chrome") def setup_chrome(): + from frappe.utils.print_utils import setup_chromium + setup_chromium() diff --git a/frappe/utils/pdf.py b/frappe/utils/pdf.py index 44b2f632cc..9f40feffaa 100644 --- a/frappe/utils/pdf.py +++ b/frappe/utils/pdf.py @@ -6,15 +6,11 @@ import io import mimetypes import os import subprocess -import time from urllib.parse import parse_qs, urlparse import cssutils import pdfkit -from frappe.utils.pdf_generator.browser import Browser -from frappe.utils.pdf_generator.pdf_merge import PDFTransformer - pdfkit.source.unicode = str # NOTE: upstream bug; PYTHONOPTIMIZE=1 optimized this away from bs4 import BeautifulSoup from packaging.version import Version @@ -136,6 +132,8 @@ def get_pdf(html, options=None, output: PdfWriter | None = None): def measure_time(func): + import time + def wrapper(*args, **kwargs): start_time = time.time() result = func(*args, **kwargs) @@ -148,7 +146,9 @@ def measure_time(func): @measure_time def get_chrome_pdf(print_format, html, options, output, pdf_generator=None): + from frappe.utils.pdf_generator.browser import Browser from frappe.utils.pdf_generator.chrome_pdf_generator import ChromePDFGenerator + from frappe.utils.pdf_generator.pdf_merge import PDFTransformer if pdf_generator != "chrome": # Use the default pdf generator diff --git a/frappe/utils/pdf_generator/browser.py b/frappe/utils/pdf_generator/browser.py index a8666f52d6..3e9b71683e 100644 --- a/frappe/utils/pdf_generator/browser.py +++ b/frappe/utils/pdf_generator/browser.py @@ -3,8 +3,6 @@ from typing import ClassVar from bs4 import BeautifulSoup import frappe -from frappe.utils.pdf_generator.cdp_connection import CDPSocketClient -from frappe.utils.pdf_generator.page import Page from frappe.utils.print_utils import convert_uom, parse_float_and_unit @@ -54,6 +52,8 @@ class Browser: generator.remove_browser(self.browserID) def open(self, generator): + from frappe.utils.pdf_generator.cdp_connection import CDPSocketClient + # checking because if we share browser accross request _devtools_url will already be set for subsequent requests. if not generator._devtools_url: generator._set_devtools_url() @@ -86,6 +86,8 @@ class Browser: NOTE: In theory this will make it faster but more importantly use less cpu, ram etc. """ + from frappe.utils.pdf_generator.page import Page + page = Page(self.session, self.browser_context_id, page_type) page.is_print_designer = self.is_print_designer diff --git a/frappe/utils/pdf_generator/page.py b/frappe/utils/pdf_generator/page.py index fd813839c5..f0e9a62304 100644 --- a/frappe/utils/pdf_generator/page.py +++ b/frappe/utils/pdf_generator/page.py @@ -1,9 +1,6 @@ import base64 import time import urllib -from io import BytesIO - -from pypdf import PdfReader import frappe @@ -75,13 +72,13 @@ class Page: "domain": domain, "sameSite": "Strict", } - result, error = self.send("Network.enable") + _result, error = self.send("Network.enable") if error: raise RuntimeError(f"Error enabling network: {error}") - result, error = self.send("Network.setCookie", cookie) + _result, error = self.send("Network.setCookie", cookie) if error: raise RuntimeError(f"Error setting cookie: {error}") - result, error = self.send("Network.disable") + _result, error = self.send("Network.disable") if error: raise RuntimeError(f"Error disabling network: {error}") @@ -324,6 +321,10 @@ class Page: return stream_id def get_pdf_from_stream(self, stream_id, raw=False): + from io import BytesIO + + from pypdf import PdfReader + pdf_data = b"" offset = 0 while True: diff --git a/frappe/utils/pdf_generator/pdf_merge.py b/frappe/utils/pdf_generator/pdf_merge.py index 586f83adf5..7081498ac6 100644 --- a/frappe/utils/pdf_generator/pdf_merge.py +++ b/frappe/utils/pdf_generator/pdf_merge.py @@ -1,8 +1,3 @@ -from io import BytesIO - -from pypdf import PdfWriter, Transformation - - class PDFTransformer: def __init__(self, browser): self.browser = browser @@ -29,6 +24,8 @@ class PDFTransformer: self.is_footer_dynamic = self.browser.is_footer_dynamic def transform_pdf(self, output=None): + from pypdf import PdfWriter + header = self.header_pdf body = self.body_pdf footer = self.footer_pdf @@ -99,12 +96,16 @@ class PDFTransformer: return self.get_file_data_from_writer(writer) def _transform(self, page, page_top, ty): + from pypdf import PdfWriter, Transformation + transform = Transformation().translate(ty=ty) page.mediabox.upper_right = (page.mediabox.right, page_top) page.add_transformation(transform) return page def get_file_data_from_writer(self, writer_obj): + from io import BytesIO + # https://docs.python.org/3/library/io.html stream = BytesIO() writer_obj.write(stream) diff --git a/frappe/utils/print_utils.py b/frappe/utils/print_utils.py index 54d9c48602..6efa3a119c 100644 --- a/frappe/utils/print_utils.py +++ b/frappe/utils/print_utils.py @@ -1,13 +1,8 @@ import os -import platform import re -import shutil -import zipfile -from pathlib import Path from typing import Literal import click -import requests import frappe from frappe.utils.data import cint, cstr @@ -176,6 +171,9 @@ def setup_chromium(): def find_or_download_chromium_executable(): """Finds the Chromium executable or downloads if not found.""" + import platform + from pathlib import Path + bench_path = frappe.utils.get_bench_path() """Determine the path to the Chromium executable.""" chromium_dir = os.path.join(bench_path, "chromium") @@ -200,6 +198,12 @@ def find_or_download_chromium_executable(): def download_chromium(): + import platform + import shutil + import zipfile + + import requests + bench_path = frappe.utils.get_bench_path() """Download and extract Chromium for the specific version at the bench level.""" chromium_dir = os.path.join(bench_path, "chromium") @@ -367,6 +371,8 @@ def calculate_platform(): Returns: str: The detected platform string (e.g., 'linux64', 'mac-arm64', etc.). """ + import platform + system = platform.system().lower() arch = platform.machine().lower()