refactor: Consider singles for dynamic set_value usage (#21367)

Found all usage using this semgrep rule:

```yaml
    - pattern: frappe.db.set_value($DOCTYPE, ...)
    - pattern-not: frappe.db.set_value("$STR", ...)
```
This commit is contained in:
Ankush Menat 2023-06-14 10:46:25 +05:30 committed by GitHub
parent 5d074f3237
commit 039be73af4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 75 additions and 30 deletions

View file

@ -755,4 +755,4 @@
"states": [],
"track_changes": 1,
"translated_doctype": 1
}
}

View file

@ -236,12 +236,19 @@ class File(Document):
):
return
frappe.db.set_value(
self.attached_to_doctype,
self.attached_to_name,
self.attached_to_field,
self.file_url,
)
if frappe.get_meta(self.attached_to_doctype).issingle:
frappe.db.set_single_value(
self.attached_to_doctype,
self.attached_to_field,
self.file_url,
)
else:
frappe.db.set_value(
self.attached_to_doctype,
self.attached_to_name,
self.attached_to_field,
self.file_url,
)
def fetch_attached_to_field(self, old_file_url):
if self.attached_to_field:

View file

@ -81,13 +81,21 @@ class ToDo(Document):
)
assignments.reverse()
frappe.db.set_value(
self.reference_type,
self.reference_name,
"_assign",
json.dumps(assignments),
update_modified=False,
)
if frappe.get_meta(self.reference_type).issingle:
frappe.db.set_single_value(
self.reference_type,
"_assign",
json.dumps(assignments),
update_modified=False,
)
else:
frappe.db.set_value(
self.reference_type,
self.reference_name,
"_assign",
json.dumps(assignments),
update_modified=False,
)
except Exception as e:
if frappe.db.is_table_missing(e) and frappe.flags.in_install:

View file

@ -52,7 +52,10 @@ def _toggle_like(doctype, name, add, user=None):
liked_by.remove(user)
remove_like(doctype, name)
frappe.db.set_value(doctype, name, "_liked_by", json.dumps(liked_by), update_modified=False)
if frappe.get_meta(doctype).issingle:
frappe.db.set_single_value(doctype, "_liked_by", json.dumps(liked_by), update_modified=False)
else:
frappe.db.set_value(doctype, name, "_liked_by", json.dumps(liked_by), update_modified=False)
except frappe.db.ProgrammingError as e:
if frappe.db.is_column_missing(e):

View file

@ -646,7 +646,10 @@ class BaseDocument:
def update_modified(self):
"""Update modified timestamp"""
self.set("modified", now())
frappe.db.set_value(self.doctype, self.name, "modified", self.modified, update_modified=False)
if getattr(self.meta, "issingle", False):
frappe.db.set_single_value(self.doctype, "modified", self.modified, update_modified=False)
else:
frappe.db.set_value(self.doctype, self.name, "modified", self.modified, update_modified=False)
def _fix_numeric_types(self):
for df in self.meta.get("fields"):

View file

@ -1123,7 +1123,7 @@ class Document(BaseDocument):
def reset_seen(self):
"""Clear _seen property and set current user as seen"""
if getattr(self.meta, "track_seen", False):
if getattr(self.meta, "track_seen", False) and not getattr(self.meta, "issingle", False):
frappe.db.set_value(
self.doctype, self.name, "_seen", json.dumps([frappe.session.user]), update_modified=False
)
@ -1182,15 +1182,25 @@ class Document(BaseDocument):
if self.name is None:
return
frappe.db.set_value(
self.doctype,
self.name,
fieldname,
value,
self.modified,
self.modified_by,
update_modified=update_modified,
)
if self.meta.issingle:
frappe.db.set_single_value(
self.doctype,
fieldname,
value,
modified=self.modified,
modified_by=self.modified_by,
update_modified=update_modified,
)
else:
frappe.db.set_value(
self.doctype,
self.name,
fieldname,
value,
self.modified,
self.modified_by,
update_modified=update_modified,
)
self.run_method("on_change")
@ -1375,7 +1385,7 @@ class Document(BaseDocument):
if not user:
user = frappe.session.user
if self.meta.track_seen and not frappe.flags.read_only:
if self.meta.track_seen and not frappe.flags.read_only and not self.meta.issingle:
_seen = self.get("_seen") or []
_seen = frappe.parse_json(_seen)

View file

@ -23,16 +23,23 @@ class TestAssign(FrappeTestCase):
if not frappe.db.exists("User", "test@example.com"):
frappe.get_doc({"doctype": "User", "email": "test@example.com", "first_name": "Test"}).insert()
added = assign(todo, "test@example.com")
self._test_basic_assign_on_document(todo)
def _test_basic_assign_on_document(self, doc):
added = assign(doc, "test@example.com")
self.assertTrue("test@example.com" in [d.owner for d in added])
frappe.desk.form.assign_to.remove(todo.doctype, todo.name, "test@example.com")
frappe.desk.form.assign_to.remove(doc.doctype, doc.name, "test@example.com")
# assignment is cleared
assignments = frappe.desk.form.assign_to.get(dict(doctype=todo.doctype, name=todo.name))
assignments = frappe.desk.form.assign_to.get(dict(doctype=doc.doctype, name=doc.name))
self.assertEqual(len(assignments), 0)
def test_assign_single(self):
c = frappe.get_doc("Contact Us Settings")
self._test_basic_assign_on_document(c)
def test_assignment_count(self):
frappe.db.delete("ToDo")

View file

@ -452,6 +452,13 @@ class TestDocument(FrappeTestCase):
frappe.exceptions.InvalidDates, doc.validate_from_to_dates, "start_date", "end_date"
)
def test_db_set_singles(self):
c = frappe.get_doc("Contact Us Settings")
key, val = "email_id", "admin1@example.com"
c.db_set(key, val)
changed_val = frappe.db.get_single_value(c.doctype, key)
self.assertEqual(val, changed_val)
class TestDocumentWebView(FrappeTestCase):
def get(self, path, user="Guest"):