Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: refactor document.get definition (#26280) #26281

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion frappe/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1908,7 +1908,7 @@ def copy_doc(doc: "Document", ignore_no_copy: bool = True) -> "Document":
import copy

def remove_no_copy_fields(d):
for df in d.meta.get("fields", {"no_copy": 1}):
for df in d.meta.get("fields", filters={"no_copy": 1}):
if hasattr(d, df.fieldname):
d.set(df.fieldname, None)

Expand Down
10 changes: 5 additions & 5 deletions frappe/core/doctype/doctype/doctype.py
Original file line number Diff line number Diff line change
Expand Up @@ -725,7 +725,7 @@ def before_reload(self):

def preserve_naming_series_options_in_property_setter(self):
"""Preserve naming_series as property setter if it does not exist"""
naming_series = self.get("fields", {"fieldname": "naming_series"})
naming_series = self.get("fields", filters={"fieldname": "naming_series"})

if not naming_series:
return
Expand Down Expand Up @@ -1048,11 +1048,11 @@ def validate_series(dt, autoname=None, name=None):
if not name:
name = dt.name

if not autoname and dt.get("fields", {"fieldname": "naming_series"}):
if not autoname and dt.get("fields", filters={"fieldname": "naming_series"}):
dt.autoname = "naming_series:"
elif dt.autoname and dt.autoname.startswith("naming_series:"):
fieldname = dt.autoname.split("naming_series:", 1)[0] or "naming_series"
if not dt.get("fields", {"fieldname": fieldname}):
if not dt.get("fields", filters={"fieldname": fieldname}):
frappe.throw(
_("Fieldname called {0} must exist to enable autonaming").format(frappe.bold(fieldname)),
title=_("Field Missing"),
Expand Down Expand Up @@ -1468,7 +1468,7 @@ def check_image_field(meta):
if not meta.image_field:
return

df = meta.get("fields", {"fieldname": meta.image_field})
df = meta.get("fields", filters={"fieldname": meta.image_field})
if not df:
frappe.throw(_("Image field must be a valid fieldname"), InvalidFieldNameError)
if df[0].fieldtype != "Attach Image":
Expand Down Expand Up @@ -1500,7 +1500,7 @@ def check_timeline_field(meta):
if meta.timeline_field not in fieldname_list:
frappe.throw(_("Timeline field must be a valid fieldname"), InvalidFieldNameError)

df = meta.get("fields", {"fieldname": meta.timeline_field})[0]
df = meta.get("fields", filters={"fieldname": meta.timeline_field})[0]
if df.fieldtype not in ("Link", "Dynamic Link"):
frappe.throw(_("Timeline field must be a Link or Dynamic Link"), InvalidFieldNameError)

Expand Down
4 changes: 2 additions & 2 deletions frappe/core/doctype/file/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ def attach_files_to_document(doc: "Document", event) -> None:
is created.
"""

attach_fields = doc.meta.get("fields", {"fieldtype": ["in", ["Attach", "Attach Image"]]})
attach_fields = doc.meta.get("fields", filters={"fieldtype": ["in", ["Attach", "Attach Image"]]})

for df in attach_fields:
# this method runs in on_update hook of all documents
Expand Down Expand Up @@ -394,7 +394,7 @@ def relink_files(doc, fieldname, temp_doc_name):
def relink_mismatched_files(doc: "Document") -> None:
if not doc.get("__temporary_name", None):
return
attach_fields = doc.meta.get("fields", {"fieldtype": ["in", ["Attach", "Attach Image"]]})
attach_fields = doc.meta.get("fields", filters={"fieldtype": ["in", ["Attach", "Attach Image"]]})
for df in attach_fields:
if doc.get(df.fieldname):
relink_files(doc, df.fieldname, doc.__temporary_name)
Expand Down
6 changes: 3 additions & 3 deletions frappe/custom/doctype/customize_form/customize_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ def set_property_setters(self):

# docfield
for df in self.get("fields"):
meta_df = meta.get("fields", {"fieldname": df.fieldname})
meta_df = meta.get("fields", filters={"fieldname": df.fieldname})
if not meta_df or not is_standard_or_system_generated_field(meta_df[0]):
continue

Expand Down Expand Up @@ -484,7 +484,7 @@ def add_custom_field(self, df, i):

def update_in_custom_field(self, df, i):
meta = frappe.get_meta(self.doc_type)
meta_df = meta.get("fields", {"fieldname": df.fieldname})
meta_df = meta.get("fields", filters={"fieldname": df.fieldname})
if not meta_df or is_standard_or_system_generated_field(meta_df[0]):
# not a custom field
return
Expand Down Expand Up @@ -520,7 +520,7 @@ def delete_custom_fields(self):
df.fieldname for df in self.get("fields")
}
for fieldname in fields_to_remove:
df = meta.get("fields", {"fieldname": fieldname})[0]
df = meta.get("fields", filters={"fieldname": fieldname})[0]
if not is_standard_or_system_generated_field(df):
frappe.delete_doc("Custom Field", df.name)

Expand Down
26 changes: 13 additions & 13 deletions frappe/custom/doctype/customize_form/test_customize_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def test_fetch_to_customize(self):

self.assertEqual(len(d.get("fields")), len(frappe.get_doc("DocType", d.doc_type).fields) + 1)
self.assertEqual(d.get("fields")[-1].fieldname, self.field.fieldname)
self.assertEqual(d.get("fields", {"fieldname": "event_type"})[0].in_list_view, 1)
self.assertEqual(d.get("fields", filters={"fieldname": "event_type"})[0].in_list_view, 1)

return d

Expand Down Expand Up @@ -98,7 +98,7 @@ def test_save_customization_field_property(self):
None,
)

repeat_this_event_field = d.get("fields", {"fieldname": "repeat_this_event"})[0]
repeat_this_event_field = d.get("fields", filters={"fieldname": "repeat_this_event"})[0]
repeat_this_event_field.reqd = 1
d.run_method("save_customization")
self.assertEqual(
Expand All @@ -110,7 +110,7 @@ def test_save_customization_field_property(self):
"1",
)

repeat_this_event_field = d.get("fields", {"fieldname": "repeat_this_event"})[0]
repeat_this_event_field = d.get("fields", filters={"fieldname": "repeat_this_event"})[0]
repeat_this_event_field.reqd = 0
d.run_method("save_customization")
self.assertEqual(
Expand All @@ -126,14 +126,14 @@ def test_save_customization_custom_field_property(self):
d = self.get_customize_form("Event")
self.assertEqual(frappe.db.get_value("Custom Field", self.field.name, "reqd"), 0)

custom_field = d.get("fields", {"fieldname": self.field.fieldname})[0]
custom_field = d.get("fields", filters={"fieldname": self.field.fieldname})[0]
custom_field.reqd = 1
custom_field.no_copy = 1
d.run_method("save_customization")
self.assertEqual(frappe.db.get_value("Custom Field", self.field.name, "reqd"), 1)
self.assertEqual(frappe.db.get_value("Custom Field", self.field.name, "no_copy"), 1)

custom_field = d.get("fields", {"is_custom_field": True})[0]
custom_field = d.get("fields", filters={"is_custom_field": True})[0]
custom_field.reqd = 0
custom_field.no_copy = 0
d.run_method("save_customization")
Expand Down Expand Up @@ -169,7 +169,7 @@ def test_save_customization_new_field(self):

def test_save_customization_remove_field(self):
d = self.get_customize_form("Event")
custom_field = d.get("fields", {"fieldname": self.field.fieldname})[0]
custom_field = d.get("fields", filters={"fieldname": self.field.fieldname})[0]
d.get("fields").remove(custom_field)
d.run_method("save_customization")

Expand All @@ -183,29 +183,29 @@ def test_reset_to_defaults(self):
d.doc_type = "Event"
d.run_method("reset_to_defaults")

self.assertEqual(d.get("fields", {"fieldname": "repeat_this_event"})[0].in_list_view, 0)
self.assertEqual(d.get("fields", filters={"fieldname": "repeat_this_event"})[0].in_list_view, 0)

frappe.local.test_objects["Property Setter"] = []
make_test_records_for_doctype("Property Setter")

def test_set_allow_on_submit(self):
d = self.get_customize_form("Event")
d.get("fields", {"fieldname": "subject"})[0].allow_on_submit = 1
d.get("fields", {"fieldname": "custom_test_field"})[0].allow_on_submit = 1
d.get("fields", filters={"fieldname": "subject"})[0].allow_on_submit = 1
d.get("fields", filters={"fieldname": "custom_test_field"})[0].allow_on_submit = 1
d.run_method("save_customization")

d = self.get_customize_form("Event")

# don't allow for standard fields
self.assertEqual(d.get("fields", {"fieldname": "subject"})[0].allow_on_submit or 0, 0)
self.assertEqual(d.get("fields", filters={"fieldname": "subject"})[0].allow_on_submit or 0, 0)

# allow for custom field
self.assertEqual(d.get("fields", {"fieldname": "custom_test_field"})[0].allow_on_submit, 1)
self.assertEqual(d.get("fields", filters={"fieldname": "custom_test_field"})[0].allow_on_submit, 1)

def test_title_field_pattern(self):
d = self.get_customize_form("Web Form")

df = d.get("fields", {"fieldname": "title"})[0]
df = d.get("fields", filters={"fieldname": "title"})[0]

# invalid fieldname
df.default = """{doc_type} - {introduction_test}"""
Expand Down Expand Up @@ -235,7 +235,7 @@ def test_save_customization_length_field_property(self):
d = self.get_customize_form("Notification Log")

new_document_length = 255
document_name = d.get("fields", {"fieldname": "document_name"})[0]
document_name = d.get("fields", filters={"fieldname": "document_name"})[0]
document_name.length = new_document_length
d.run_method("save_customization")

Expand Down
8 changes: 4 additions & 4 deletions frappe/desk/doctype/todo/test_todo.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def test_fetch_setup(self):
frappe.db.delete("ToDo")

todo_meta = frappe.get_doc("DocType", "ToDo")
todo_meta.get("fields", dict(fieldname="assigned_by_full_name"))[0].fetch_from = ""
todo_meta.get("fields", filters=dict(fieldname="assigned_by_full_name"))[0].fetch_from = ""
todo_meta.save()

frappe.clear_cache(doctype="ToDo")
Expand All @@ -40,7 +40,7 @@ def test_fetch_setup(self):
self.assertFalse(todo.assigned_by_full_name)

todo_meta = frappe.get_doc("DocType", "ToDo")
todo_meta.get("fields", dict(fieldname="assigned_by_full_name"))[
todo_meta.get("fields", filters=dict(fieldname="assigned_by_full_name"))[
0
].fetch_from = "assigned_by.full_name"
todo_meta.save()
Expand Down Expand Up @@ -112,7 +112,7 @@ def test_fetch_if_empty(self):

# Allow user changes
todo_meta = frappe.get_doc("DocType", "ToDo")
field = todo_meta.get("fields", dict(fieldname="assigned_by_full_name"))[0]
field = todo_meta.get("fields", filters=dict(fieldname="assigned_by_full_name"))[0]
field.fetch_from = "assigned_by.full_name"
field.fetch_if_empty = 1
todo_meta.save()
Expand All @@ -129,7 +129,7 @@ def test_fetch_if_empty(self):
self.assertEqual(todo.assigned_by_full_name, "Admin")

# Overwrite user changes
todo.meta.get("fields", dict(fieldname="assigned_by_full_name"))[0].fetch_if_empty = 0
todo.meta.get("fields", filters=dict(fieldname="assigned_by_full_name"))[0].fetch_if_empty = 0
todo.meta.save()

todo.reload()
Expand Down
2 changes: 1 addition & 1 deletion frappe/desk/form/linked_with.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ def get_linked_docs(doctype: str, name: str, linkinfo: dict | None = None) -> di
d.fieldname
for d in linkmeta.get(
"fields",
{
filters={
"in_list_view": 1,
"fieldtype": ["not in", ("Image", "HTML", "Button", *frappe.model.table_fields)],
},
Expand Down
4 changes: 2 additions & 2 deletions frappe/desk/form/meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ def add_custom_script(self):

def add_search_fields(self):
"""add search fields found in the doctypes indicated by link fields' options"""
for df in self.get("fields", {"fieldtype": "Link", "options": ["!=", "[Select]"]}):
for df in self.get("fields", filters={"fieldtype": "Link", "options": ["!=", "[Select]"]}):
if df.options:
try:
search_fields = frappe.get_meta(df.options).search_fields
Expand Down Expand Up @@ -213,7 +213,7 @@ def _show_missing_doctype_msg(self, df):
frappe.throw(msg, title=_("Missing DocType"))

def add_linked_document_type(self):
for df in self.get("fields", {"fieldtype": "Link"}):
for df in self.get("fields", filters={"fieldtype": "Link"}):
if df.options:
try:
df.linked_document_type = frappe.get_meta(df.options).document_type
Expand Down
4 changes: 2 additions & 2 deletions frappe/desk/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,9 @@ def search_widget(
if not meta.translated_doctype and (f == "name" or (fmeta and fmeta.fieldtype in field_types)):
or_filters.append([doctype, f.strip(), "like", f"%{txt}%"])

if meta.get("fields", {"fieldname": "enabled", "fieldtype": "Check"}):
if meta.get("fields", filters={"fieldname": "enabled", "fieldtype": "Check"}):
filters.append([doctype, "enabled", "=", 1])
if meta.get("fields", {"fieldname": "disabled", "fieldtype": "Check"}):
if meta.get("fields", filters={"fieldname": "disabled", "fieldtype": "Check"}):
filters.append([doctype, "disabled", "!=", 1])

# format a list of fields combining search fields and filter fields
Expand Down
28 changes: 17 additions & 11 deletions frappe/model/base_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,16 +212,20 @@ def update_if_missing(self, d):
def get_db_value(self, key):
return frappe.db.get_value(self.doctype, self.name, key)

def get(self, key, filters=None, limit=None, default=None):
def get(self, key, default=None, limit=None, filters=None):
if isinstance(key, dict):
return _filter(self.get_all_children(), key, limit=limit)

if filters:
if isinstance(filters, dict):
return _filter(self.__dict__.get(key, []), filters, limit=limit)
if filters is not None:
return _filter(self.__dict__.get(key, []), filters, limit=limit)

# perhaps you wanted to set a default instead
default = filters
if default and isinstance(default, dict):
from frappe.utils.deprecations import deprecation_warning

deprecation_warning("Please use the doc.get `filters` keyword argument.")

filters = default
return _filter(self.__dict__.get(key, []), filters, limit=limit)

value = self.__dict__.get(key, default)

Expand Down Expand Up @@ -759,7 +763,7 @@ def has_content(df):

missing = []

for df in self.meta.get("fields", {"reqd": ("=", 1)}):
for df in self.meta.get("fields", filters={"reqd": ("=", 1)}):
if self.get(df.fieldname) in (None, []) or not has_content(df):
missing.append((df.fieldname, get_msg(df)))

Expand All @@ -784,7 +788,9 @@ def get_msg(df, docname):
invalid_links = []
cancelled_links = []

for df in self.meta.get_link_fields() + self.meta.get("fields", {"fieldtype": ("=", "Dynamic Link")}):
for df in self.meta.get_link_fields() + self.meta.get(
"fields", filters={"fieldtype": ("=", "Dynamic Link")}
):
docname = self.get(df.fieldname)

if docname:
Expand Down Expand Up @@ -944,7 +950,7 @@ def _validate_constants(self):
if frappe.flags.in_import or self.is_new() or self.flags.ignore_validate_constants:
return

constants = [d.fieldname for d in self.meta.get("fields", {"set_only_once": ("=", 1)})]
constants = [d.fieldname for d in self.meta.get("fields", filters={"set_only_once": ("=", 1)})]
if constants:
values = frappe.db.get_value(self.doctype, self.name, constants, as_dict=True)

Expand Down Expand Up @@ -1119,7 +1125,7 @@ def _save_passwords(self):
if self.flags.ignore_save_passwords is True:
return

for df in self.meta.get("fields", {"fieldtype": ("=", "Password")}):
for df in self.meta.get("fields", filters={"fieldtype": ("=", "Password")}):
if self.flags.ignore_save_passwords and df.fieldname in self.flags.ignore_save_passwords:
continue
new_password = self.get(df.fieldname)
Expand Down Expand Up @@ -1290,7 +1296,7 @@ def _extract_images_from_text_editor(self):
from frappe.core.doctype.file.utils import extract_images_from_doc

if self.doctype != "DocType":
for df in self.meta.get("fields", {"fieldtype": ("=", "Text Editor")}):
for df in self.meta.get("fields", filters={"fieldtype": ("=", "Text Editor")}):
extract_images_from_doc(self, df.fieldname)


Expand Down
2 changes: 1 addition & 1 deletion frappe/model/db_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,7 @@ def prepare_filter_condition(self, f):
f.update(get_additional_filter_field(additional_filters_config, f, f.value))

meta = frappe.get_meta(f.doctype)
df = meta.get("fields", {"fieldname": f.fieldname})
df = meta.get("fields", filters={"fieldname": f.fieldname})
df = df[0] if df else None

# primary key is never nullable, modified is usually indexed by default and always present
Expand Down
4 changes: 2 additions & 2 deletions frappe/model/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -624,14 +624,14 @@ def get_msg(df):
)

for df in self.meta.get(
"fields", {"non_negative": ("=", 1), "fieldtype": ("in", ["Int", "Float", "Currency"])}
"fields", filters={"non_negative": ("=", 1), "fieldtype": ("in", ["Int", "Float", "Currency"])}
):
if flt(self.get(df.fieldname)) < 0:
msg = get_msg(df)
frappe.throw(msg, frappe.NonNegativeError, title=_("Negative Value"))

def _fix_rating_value(self):
for field in self.meta.get("fields", {"fieldtype": "Rating"}):
for field in self.meta.get("fields", filters={"fieldtype": "Rating"}):
value = self.get(field.fieldname)
if not isinstance(value, float):
value = flt(value)
Expand Down