From 45f8aff909c8ebc257a100dada6f53f211f4d79a Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Sat, 24 Jun 2023 12:28:20 +0530 Subject: [PATCH] perf: defer LDAP import --- .../core/doctype/error_log/test_error_log.py | 9 ++++++++ frappe/utils/error.py | 21 +++++++++++++++---- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/frappe/core/doctype/error_log/test_error_log.py b/frappe/core/doctype/error_log/test_error_log.py index 59670de8d2..3f19a6dd0c 100644 --- a/frappe/core/doctype/error_log/test_error_log.py +++ b/frappe/core/doctype/error_log/test_error_log.py @@ -1,7 +1,10 @@ # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE +from ldap3.core.exceptions import LDAPException, LDAPInappropriateAuthenticationResult + import frappe from frappe.tests.utils import FrappeTestCase +from frappe.utils.error import _is_ldap_exception # test_records = frappe.get_test_records('Error Log') @@ -12,3 +15,9 @@ class TestErrorLog(FrappeTestCase): doc = frappe.new_doc("Error Log") error = doc.log_error("This is an error") self.assertEqual(error.doctype, "Error Log") + + def test_ldap_exceptions(self): + exc = [LDAPException, LDAPInappropriateAuthenticationResult] + + for e in exc: + self.assertTrue(_is_ldap_exception(e())) diff --git a/frappe/utils/error.py b/frappe/utils/error.py index 47c5b055a8..323b0e2746 100644 --- a/frappe/utils/error.py +++ b/frappe/utils/error.py @@ -11,8 +11,6 @@ import pydoc import sys import traceback -from ldap3.core.exceptions import LDAPException - import frappe from frappe.utils import cstr, encode @@ -20,16 +18,31 @@ EXCLUDE_EXCEPTIONS = ( frappe.AuthenticationError, frappe.CSRFTokenError, # CSRF covers OAuth too frappe.SecurityException, - LDAPException, frappe.InReadOnlyMode, ) +LDAP_BASE_EXCEPTION = "LDAPException" + + +def _is_ldap_exception(e): + """Check if exception is from LDAP library. + + This is a hack but ensures that LDAP is not imported unless it's required. This is tested in + unittests in case the exception changes in future. + """ + + for t in type(e).__mro__: + if t.__name__ == LDAP_BASE_EXCEPTION: + return True + + return False + def make_error_snapshot(exception): if frappe.conf.disable_error_snapshot: return - if isinstance(exception, EXCLUDE_EXCEPTIONS): + if isinstance(exception, EXCLUDE_EXCEPTIONS) or _is_ldap_exception(exception): return logger = frappe.logger(with_more_info=True)