From ff83bb1473dc3dd0e2010e27944089b5e4873ab1 Mon Sep 17 00:00:00 2001 From: Kaushal Shriwas <64089478+kaulith@users.noreply.github.com> Date: Thu, 30 Apr 2026 13:15:04 +0530 Subject: [PATCH] fix: preserve docnames matching scientific notation in get_safe_filters --- frappe/tests/test_client.py | 9 +++++++++ frappe/tests/test_utils.py | 18 ++++++++++++++++++ frappe/utils/__init__.py | 6 ++---- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/frappe/tests/test_client.py b/frappe/tests/test_client.py index 24bc03f9c3..a40e1ce5d7 100644 --- a/frappe/tests/test_client.py +++ b/frappe/tests/test_client.py @@ -291,3 +291,12 @@ class TestClient(IntegrationTestCase): # cleanup for doc in docs: frappe.delete_doc("Note", doc) + + def test_get_value_with_scientific_notation_docname(self): + from frappe.client import get_value + + tag = frappe.get_doc({"doctype": "Tag", "name": "3E002"}).insert(ignore_if_duplicate=True) + try: + self.assertEqual(get_value("Tag", ["name"], "3E002"), {"name": "3E002"}) + finally: + tag.delete() diff --git a/frappe/tests/test_utils.py b/frappe/tests/test_utils.py index 3093fba8b0..9ab94d4e6b 100644 --- a/frappe/tests/test_utils.py +++ b/frappe/tests/test_utils.py @@ -32,6 +32,7 @@ from frappe.utils import ( get_file_timestamp, get_gravatar, get_link_to_report, + get_safe_filters, get_site_info, get_sites, get_url, @@ -352,6 +353,23 @@ class TestFilters(IntegrationTestCase): link = get_link_to_report(name="ToDo", filters=filters) self.assertIn('creation=["between",["2024-01-01","2024-12-31"]]', link) + def test_get_safe_filters_preserves_scientific_notation_docnames(self): + self.assertEqual(get_safe_filters("3E002"), "3E002") + self.assertEqual(get_safe_filters("1E5"), "1E5") + self.assertEqual(get_safe_filters("2e10"), "2e10") + self.assertEqual(get_safe_filters("1.5"), "1.5") + self.assertEqual(get_safe_filters("Infinity"), "Infinity") + self.assertEqual(get_safe_filters("NaN"), "NaN") + + def test_get_safe_filters_still_parses_json(self): + self.assertEqual(get_safe_filters('{"name": "ABC"}'), {"name": "ABC"}) + self.assertEqual(get_safe_filters('[["name", "=", "ABC"]]'), [["name", "=", "ABC"]]) + + def test_get_safe_filters_passes_through_non_strings(self): + self.assertEqual(get_safe_filters({"name": "ABC"}), {"name": "ABC"}) + self.assertEqual(get_safe_filters([["name", "=", "ABC"]]), [["name", "=", "ABC"]]) + self.assertIsNone(get_safe_filters(None)) + class TestMoney(IntegrationTestCase): def test_money_in_words(self): diff --git a/frappe/utils/__init__.py b/frappe/utils/__init__.py index 68ca5c7f51..0ec51ca9b0 100644 --- a/frappe/utils/__init__.py +++ b/frappe/utils/__init__.py @@ -904,12 +904,10 @@ def call(fn, *args, **kwargs): def get_safe_filters(filters): + if not isinstance(filters, str) or not filters or filters[0] not in "{[": + return filters try: filters = orjson.loads(filters) - - if isinstance(filters, int | float): - filters = frappe.as_unicode(filters) - except (TypeError, ValueError): # filters are not passed, not json pass