diff --git a/frappe/database/utils.py b/frappe/database/utils.py index 16df8e8eeb..5fcb7cecf2 100644 --- a/frappe/database/utils.py +++ b/frappe/database/utils.py @@ -4,9 +4,9 @@ from functools import cached_property, wraps import frappe -from frappe.model.document import DocRef from frappe.query_builder.builder import MariaDB, Postgres from frappe.query_builder.functions import Function +from frappe.types import DocRef Query = str | MariaDB | Postgres QueryValues = tuple | list | dict | None diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py index 4fe1fa2fde..90eee8d0a6 100644 --- a/frappe/model/base_document.py +++ b/frappe/model/base_document.py @@ -368,8 +368,6 @@ class BaseDocument: def get_valid_dict( self, sanitize=True, convert_dates_to_str=False, ignore_nulls=False, ignore_virtual=False ) -> _dict: - from frappe.model.document import DocRef - d = _dict() field_values = self.__dict__ diff --git a/frappe/model/document.py b/frappe/model/document.py index 3be39eacbd..067d00b336 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -23,7 +23,7 @@ from frappe.model.docstatus import DocStatus from frappe.model.naming import set_new_name, validate_name from frappe.model.utils import is_virtual_doctype, simple_singledispatch from frappe.model.workflow import set_workflow_state_on_action, validate_workflow -from frappe.types import DF +from frappe.types import DF, DocRef from frappe.utils import compare, cstr, date_diff, file_lock, flt, now from frappe.utils.data import get_absolute_url, get_datetime, get_timedelta, getdate from frappe.utils.global_search import update_global_search @@ -38,27 +38,6 @@ DOCUMENT_LOCK_EXPIRTY = 12 * 60 * 60 # All locks expire in 12 hours automatical DOCUMENT_LOCK_SOFT_EXPIRY = 60 * 60 # Let users force-unlock after 60 minutes -class DocRef: - """A lightweight reference to a document, containing just the doctype and name.""" - - def __init__(self, doctype: str, name: str): - self.doctype = doctype - self.name = name - - def __value__(self): - # Used when requiring its value representation for db interactions, serializations, etc - return self.name - - def __hash__(self): - return hash(self.doctype + self.name or "") - - def __str__(self): - return f"{self.doctype} ({self.name or 'n/a'})" - - def __repr__(self): - return f"<{self.__class__.__name__}: doctype={self.doctype} name={self.name or 'n/a'}>" - - @simple_singledispatch def get_doc(*args, **kwargs) -> "Document": """Return a `frappe.model.Document` object. diff --git a/frappe/model/meta.py b/frappe/model/meta.py index 78d30f1c0e..e7d865d876 100644 --- a/frappe/model/meta.py +++ b/frappe/model/meta.py @@ -38,9 +38,10 @@ from frappe.model.base_document import ( TABLE_DOCTYPES_FOR_DOCTYPE, BaseDocument, ) -from frappe.model.document import DocRef, Document +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 from frappe.utils import cast, cint, cstr DEFAULT_FIELD_LABELS = { diff --git a/frappe/tests/test_doc_ref.py b/frappe/tests/test_doc_ref.py index 1422a457d4..5528e88aad 100644 --- a/frappe/tests/test_doc_ref.py +++ b/frappe/tests/test_doc_ref.py @@ -1,6 +1,7 @@ import frappe -from frappe.model.document import DocRef, Document, get_doc +from frappe.model.document import Document, get_doc from frappe.tests import IntegrationTestCase +from frappe.types import DocRef EXTRA_TEST_RECORD_DEPENDENCIES = ["User"] diff --git a/frappe/types/__init__.py b/frappe/types/__init__.py index e69de29bb2..de1873b02a 100644 --- a/frappe/types/__init__.py +++ b/frappe/types/__init__.py @@ -0,0 +1,2 @@ +from .docref import DocRef +from .frappedict import _dict diff --git a/frappe/types/docref.py b/frappe/types/docref.py new file mode 100644 index 0000000000..b86d784513 --- /dev/null +++ b/frappe/types/docref.py @@ -0,0 +1,25 @@ +from typing_extensions import override + + +class DocRef: + """A lightweight reference to a document, containing just the doctype and name.""" + + def __init__(self, doctype: str, name: str): + self.doctype = doctype + self.name = name + + def __value__(self) -> str: + # Used when requiring its value representation for db interactions, serializations, etc + return self.name + + @override + def __hash__(self) -> int: + return hash(self.doctype + self.name or "") + + @override + def __str__(self) -> str: + return f"{self.doctype} ({self.name or 'n/a'})" + + @override + def __repr__(self) -> str: + return f"<{self.__class__.__name__}: doctype={self.doctype} name={self.name or 'n/a'}>"