fix: meta signature (#28526)
* fix: meta
* fix: test case
save is required:
1. Fetch values
```python
def get_invalid_links(self, is_submittable=False):
"""Return list of invalid links and also update fetch values if not set."""
...
```
2. Is triggered by
```python
def _validate_links(self):
if self.flags.ignore_links or self._action == "cancel":
return
...
```
3. Which is triggered by either `_save` or `insert`
----
`reload` does not trigger link fetch
```python
def reload(self) -> "Self":
"""Reload document from database"""
return self.load_from_db()
```
Neither does the new calling path which does not excempt Document
from caching when initializing meta.
It can be proven that this revert would be an alternative fix. But this
seems design by accident and there's no preceivable reason to excempt
Document args from being cached normally.
diff --git a/frappe/model/meta.py b/frappe/model/meta.py
index c4321f0128..87452c812c 100644
--- a/frappe/model/meta.py
+++ b/frappe/model/meta.py
@@ -70,11 +70,10 @@ def get_meta(doctype: str | dict | DocRef, cached=True) -> "_Meta":
Returns:
Meta object for the given doctype.
"""
- if cached and (
- doctype_name := getattr(doctype, "doctype", doctype)
- if not isinstance(doctype, dict)
- else doctype.get("doctype")
- ):
+ if cached and not isinstance(doctype, Document):
+ doctype_name = (
+ getattr(doctype, "doctype", doctype) if not isinstance(doctype, dict) else doctype.get("doctype")
+ )
if meta := frappe.cache.hget("doctype_meta", doctype_name):
return meta
Therefore, we comply the test.
This commit is contained in:
parent
15d122025f
commit
3c1392c8fd
3 changed files with 18 additions and 15 deletions
|
|
@ -520,7 +520,7 @@ class DocType(Document):
|
|||
self.setup_autoincrement_and_sequence()
|
||||
|
||||
try:
|
||||
frappe.db.updatedb(self.name, Meta(self))
|
||||
frappe.db.updatedb(self.name, Meta(None, bootstrap=self))
|
||||
except Exception as e:
|
||||
print(f"\n\nThere was an issue while migrating the DocType: {self.name}\n")
|
||||
raise e
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class TestToDo(IntegrationTestCase):
|
|||
def test_fetch_setup(self):
|
||||
frappe.db.delete("ToDo")
|
||||
|
||||
todo_meta = frappe.get_doc("DocType", "ToDo")
|
||||
todo_meta = frappe.get_meta("ToDo")
|
||||
todo_meta.get("fields", dict(fieldname="assigned_by_full_name"))[0].fetch_from = ""
|
||||
todo_meta.save()
|
||||
|
||||
|
|
@ -48,13 +48,14 @@ class TestToDo(IntegrationTestCase):
|
|||
todo = frappe.get_doc(doctype="ToDo", description="test todo", assigned_by="Administrator").insert()
|
||||
self.assertFalse(todo.assigned_by_full_name)
|
||||
|
||||
todo_meta = frappe.get_doc("DocType", "ToDo")
|
||||
todo_meta = frappe.get_meta("ToDo")
|
||||
todo_meta.get("fields", dict(fieldname="assigned_by_full_name"))[
|
||||
0
|
||||
].fetch_from = "assigned_by.full_name"
|
||||
todo_meta.save()
|
||||
|
||||
todo.reload()
|
||||
todo.save()
|
||||
|
||||
self.assertEqual(
|
||||
todo.assigned_by_full_name, frappe.db.get_value("User", todo.assigned_by, "full_name")
|
||||
|
|
@ -120,7 +121,7 @@ class TestToDo(IntegrationTestCase):
|
|||
frappe.db.delete("ToDo")
|
||||
|
||||
# Allow user changes
|
||||
todo_meta = frappe.get_doc("DocType", "ToDo")
|
||||
todo_meta = frappe.get_meta("ToDo")
|
||||
field = todo_meta.get("fields", dict(fieldname="assigned_by_full_name"))[0]
|
||||
field.fetch_from = "assigned_by.full_name"
|
||||
field.fetch_if_empty = 1
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import os
|
|||
import typing
|
||||
from datetime import datetime
|
||||
from functools import singledispatchmethod
|
||||
from types import NoneType
|
||||
|
||||
import click
|
||||
|
||||
|
|
@ -41,7 +42,7 @@ from frappe.model.base_document import (
|
|||
from frappe.model.document import Document
|
||||
from frappe.model.workflow import get_workflow_name
|
||||
from frappe.modules import load_doctype_module
|
||||
from frappe.types import DocRef, _dict
|
||||
from frappe.types import DocRef
|
||||
from frappe.utils import cast, cint, cstr
|
||||
|
||||
DEFAULT_FIELD_LABELS = {
|
||||
|
|
@ -59,20 +60,21 @@ DEFAULT_FIELD_LABELS = {
|
|||
}
|
||||
|
||||
|
||||
def get_meta(doctype: str | dict | DocRef | Document, cached=True) -> "_Meta":
|
||||
def get_meta(doctype: str | dict | DocRef, cached=True) -> "_Meta":
|
||||
"""Get metadata for a doctype.
|
||||
|
||||
Args:
|
||||
doctype: The doctype as a string, dict, DocRef, or Document object.
|
||||
doctype: The doctype as a string, dict, DocRef (also: Document) object.
|
||||
cached: Whether to use cached metadata (default: True).
|
||||
|
||||
Returns:
|
||||
Meta object for the given doctype.
|
||||
"""
|
||||
if cached and not isinstance(doctype, Document):
|
||||
doctype_name = (
|
||||
getattr(doctype, "doctype", doctype) if not isinstance(doctype, dict) else doctype.get("doctype")
|
||||
)
|
||||
if cached and (
|
||||
doctype_name := getattr(doctype, "doctype", doctype)
|
||||
if not isinstance(doctype, dict)
|
||||
else doctype.get("doctype")
|
||||
):
|
||||
if meta := frappe.cache.hget("doctype_meta", doctype_name):
|
||||
return meta
|
||||
|
||||
|
|
@ -127,7 +129,7 @@ class Meta(Document):
|
|||
)
|
||||
|
||||
@singledispatchmethod
|
||||
def __init__(self, arg):
|
||||
def __init__(self, arg, bootstrap: Document = None):
|
||||
raise TypeError(f"Unsupported argument type: {type(arg)}")
|
||||
|
||||
@__init__.register(str)
|
||||
|
|
@ -145,9 +147,9 @@ class Meta(Document):
|
|||
super().__init__("DocType", doc_ref.get("doctype"))
|
||||
self.process()
|
||||
|
||||
@__init__.register(Document)
|
||||
def _(self, doc):
|
||||
super().__init__(doc.as_dict())
|
||||
@__init__.register(NoneType)
|
||||
def _(self, _args, bootstrap):
|
||||
super().__init__(bootstrap.as_dict())
|
||||
self.process()
|
||||
|
||||
def load_from_db(self):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue