diff --git a/frappe/__init__.py b/frappe/__init__.py index 925508adc9..ca6166ef28 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -42,7 +42,7 @@ from frappe.query_builder.utils import ( get_query_builder, ) from frappe.utils.caching import deprecated_local_cache as local_cache -from frappe.utils.caching import request_cache +from frappe.utils.caching import request_cache, site_cache from frappe.utils.data import as_unicode, bold, cint, cstr, safe_decode, safe_encode, sbool from frappe.utils.local import Local, LocalProxy, release_local @@ -1332,7 +1332,6 @@ def get_doc_hooks(): return local.doc_events_hooks -@request_cache def _load_app_hooks(app_name: str | None = None): import types @@ -1359,6 +1358,10 @@ def _load_app_hooks(app_name: str | None = None): return hooks +_request_cached_load_app_hooks = request_cache(_load_app_hooks) +_site_cached_load_app_hooks = site_cache(_load_app_hooks) + + def get_hooks( hook: str | None = None, default: Any | None = "_KEEP_DEFAULT_LIST", app_name: str | None = None ) -> _dict: @@ -1369,17 +1372,18 @@ def get_hooks( :param app_name: Filter by app.""" if app_name: - hooks = _load_app_hooks(app_name) + hooks = _request_cached_load_app_hooks(app_name) + elif local.conf.developer_mode: + hooks = _site_cached_load_app_hooks() else: - if conf.developer_mode: + hooks = client_cache.get_value("app_hooks") + if hooks is None: hooks = _load_app_hooks() - else: - hooks = client_cache.get_value("app_hooks") - if hooks is None: - hooks = _load_app_hooks() - client_cache.set_value("app_hooks", hooks) + client_cache.set_value("app_hooks", hooks) + if hook: return hooks.get(hook, ([] if default == "_KEEP_DEFAULT_LIST" else default)) + return _dict(hooks) diff --git a/frappe/tests/test_hooks.py b/frappe/tests/test_hooks.py index 9f175a958a..8c84f5e4a0 100644 --- a/frappe/tests/test_hooks.py +++ b/frappe/tests/test_hooks.py @@ -132,8 +132,8 @@ class TestHooks(IntegrationTestCase): # every call to frappe.get_hooks loads the hooks module into cache # therefor the cache has to be invalidated after every manual overwriting of hooks # TODO replace with a more elegant solution if there is one or build a util function for this purpose - if frappe._load_app_hooks.__wrapped__ in frappe.local.request_cache.keys(): - del frappe.local.request_cache[frappe._load_app_hooks.__wrapped__] + if frappe._load_app_hooks in frappe.local.request_cache.keys(): + del frappe.local.request_cache[frappe._load_app_hooks] self.assertEqual([False], frappe.get_hooks("fixture_auto_order", app_name=app)) self.assertEqual( [ @@ -151,7 +151,7 @@ class TestHooks(IntegrationTestCase): ) hooks.fixture_auto_order = True - del frappe.local.request_cache[frappe._load_app_hooks.__wrapped__] + del frappe.local.request_cache[frappe._load_app_hooks] self.assertEqual([True], frappe.get_hooks("fixture_auto_order", app_name=app)) shutil.rmtree(frappe.get_app_path(app, "fixtures")) @@ -168,7 +168,7 @@ class TestHooks(IntegrationTestCase): ] hooks.fixture_auto_order = False - del frappe.local.request_cache[frappe._load_app_hooks.__wrapped__] + del frappe.local.request_cache[frappe._load_app_hooks] shutil.rmtree(frappe.get_app_path(app, "fixtures")) export_fixtures(app) self.assertCountEqual( @@ -177,7 +177,7 @@ class TestHooks(IntegrationTestCase): ) hooks.fixture_auto_order = True - del frappe.local.request_cache[frappe._load_app_hooks.__wrapped__] + del frappe.local.request_cache[frappe._load_app_hooks] shutil.rmtree(frappe.get_app_path(app, "fixtures")) export_fixtures(app) self.assertCountEqual(