perf(BaseDocument): ~50% faster as_dict (#16549)
Co-authored-by: Pruthvi Patel <pruthvipatel145@gmail.com>
This commit is contained in:
parent
042f98bcc5
commit
fa7ea4bce8
2 changed files with 39 additions and 39 deletions
|
|
@ -40,6 +40,9 @@ data_fieldtypes = (
|
|||
"JSON",
|
||||
)
|
||||
|
||||
float_like_fields = {"Float", "Currency", "Percent"}
|
||||
datetime_fields = {"Datetime", "Date", "Time"}
|
||||
|
||||
attachment_fieldtypes = (
|
||||
"Attach",
|
||||
"Attach Image",
|
||||
|
|
|
|||
|
|
@ -6,7 +6,14 @@ from typing import Dict, List
|
|||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model import child_table_fields, default_fields, display_fieldtypes, table_fields
|
||||
from frappe.model import (
|
||||
child_table_fields,
|
||||
datetime_fields,
|
||||
default_fields,
|
||||
display_fieldtypes,
|
||||
float_like_fields,
|
||||
table_fields,
|
||||
)
|
||||
from frappe.model.docstatus import DocStatus
|
||||
from frappe.model.naming import set_new_name
|
||||
from frappe.model.utils.link_count import notify_link_count
|
||||
|
|
@ -256,7 +263,8 @@ class BaseDocument(object):
|
|||
) -> Dict:
|
||||
d = frappe._dict()
|
||||
for fieldname in self.meta.get_valid_columns():
|
||||
d[fieldname] = self.get(fieldname)
|
||||
# column is valid, we can use getattr
|
||||
d[fieldname] = getattr(self, fieldname, None)
|
||||
|
||||
# if no need for sanitization and value is None, continue
|
||||
if not sanitize and d[fieldname] is None:
|
||||
|
|
@ -264,25 +272,24 @@ class BaseDocument(object):
|
|||
|
||||
df = self.meta.get_field(fieldname)
|
||||
|
||||
if df and df.get("is_virtual"):
|
||||
if ignore_virtual:
|
||||
del d[fieldname]
|
||||
continue
|
||||
if df:
|
||||
if getattr(df, "is_virtual", False):
|
||||
if ignore_virtual:
|
||||
del d[fieldname]
|
||||
continue
|
||||
|
||||
from frappe.utils.safe_exec import get_safe_globals
|
||||
if d[fieldname] is None and (options := getattr(df, "options", None)):
|
||||
from frappe.utils.safe_exec import get_safe_globals
|
||||
|
||||
if d[fieldname] is None:
|
||||
if df.get("options"):
|
||||
d[fieldname] = frappe.safe_eval(
|
||||
code=df.get("options"),
|
||||
code=options,
|
||||
eval_globals=get_safe_globals(),
|
||||
eval_locals={"doc": self},
|
||||
)
|
||||
else:
|
||||
_val = getattr(self, fieldname, None)
|
||||
if _val and not callable(_val):
|
||||
d[fieldname] = _val
|
||||
elif df:
|
||||
|
||||
if isinstance(d[fieldname], list) and df.fieldtype not in table_fields:
|
||||
frappe.throw(_("Value for {0} cannot be a list").format(_(df.label)))
|
||||
|
||||
if df.fieldtype == "Check":
|
||||
d[fieldname] = 1 if cint(d[fieldname]) else 0
|
||||
|
||||
|
|
@ -292,25 +299,20 @@ class BaseDocument(object):
|
|||
elif df.fieldtype == "JSON" and isinstance(d[fieldname], dict):
|
||||
d[fieldname] = json.dumps(d[fieldname], sort_keys=True, indent=4, separators=(",", ": "))
|
||||
|
||||
elif df.fieldtype in ("Currency", "Float", "Percent") and not isinstance(d[fieldname], float):
|
||||
elif df.fieldtype in float_like_fields and not isinstance(d[fieldname], float):
|
||||
d[fieldname] = flt(d[fieldname])
|
||||
|
||||
elif df.fieldtype in ("Datetime", "Date", "Time") and d[fieldname] == "":
|
||||
elif (df.fieldtype in datetime_fields and d[fieldname] == "") or (
|
||||
getattr(df, "unique", False) and cstr(d[fieldname]).strip() == ""
|
||||
):
|
||||
d[fieldname] = None
|
||||
|
||||
elif df.get("unique") and cstr(d[fieldname]).strip() == "":
|
||||
# unique empty field should be set to None
|
||||
d[fieldname] = None
|
||||
|
||||
if isinstance(d[fieldname], list) and df.fieldtype not in table_fields:
|
||||
frappe.throw(_("Value for {0} cannot be a list").format(_(df.label)))
|
||||
|
||||
if convert_dates_to_str and isinstance(
|
||||
d[fieldname], (datetime.datetime, datetime.date, datetime.time, datetime.timedelta)
|
||||
):
|
||||
d[fieldname] = str(d[fieldname])
|
||||
|
||||
if d[fieldname] is None and ignore_nulls:
|
||||
if ignore_nulls and d[fieldname] is None:
|
||||
del d[fieldname]
|
||||
|
||||
return d
|
||||
|
|
@ -361,7 +363,7 @@ class BaseDocument(object):
|
|||
convert_dates_to_str=False,
|
||||
no_child_table_fields=False,
|
||||
) -> Dict:
|
||||
doc = self.get_valid_dict(convert_dates_to_str=convert_dates_to_str)
|
||||
doc = self.get_valid_dict(convert_dates_to_str=convert_dates_to_str, ignore_nulls=no_nulls)
|
||||
doc["doctype"] = self.doctype
|
||||
|
||||
for df in self.meta.get_table_fields():
|
||||
|
|
@ -376,20 +378,15 @@ class BaseDocument(object):
|
|||
for d in children
|
||||
]
|
||||
|
||||
if no_nulls:
|
||||
for k in list(doc):
|
||||
if doc[k] is None:
|
||||
del doc[k]
|
||||
|
||||
if no_default_fields:
|
||||
for k in list(doc):
|
||||
if k in default_fields:
|
||||
del doc[k]
|
||||
for key in default_fields:
|
||||
if key in doc:
|
||||
del doc[key]
|
||||
|
||||
if no_child_table_fields:
|
||||
for k in list(doc):
|
||||
if k in child_table_fields:
|
||||
del doc[k]
|
||||
for key in child_table_fields:
|
||||
if key in doc:
|
||||
del doc[key]
|
||||
|
||||
for key in (
|
||||
"_user_tags",
|
||||
|
|
@ -399,8 +396,8 @@ class BaseDocument(object):
|
|||
"__run_link_triggers",
|
||||
"__unsaved",
|
||||
):
|
||||
if self.get(key):
|
||||
doc[key] = self.get(key)
|
||||
if value := getattr(self, key, None):
|
||||
doc[key] = value
|
||||
|
||||
return doc
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue