docs: consistent doc strings
This commit is contained in:
parent
aefe634ff7
commit
8d2137c265
102 changed files with 487 additions and 594 deletions
|
|
@ -109,7 +109,7 @@ class _dict(dict):
|
||||||
|
|
||||||
|
|
||||||
def _(msg: str, lang: str | None = None, context: str | None = None) -> str:
|
def _(msg: str, lang: str | None = None, context: str | None = None) -> str:
|
||||||
"""Returns translated string in current lang, if exists.
|
"""Return translated string in current lang, if exists.
|
||||||
Usage:
|
Usage:
|
||||||
_('Change')
|
_('Change')
|
||||||
_('Change', context='Coins')
|
_('Change', context='Coins')
|
||||||
|
|
@ -145,7 +145,7 @@ def _(msg: str, lang: str | None = None, context: str | None = None) -> str:
|
||||||
|
|
||||||
|
|
||||||
def as_unicode(text, encoding: str = "utf-8") -> str:
|
def as_unicode(text, encoding: str = "utf-8") -> str:
|
||||||
"""Convert to unicode if required"""
|
"""Convert to unicode if required."""
|
||||||
if isinstance(text, str):
|
if isinstance(text, str):
|
||||||
return text
|
return text
|
||||||
elif text is None:
|
elif text is None:
|
||||||
|
|
@ -327,7 +327,7 @@ def connect_replica() -> bool:
|
||||||
|
|
||||||
|
|
||||||
def get_site_config(sites_path: str | None = None, site_path: str | None = None) -> dict[str, Any]:
|
def get_site_config(sites_path: str | None = None, site_path: str | None = None) -> dict[str, Any]:
|
||||||
"""Returns `site_config.json` combined with `sites/common_site_config.json`.
|
"""Return `site_config.json` combined with `sites/common_site_config.json`.
|
||||||
`site_config` is a set of site wide settings like database name, password, email etc."""
|
`site_config` is a set of site wide settings like database name, password, email etc."""
|
||||||
config = _dict()
|
config = _dict()
|
||||||
|
|
||||||
|
|
@ -373,7 +373,7 @@ def get_site_config(sites_path: str | None = None, site_path: str | None = None)
|
||||||
|
|
||||||
|
|
||||||
def get_common_site_config(sites_path: str | None = None) -> dict[str, Any]:
|
def get_common_site_config(sites_path: str | None = None) -> dict[str, Any]:
|
||||||
"""Returns common site config as dictionary.
|
"""Return common site config as dictionary.
|
||||||
|
|
||||||
This is useful for:
|
This is useful for:
|
||||||
- checking configuration which should only be allowed in common site config
|
- checking configuration which should only be allowed in common site config
|
||||||
|
|
@ -432,7 +432,7 @@ def setup_redis_cache_connection():
|
||||||
|
|
||||||
|
|
||||||
def get_traceback(with_context: bool = False) -> str:
|
def get_traceback(with_context: bool = False) -> str:
|
||||||
"""Returns error traceback."""
|
"""Return error traceback."""
|
||||||
from frappe.utils import get_traceback
|
from frappe.utils import get_traceback
|
||||||
|
|
||||||
return get_traceback(with_context=with_context)
|
return get_traceback(with_context=with_context)
|
||||||
|
|
@ -638,7 +638,7 @@ def get_user():
|
||||||
|
|
||||||
|
|
||||||
def get_roles(username=None) -> list[str]:
|
def get_roles(username=None) -> list[str]:
|
||||||
"""Returns roles of current user."""
|
"""Return roles of current user."""
|
||||||
if not local.session or not local.session.user:
|
if not local.session or not local.session.user:
|
||||||
return ["Guest"]
|
return ["Guest"]
|
||||||
import frappe.permissions
|
import frappe.permissions
|
||||||
|
|
@ -1003,8 +1003,8 @@ def has_permission(
|
||||||
parent_doctype=None,
|
parent_doctype=None,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Returns True if the user has permission `ptype` for given `doctype` or `doc`
|
Return True if the user has permission `ptype` for given `doctype` or `doc`
|
||||||
Raises `frappe.PermissionError` if user isn't permitted and `throw` is truthy
|
Raise `frappe.PermissionError` if user isn't permitted and `throw` is truthy
|
||||||
|
|
||||||
:param doctype: DocType for which permission is to be check.
|
:param doctype: DocType for which permission is to be check.
|
||||||
:param ptype: Permission type (`read`, `write`, `create`, `submit`, `cancel`, `amend`). Default: `read`.
|
:param ptype: Permission type (`read`, `write`, `create`, `submit`, `cancel`, `amend`). Default: `read`.
|
||||||
|
|
@ -1084,7 +1084,7 @@ def has_website_permission(doc=None, ptype="read", user=None, verbose=False, doc
|
||||||
|
|
||||||
|
|
||||||
def is_table(doctype: str) -> bool:
|
def is_table(doctype: str) -> bool:
|
||||||
"""Returns True if `istable` property (indicating child Table) is set for given DocType."""
|
"""Return True if `istable` property (indicating child Table) is set for given DocType."""
|
||||||
|
|
||||||
def get_tables():
|
def get_tables():
|
||||||
return db.get_values("DocType", filters={"istable": 1}, order_by=None, pluck=True)
|
return db.get_values("DocType", filters={"istable": 1}, order_by=None, pluck=True)
|
||||||
|
|
@ -1128,7 +1128,7 @@ def new_doc(
|
||||||
as_dict: bool = False,
|
as_dict: bool = False,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
) -> "Document":
|
) -> "Document":
|
||||||
"""Returns a new document of the given DocType with defaults set.
|
"""Return a new document of the given DocType with defaults set.
|
||||||
|
|
||||||
:param doctype: DocType of the new document.
|
:param doctype: DocType of the new document.
|
||||||
:param parent_doc: [optional] add to parent document.
|
:param parent_doc: [optional] add to parent document.
|
||||||
|
|
@ -1174,7 +1174,7 @@ def _set_document_in_cache(key: str, doc: "Document") -> None:
|
||||||
def can_cache_doc(args) -> str | None:
|
def can_cache_doc(args) -> str | None:
|
||||||
"""
|
"""
|
||||||
Determine if document should be cached based on get_doc params.
|
Determine if document should be cached based on get_doc params.
|
||||||
Returns cache key if doc can be cached, None otherwise.
|
Return cache key if doc can be cached, None otherwise.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not args:
|
if not args:
|
||||||
|
|
@ -1426,17 +1426,17 @@ def rename_doc(
|
||||||
|
|
||||||
|
|
||||||
def get_module(modulename):
|
def get_module(modulename):
|
||||||
"""Returns a module object for given Python module name using `importlib.import_module`."""
|
"""Return a module object for given Python module name using `importlib.import_module`."""
|
||||||
return importlib.import_module(modulename)
|
return importlib.import_module(modulename)
|
||||||
|
|
||||||
|
|
||||||
def scrub(txt: str) -> str:
|
def scrub(txt: str) -> str:
|
||||||
"""Returns sluggified string. e.g. `Sales Order` becomes `sales_order`."""
|
"""Return sluggified string. e.g. `Sales Order` becomes `sales_order`."""
|
||||||
return cstr(txt).replace(" ", "_").replace("-", "_").lower()
|
return cstr(txt).replace(" ", "_").replace("-", "_").lower()
|
||||||
|
|
||||||
|
|
||||||
def unscrub(txt: str) -> str:
|
def unscrub(txt: str) -> str:
|
||||||
"""Returns titlified string. e.g. `sales_order` becomes `Sales Order`."""
|
"""Return titlified string. e.g. `sales_order` becomes `Sales Order`."""
|
||||||
return txt.replace("_", " ").replace("-", " ").title()
|
return txt.replace("_", " ").replace("-", " ").title()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1536,7 +1536,7 @@ def get_installed_apps(*, _ensure_on_bench=False) -> list[str]:
|
||||||
|
|
||||||
|
|
||||||
def get_doc_hooks():
|
def get_doc_hooks():
|
||||||
"""Returns hooked methods for given doc. It will expand the dict tuple if required."""
|
"""Return hooked methods for given doc. Expand the dict tuple if required."""
|
||||||
if not hasattr(local, "doc_events_hooks"):
|
if not hasattr(local, "doc_events_hooks"):
|
||||||
hooks = get_hooks("doc_events", {})
|
hooks = get_hooks("doc_events", {})
|
||||||
out = {}
|
out = {}
|
||||||
|
|
@ -1643,7 +1643,7 @@ def setup_module_map():
|
||||||
|
|
||||||
|
|
||||||
def get_file_items(path, raise_not_found=False, ignore_empty_lines=True):
|
def get_file_items(path, raise_not_found=False, ignore_empty_lines=True):
|
||||||
"""Returns items from text file as a list. Ignores empty lines."""
|
"""Return items from text file as a list. Ignore empty lines."""
|
||||||
import frappe.utils
|
import frappe.utils
|
||||||
|
|
||||||
content = read_file(path, raise_not_found=raise_not_found)
|
content = read_file(path, raise_not_found=raise_not_found)
|
||||||
|
|
@ -1996,7 +1996,7 @@ def get_all(doctype, *args, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
def get_value(*args, **kwargs):
|
def get_value(*args, **kwargs):
|
||||||
"""Returns a document property or list of properties.
|
"""Return a document property or list of properties.
|
||||||
|
|
||||||
Alias for `frappe.db.get_value`
|
Alias for `frappe.db.get_value`
|
||||||
|
|
||||||
|
|
@ -2011,7 +2011,7 @@ def get_value(*args, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
def as_json(obj: dict | list, indent=1, separators=None, ensure_ascii=True) -> str:
|
def as_json(obj: dict | list, indent=1, separators=None, ensure_ascii=True) -> str:
|
||||||
"""Returns the JSON string representation of the given `obj`."""
|
"""Return the JSON string representation of the given `obj`."""
|
||||||
from frappe.utils.response import json_handler
|
from frappe.utils.response import json_handler
|
||||||
|
|
||||||
if separators is None:
|
if separators is None:
|
||||||
|
|
@ -2044,7 +2044,7 @@ def are_emails_muted():
|
||||||
|
|
||||||
|
|
||||||
def get_test_records(doctype):
|
def get_test_records(doctype):
|
||||||
"""Returns list of objects from `test_records.json` in the given doctype's folder."""
|
"""Return list of objects from `test_records.json` in the given doctype's folder."""
|
||||||
from frappe.modules import get_doctype_module, get_module_path
|
from frappe.modules import get_doctype_module, get_module_path
|
||||||
|
|
||||||
path = os.path.join(
|
path = os.path.join(
|
||||||
|
|
@ -2277,7 +2277,7 @@ log_level = None
|
||||||
def logger(
|
def logger(
|
||||||
module=None, with_more_info=False, allow_site=True, filter=None, max_size=100_000, file_count=20
|
module=None, with_more_info=False, allow_site=True, filter=None, max_size=100_000, file_count=20
|
||||||
):
|
):
|
||||||
"""Returns a python logger that uses StreamHandler"""
|
"""Return a python logger that uses StreamHandler."""
|
||||||
from frappe.utils.logger import get_logger
|
from frappe.utils.logger import get_logger
|
||||||
|
|
||||||
return get_logger(
|
return get_logger(
|
||||||
|
|
@ -2298,7 +2298,7 @@ def get_desk_link(doctype, name):
|
||||||
|
|
||||||
|
|
||||||
def bold(text: str) -> str:
|
def bold(text: str) -> str:
|
||||||
"""Returns `text` wrapped in `<strong>` tags."""
|
"""Return `text` wrapped in `<strong>` tags."""
|
||||||
return f"<strong>{text}</strong>"
|
return f"<strong>{text}</strong>"
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2322,7 +2322,7 @@ def get_website_settings(key):
|
||||||
|
|
||||||
|
|
||||||
def get_system_settings(key: str):
|
def get_system_settings(key: str):
|
||||||
"""Returns the value associated with the given `key` from System Settings DocType."""
|
"""Return the value associated with the given `key` from System Settings DocType."""
|
||||||
if not hasattr(local, "system_settings"):
|
if not hasattr(local, "system_settings"):
|
||||||
try:
|
try:
|
||||||
local.system_settings = get_cached_doc("System Settings")
|
local.system_settings = get_cached_doc("System Settings")
|
||||||
|
|
@ -2341,7 +2341,7 @@ def get_active_domains():
|
||||||
|
|
||||||
def get_version(doctype, name, limit=None, head=False, raise_err=True):
|
def get_version(doctype, name, limit=None, head=False, raise_err=True):
|
||||||
"""
|
"""
|
||||||
Returns a list of version information of a given DocType.
|
Return a list of version information for the given DocType.
|
||||||
|
|
||||||
Note: Applicable only if DocType has changes tracked.
|
Note: Applicable only if DocType has changes tracked.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -289,7 +289,7 @@ class LoginManager:
|
||||||
def check_password(self, user, pwd):
|
def check_password(self, user, pwd):
|
||||||
"""check password"""
|
"""check password"""
|
||||||
try:
|
try:
|
||||||
# returns user in correct case
|
# return user in correct case
|
||||||
return check_password(user, pwd)
|
return check_password(user, pwd)
|
||||||
except frappe.AuthenticationError:
|
except frappe.AuthenticationError:
|
||||||
self.fail("Incorrect password", user=user)
|
self.fail("Incorrect password", user=user)
|
||||||
|
|
|
||||||
|
|
@ -297,11 +297,11 @@ class AutoRepeat(Document):
|
||||||
|
|
||||||
def get_next_schedule_date(self, schedule_date, for_full_schedule=False):
|
def get_next_schedule_date(self, schedule_date, for_full_schedule=False):
|
||||||
"""
|
"""
|
||||||
Returns the next schedule date for auto repeat after a recurring document has been created.
|
Return the next schedule date for auto repeat after a recurring document has been created.
|
||||||
Adds required offset to the schedule_date param and returns the next schedule date.
|
Add required offset to the schedule_date param and return the next schedule date.
|
||||||
|
|
||||||
:param schedule_date: The date when the last recurring document was created.
|
:param schedule_date: The date when the last recurring document was created.
|
||||||
:param for_full_schedule: If True, returns the immediate next schedule date, else the full schedule.
|
:param for_full_schedule: If True, return the immediate next schedule date, else the full schedule.
|
||||||
"""
|
"""
|
||||||
if month_map.get(self.frequency):
|
if month_map.get(self.frequency):
|
||||||
month_count = month_map.get(self.frequency) + month_diff(schedule_date, self.start_date) - 1
|
month_count = month_map.get(self.frequency) + month_diff(schedule_date, self.start_date) - 1
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,7 @@ def setup_assets(assets_archive):
|
||||||
def download_frappe_assets(verbose=True):
|
def download_frappe_assets(verbose=True):
|
||||||
"""Downloads and sets up Frappe assets if they exist based on the current
|
"""Downloads and sets up Frappe assets if they exist based on the current
|
||||||
commit HEAD.
|
commit HEAD.
|
||||||
Returns True if correctly setup else returns False.
|
Return True if correctly setup else return False.
|
||||||
"""
|
"""
|
||||||
frappe_head = getoutput("cd ../apps/frappe && git rev-parse HEAD")
|
frappe_head = getoutput("cd ../apps/frappe && git rev-parse HEAD")
|
||||||
|
|
||||||
|
|
@ -407,7 +407,7 @@ def link_assets_dir(source, target, hard_link=False):
|
||||||
|
|
||||||
|
|
||||||
def scrub_html_template(content):
|
def scrub_html_template(content):
|
||||||
"""Returns HTML content with removed whitespace and comments"""
|
"""Return HTML content with removed whitespace and comments."""
|
||||||
# remove whitespace to a single space
|
# remove whitespace to a single space
|
||||||
content = WHITESPACE_PATTERN.sub(" ", content)
|
content = WHITESPACE_PATTERN.sub(" ", content)
|
||||||
|
|
||||||
|
|
@ -418,7 +418,7 @@ def scrub_html_template(content):
|
||||||
|
|
||||||
|
|
||||||
def html_to_js_template(path, content):
|
def html_to_js_template(path, content):
|
||||||
"""returns HTML template content as Javascript code, adding it to `frappe.templates`"""
|
"""Return HTML template content as Javascript code, by adding it to `frappe.templates`"""
|
||||||
return """frappe.templates["{key}"] = '{content}';\n""".format(
|
return """frappe.templates["{key}"] = '{content}';\n""".format(
|
||||||
key=path.rsplit("/", 1)[-1][:-5], content=scrub_html_template(content)
|
key=path.rsplit("/", 1)[-1][:-5], content=scrub_html_template(content)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ def get_list(
|
||||||
as_dict: bool = True,
|
as_dict: bool = True,
|
||||||
or_filters=None,
|
or_filters=None,
|
||||||
):
|
):
|
||||||
"""Returns a list of records by filters, fields, ordering and limit
|
"""Return a list of records by filters, fields, ordering and limit.
|
||||||
|
|
||||||
:param doctype: DocType of the data to be queried
|
:param doctype: DocType of the data to be queried
|
||||||
:param fields: fields to be returned. Default is `name`
|
:param fields: fields to be returned. Default is `name`
|
||||||
|
|
@ -74,7 +74,7 @@ def get_count(doctype, filters=None, debug=False, cache=False):
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get(doctype, name=None, filters=None, parent=None):
|
def get(doctype, name=None, filters=None, parent=None):
|
||||||
"""Returns a document by name or filters
|
"""Return a document by name or filters.
|
||||||
|
|
||||||
:param doctype: DocType of the document to be returned
|
:param doctype: DocType of the document to be returned
|
||||||
:param name: return document of this `name`
|
:param name: return document of this `name`
|
||||||
|
|
@ -97,7 +97,7 @@ def get(doctype, name=None, filters=None, parent=None):
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_value(doctype, fieldname, filters=None, as_dict=True, debug=False, parent=None):
|
def get_value(doctype, fieldname, filters=None, as_dict=True, debug=False, parent=None):
|
||||||
"""Returns a value form a document
|
"""Return a value from a document.
|
||||||
|
|
||||||
:param doctype: DocType to be queried
|
:param doctype: DocType to be queried
|
||||||
:param fieldname: Field to be returned (default `name`)
|
:param fieldname: Field to be returned (default `name`)
|
||||||
|
|
@ -296,7 +296,7 @@ def bulk_update(docs):
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def has_permission(doctype, docname, perm_type="read"):
|
def has_permission(doctype, docname, perm_type="read"):
|
||||||
"""Returns a JSON with data whether the document has the requested permission
|
"""Return a JSON with data whether the document has the requested permission.
|
||||||
|
|
||||||
:param doctype: DocType of the document to be checked
|
:param doctype: DocType of the document to be checked
|
||||||
:param docname: `name` of the document to be checked
|
:param docname: `name` of the document to be checked
|
||||||
|
|
@ -307,7 +307,7 @@ def has_permission(doctype, docname, perm_type="read"):
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_doc_permissions(doctype, docname):
|
def get_doc_permissions(doctype, docname):
|
||||||
"""Returns an evaluated document permissions dict like `{"read":1, "write":1}`
|
"""Return an evaluated document permissions dict like `{"read":1, "write":1}`.
|
||||||
|
|
||||||
:param doctype: DocType of the document to be evaluated
|
:param doctype: DocType of the document to be evaluated
|
||||||
:param docname: `name` of the document to be evaluated
|
:param docname: `name` of the document to be evaluated
|
||||||
|
|
@ -354,7 +354,7 @@ def get_js(items):
|
||||||
|
|
||||||
@frappe.whitelist(allow_guest=True)
|
@frappe.whitelist(allow_guest=True)
|
||||||
def get_time_zone():
|
def get_time_zone():
|
||||||
"""Returns default time zone"""
|
"""Return the default time zone"""
|
||||||
return {"time_zone": frappe.defaults.get_defaults().get("time_zone")}
|
return {"time_zone": frappe.defaults.get_defaults().get("time_zone")}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -466,8 +466,7 @@ def validate_link(doctype: str, docname: str, fields=None):
|
||||||
|
|
||||||
|
|
||||||
def insert_doc(doc) -> "Document":
|
def insert_doc(doc) -> "Document":
|
||||||
"""Inserts document and returns parent document object with appended child document
|
"""Insert document and return parent document object with appended child document if `doc` is child document else return the inserted document object.
|
||||||
if `doc` is child document else returns the inserted document object
|
|
||||||
|
|
||||||
:param doc: doc to insert (dict)"""
|
:param doc: doc to insert (dict)"""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,7 @@ def get_preferred_address(doctype, name, preferred_key="is_primary_address"):
|
||||||
def get_default_address(
|
def get_default_address(
|
||||||
doctype: str, name: str | None, sort_key: str = "is_primary_address"
|
doctype: str, name: str | None, sort_key: str = "is_primary_address"
|
||||||
) -> str | None:
|
) -> str | None:
|
||||||
"""Returns default Address name for the given doctype, name"""
|
"""Return default Address name for the given doctype, name."""
|
||||||
if sort_key not in ["is_shipping_address", "is_primary_address"]:
|
if sort_key not in ["is_shipping_address", "is_primary_address"]:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
@ -228,7 +228,7 @@ def get_address_list(doctype, txt, filters, limit_start, limit_page_length=20, o
|
||||||
|
|
||||||
|
|
||||||
def has_website_permission(doc, ptype, user, verbose=False):
|
def has_website_permission(doc, ptype, user, verbose=False):
|
||||||
"""Returns true if there is a related lead or contact related to this document"""
|
"""Return True if there is a related lead or contact related to this document."""
|
||||||
contact_name = frappe.db.get_value("Contact", {"email_id": frappe.session.user})
|
contact_name = frappe.db.get_value("Contact", {"email_id": frappe.session.user})
|
||||||
|
|
||||||
if contact_name:
|
if contact_name:
|
||||||
|
|
|
||||||
|
|
@ -168,7 +168,7 @@ class Contact(Document):
|
||||||
|
|
||||||
|
|
||||||
def get_default_contact(doctype, name):
|
def get_default_contact(doctype, name):
|
||||||
"""Returns default contact for the given doctype, name"""
|
"""Return default contact for the given doctype, name."""
|
||||||
out = frappe.db.sql(
|
out = frappe.db.sql(
|
||||||
"""select parent,
|
"""select parent,
|
||||||
IFNULL((select is_primary_contact from tabContact c where c.name = dl.parent), 0)
|
IFNULL((select is_primary_contact from tabContact c where c.name = dl.parent), 0)
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,7 @@ def unzip_file(name: str):
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_attached_images(doctype: str, names: list[str] | str) -> frappe._dict:
|
def get_attached_images(doctype: str, names: list[str] | str) -> frappe._dict:
|
||||||
"""get list of image urls attached in form
|
"""Return list of image urls attached in form `{name: ['image.jpg', 'image.png']}`."""
|
||||||
returns {name: ['image.jpg', 'image.png']}"""
|
|
||||||
|
|
||||||
if isinstance(names, str):
|
if isinstance(names, str):
|
||||||
names = json.loads(names)
|
names = json.loads(names)
|
||||||
|
|
|
||||||
|
|
@ -298,7 +298,7 @@ class Communication(Document, CommunicationEmailMixin):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_emails_list(emails=None, exclude_displayname=False):
|
def _get_emails_list(emails=None, exclude_displayname=False):
|
||||||
"""Returns list of emails from given email string.
|
"""Return list of emails from given email string.
|
||||||
|
|
||||||
* Removes duplicate mailids
|
* Removes duplicate mailids
|
||||||
* Removes display name from email address if exclude_displayname is True
|
* Removes display name from email address if exclude_displayname is True
|
||||||
|
|
@ -309,15 +309,15 @@ class Communication(Document, CommunicationEmailMixin):
|
||||||
return [email.lower() for email in set(emails) if email]
|
return [email.lower() for email in set(emails) if email]
|
||||||
|
|
||||||
def to_list(self, exclude_displayname=True):
|
def to_list(self, exclude_displayname=True):
|
||||||
"""Returns to list."""
|
"""Return `to` list."""
|
||||||
return self._get_emails_list(self.recipients, exclude_displayname=exclude_displayname)
|
return self._get_emails_list(self.recipients, exclude_displayname=exclude_displayname)
|
||||||
|
|
||||||
def cc_list(self, exclude_displayname=True):
|
def cc_list(self, exclude_displayname=True):
|
||||||
"""Returns cc list."""
|
"""Return `cc` list."""
|
||||||
return self._get_emails_list(self.cc, exclude_displayname=exclude_displayname)
|
return self._get_emails_list(self.cc, exclude_displayname=exclude_displayname)
|
||||||
|
|
||||||
def bcc_list(self, exclude_displayname=True):
|
def bcc_list(self, exclude_displayname=True):
|
||||||
"""Returns bcc list."""
|
"""Return `bcc` list."""
|
||||||
return self._get_emails_list(self.bcc, exclude_displayname=exclude_displayname)
|
return self._get_emails_list(self.bcc, exclude_displayname=exclude_displayname)
|
||||||
|
|
||||||
def get_attachments(self):
|
def get_attachments(self):
|
||||||
|
|
@ -615,9 +615,9 @@ def parse_email(email_strings):
|
||||||
|
|
||||||
|
|
||||||
def get_email_without_link(email):
|
def get_email_without_link(email):
|
||||||
"""
|
"""Return email address without doctype links.
|
||||||
returns email address without doctype links
|
|
||||||
returns admin@example.com for email admin+doctype+docname@example.com
|
e.g. 'admin@example.com' is returned for email 'admin+doctype+docname@example.com'
|
||||||
"""
|
"""
|
||||||
if not frappe.get_all("Email Account", filters={"enable_automatic_linking": 1}):
|
if not frappe.get_all("Email Account", filters={"enable_automatic_linking": 1}):
|
||||||
return email
|
return email
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ class CommunicationEmailMixin:
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_email_with_displayname(self, email_address):
|
def get_email_with_displayname(self, email_address):
|
||||||
"""Returns email address after adding displayname."""
|
"""Return email address after adding displayname."""
|
||||||
display_name, email = parse_addr(email_address)
|
display_name, email = parse_addr(email_address)
|
||||||
if display_name and display_name != email:
|
if display_name and display_name != email:
|
||||||
return email_address
|
return email_address
|
||||||
|
|
@ -151,7 +151,7 @@ class CommunicationEmailMixin:
|
||||||
return self.content
|
return self.content
|
||||||
|
|
||||||
def get_attach_link(self, print_format):
|
def get_attach_link(self, print_format):
|
||||||
"""Returns public link for the attachment via `templates/emails/print_link.html`."""
|
"""Return public link for the attachment via `templates/emails/print_link.html`."""
|
||||||
return frappe.get_template("templates/emails/print_link.html").render(
|
return frappe.get_template("templates/emails/print_link.html").render(
|
||||||
{
|
{
|
||||||
"url": get_url(),
|
"url": get_url(),
|
||||||
|
|
|
||||||
|
|
@ -514,8 +514,8 @@ class ImportFile:
|
||||||
|
|
||||||
def parse_next_row_for_import(self, data):
|
def parse_next_row_for_import(self, data):
|
||||||
"""
|
"""
|
||||||
Parses rows that make up a doc. A doc maybe built from a single row or multiple rows.
|
Parse rows that make up a doc. A doc maybe built from a single row or multiple rows.
|
||||||
Returns the doc, rows, and data without the rows.
|
Return the doc, rows, and data without the rows.
|
||||||
"""
|
"""
|
||||||
doctypes = self.header.doctypes
|
doctypes = self.header.doctypes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -118,9 +118,10 @@ class DocField(Document):
|
||||||
width: DF.Data | None
|
width: DF.Data | None
|
||||||
# end: auto-generated types
|
# end: auto-generated types
|
||||||
def get_link_doctype(self):
|
def get_link_doctype(self):
|
||||||
"""Returns the Link doctype for the docfield (if applicable)
|
"""Return the Link doctype for the `docfield` (if applicable).
|
||||||
if fieldtype is Link: Returns "options"
|
|
||||||
if fieldtype is Table MultiSelect: Returns "options" of the Link field in the Child Table
|
* If fieldtype is Link: Return "options".
|
||||||
|
* If fieldtype is Table MultiSelect: Return "options" of the Link field in the Child Table.
|
||||||
"""
|
"""
|
||||||
if self.fieldtype == "Link":
|
if self.fieldtype == "Link":
|
||||||
return self.options
|
return self.options
|
||||||
|
|
|
||||||
|
|
@ -986,7 +986,7 @@ class DocType(Document):
|
||||||
add_column(self.name, "parentfield", "Data")
|
add_column(self.name, "parentfield", "Data")
|
||||||
|
|
||||||
def get_max_idx(self):
|
def get_max_idx(self):
|
||||||
"""Returns the highest `idx`"""
|
"""Return the highest `idx`."""
|
||||||
max_idx = frappe.db.sql("""select max(idx) from `tabDocField` where parent = %s""", self.name)
|
max_idx = frappe.db.sql("""select max(idx) from `tabDocField` where parent = %s""", self.name)
|
||||||
return max_idx and max_idx[0][0] or 0
|
return max_idx and max_idx[0][0] or 0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -544,7 +544,7 @@ class File(Document):
|
||||||
return self._content
|
return self._content
|
||||||
|
|
||||||
def get_full_path(self):
|
def get_full_path(self):
|
||||||
"""Returns file path from given file name"""
|
"""Return file path using the set file name."""
|
||||||
|
|
||||||
file_path = self.file_url or self.file_name
|
file_path = self.file_url or self.file_name
|
||||||
|
|
||||||
|
|
@ -705,7 +705,7 @@ class File(Document):
|
||||||
return has_permission(self, "read")
|
return has_permission(self, "read")
|
||||||
|
|
||||||
def get_extension(self):
|
def get_extension(self):
|
||||||
"""returns split filename and extension"""
|
"""Split and return filename and extension for the set `file_name`."""
|
||||||
return os.path.splitext(self.file_name)
|
return os.path.splitext(self.file_name)
|
||||||
|
|
||||||
def create_attachment_record(self):
|
def create_attachment_record(self):
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@ class Page(Document):
|
||||||
shutil.rmtree(dir_path, ignore_errors=True)
|
shutil.rmtree(dir_path, ignore_errors=True)
|
||||||
|
|
||||||
def is_permitted(self):
|
def is_permitted(self):
|
||||||
"""Returns true if Has Role is not set or the user is allowed."""
|
"""Return True if `Has Role` is not set or the user is allowed."""
|
||||||
from frappe.utils import has_common
|
from frappe.utils import has_common
|
||||||
|
|
||||||
allowed = [
|
allowed = [
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ class Report(Document):
|
||||||
self.set("roles", roles)
|
self.set("roles", roles)
|
||||||
|
|
||||||
def is_permitted(self):
|
def is_permitted(self):
|
||||||
"""Returns true if Has Role is not set or the user is allowed."""
|
"""Return True if `Has Role` is not set or the user is allowed."""
|
||||||
from frappe.utils import has_common
|
from frappe.utils import has_common
|
||||||
|
|
||||||
allowed = [
|
allowed = [
|
||||||
|
|
|
||||||
|
|
@ -128,14 +128,14 @@ class ServerScript(Document):
|
||||||
frappe.msgprint(str(e), title=_("Compilation warning"))
|
frappe.msgprint(str(e), title=_("Compilation warning"))
|
||||||
|
|
||||||
def execute_method(self) -> dict:
|
def execute_method(self) -> dict:
|
||||||
"""Specific to API endpoint Server Scripts
|
"""Specific to API endpoint Server Scripts.
|
||||||
|
|
||||||
Raises:
|
Raise:
|
||||||
frappe.DoesNotExistError: If self.script_type is not API
|
frappe.DoesNotExistError: If self.script_type is not API.
|
||||||
frappe.PermissionError: If self.allow_guest is unset for API accessed by Guest user
|
frappe.PermissionError: If self.allow_guest is unset for API accessed by Guest user.
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
dict: Evaluates self.script with frappe.utils.safe_exec.safe_exec and returns the flags set in it's safe globals
|
dict: Evaluate self.script with frappe.utils.safe_exec.safe_exec and return the flags set in it's safe globals.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if self.enable_rate_limit:
|
if self.enable_rate_limit:
|
||||||
|
|
@ -174,13 +174,13 @@ class ServerScript(Document):
|
||||||
safe_exec(self.script, script_filename=self.name)
|
safe_exec(self.script, script_filename=self.name)
|
||||||
|
|
||||||
def get_permission_query_conditions(self, user: str) -> list[str]:
|
def get_permission_query_conditions(self, user: str) -> list[str]:
|
||||||
"""Specific to Permission Query Server Scripts
|
"""Specific to Permission Query Server Scripts.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
user (str): Takes user email to execute script and return list of conditions
|
user (str): Take user email to execute script and return list of conditions.
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
list: Returns list of conditions defined by rules in self.script
|
list: Return list of conditions defined by rules in self.script.
|
||||||
"""
|
"""
|
||||||
locals = {"user": user, "conditions": ""}
|
locals = {"user": user, "conditions": ""}
|
||||||
safe_exec(self.script, None, locals, script_filename=self.name)
|
safe_exec(self.script, None, locals, script_filename=self.name)
|
||||||
|
|
@ -189,12 +189,10 @@ class ServerScript(Document):
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_autocompletion_items(self):
|
def get_autocompletion_items(self):
|
||||||
"""Generates a list of a autocompletion strings from the context dict
|
"""Generate a list of autocompletion strings from the context dict
|
||||||
that is used while executing a Server Script.
|
that is used while executing a Server Script.
|
||||||
|
|
||||||
Returns:
|
e.g., ["frappe.utils.cint", "frappe.get_all", ...]
|
||||||
list: Returns list of autocompletion items.
|
|
||||||
For e.g., ["frappe.utils.cint", "frappe.get_all", ...]
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def get_keys(obj):
|
def get_keys(obj):
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ def validate_receiver_nos(receiver_list):
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_contact_number(contact_name, ref_doctype, ref_name):
|
def get_contact_number(contact_name, ref_doctype, ref_name):
|
||||||
"returns mobile number of the contact"
|
"Return mobile number of the given contact."
|
||||||
number = frappe.db.sql(
|
number = frappe.db.sql(
|
||||||
"""select mobile_no, phone from tabContact
|
"""select mobile_no, phone from tabContact
|
||||||
where name=%s
|
where name=%s
|
||||||
|
|
|
||||||
|
|
@ -230,7 +230,7 @@ class User(Document):
|
||||||
frappe.cache.delete_key("users_for_mentions")
|
frappe.cache.delete_key("users_for_mentions")
|
||||||
|
|
||||||
def has_website_permission(self, ptype, user, verbose=False):
|
def has_website_permission(self, ptype, user, verbose=False):
|
||||||
"""Returns true if current user is the session user"""
|
"""Return True if current user is the session user."""
|
||||||
return self.name == frappe.session.user
|
return self.name == frappe.session.user
|
||||||
|
|
||||||
def set_full_name(self):
|
def set_full_name(self):
|
||||||
|
|
@ -686,7 +686,7 @@ class User(Document):
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_blocked_modules(self):
|
def get_blocked_modules(self):
|
||||||
"""Returns list of modules blocked for that user"""
|
"""Return list of modules blocked for that user."""
|
||||||
return [d.module for d in self.block_modules] if self.block_modules else []
|
return [d.module for d in self.block_modules] if self.block_modules else []
|
||||||
|
|
||||||
def validate_user_email_inbox(self):
|
def validate_user_email_inbox(self):
|
||||||
|
|
@ -1083,7 +1083,7 @@ def user_query(doctype, txt, searchfield, start, page_len, filters):
|
||||||
|
|
||||||
|
|
||||||
def get_total_users():
|
def get_total_users():
|
||||||
"""Returns total no. of system users"""
|
"""Return total no. of system users."""
|
||||||
return flt(
|
return flt(
|
||||||
frappe.db.sql(
|
frappe.db.sql(
|
||||||
"""SELECT SUM(`simultaneous_sessions`)
|
"""SELECT SUM(`simultaneous_sessions`)
|
||||||
|
|
@ -1118,7 +1118,7 @@ def get_system_users(exclude_users: Iterable[str] | str | None = None, limit: in
|
||||||
|
|
||||||
|
|
||||||
def get_active_users():
|
def get_active_users():
|
||||||
"""Returns No. of system users who logged in, in the last 3 days"""
|
"""Return number of system users who logged in, in the last 3 days."""
|
||||||
return frappe.db.sql(
|
return frappe.db.sql(
|
||||||
"""select count(*) from `tabUser`
|
"""select count(*) from `tabUser`
|
||||||
where enabled = 1 and user_type != 'Website User'
|
where enabled = 1 and user_type != 'Website User'
|
||||||
|
|
@ -1131,12 +1131,12 @@ def get_active_users():
|
||||||
|
|
||||||
|
|
||||||
def get_website_users():
|
def get_website_users():
|
||||||
"""Returns total no. of website users"""
|
"""Return total no. of website users."""
|
||||||
return frappe.db.count("User", filters={"enabled": True, "user_type": "Website User"})
|
return frappe.db.count("User", filters={"enabled": True, "user_type": "Website User"})
|
||||||
|
|
||||||
|
|
||||||
def get_active_website_users():
|
def get_active_website_users():
|
||||||
"""Returns No. of website users who logged in, in the last 3 days"""
|
"""Return number of website users who logged in, in the last 3 days."""
|
||||||
return frappe.db.sql(
|
return frappe.db.sql(
|
||||||
"""select count(*) from `tabUser`
|
"""select count(*) from `tabUser`
|
||||||
where enabled = 1 and user_type = 'Website User'
|
where enabled = 1 and user_type = 'Website User'
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,7 @@ def get_applicable_for_doctype_list(doctype, txt, searchfield, start, page_len,
|
||||||
|
|
||||||
|
|
||||||
def get_permitted_documents(doctype):
|
def get_permitted_documents(doctype):
|
||||||
"""Returns permitted documents from the given doctype for the session user"""
|
"""Return permitted documents from the given doctype for the session user."""
|
||||||
# sort permissions in a way to make the first permission in the list to be default
|
# sort permissions in a way to make the first permission in the list to be default
|
||||||
user_perm_list = sorted(
|
user_perm_list = sorted(
|
||||||
get_user_permissions().get(doctype, []), key=lambda x: x.get("is_default"), reverse=True
|
get_user_permissions().get(doctype, []), key=lambda x: x.get("is_default"), reverse=True
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ def get_notification_config():
|
||||||
|
|
||||||
|
|
||||||
def get_things_todo(as_list=False):
|
def get_things_todo(as_list=False):
|
||||||
"""Returns a count of incomplete todos"""
|
"""Return a count of incomplete ToDos."""
|
||||||
data = frappe.get_list(
|
data = frappe.get_list(
|
||||||
"ToDo",
|
"ToDo",
|
||||||
fields=["name", "description"] if as_list else "count(*)",
|
fields=["name", "description"] if as_list else "count(*)",
|
||||||
|
|
@ -35,7 +35,7 @@ def get_things_todo(as_list=False):
|
||||||
|
|
||||||
|
|
||||||
def get_todays_events(as_list: bool = False):
|
def get_todays_events(as_list: bool = False):
|
||||||
"""Returns a count of todays events in calendar"""
|
"""Return a count of today's events in calendar."""
|
||||||
from frappe.desk.doctype.event.event import get_events
|
from frappe.desk.doctype.event.event import get_events
|
||||||
from frappe.utils import nowdate
|
from frappe.utils import nowdate
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -109,8 +109,10 @@ def add(parent, role, permlevel):
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def update(doctype, role, permlevel, ptype, value=None, if_owner=0):
|
def update(
|
||||||
"""Update role permission params
|
doctype: str, role: str, permlevel: int, ptype: str, value=None, if_owner=0
|
||||||
|
) -> str | None:
|
||||||
|
"""Update role permission params.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
doctype (str): Name of the DocType to update params for
|
doctype (str): Name of the DocType to update params for
|
||||||
|
|
@ -119,8 +121,8 @@ def update(doctype, role, permlevel, ptype, value=None, if_owner=0):
|
||||||
ptype (str): permission type, example "read", "delete", etc.
|
ptype (str): permission type, example "read", "delete", etc.
|
||||||
value (None, optional): value for ptype, None indicates False
|
value (None, optional): value for ptype, None indicates False
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
str: Refresh flag is permission is updated successfully
|
str: Refresh flag if permission is updated successfully
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def clear_cache():
|
def clear_cache():
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import frappe
|
||||||
|
|
||||||
|
|
||||||
def get_parent_doc(doc):
|
def get_parent_doc(doc):
|
||||||
"""Returns document of `reference_doctype`, `reference_doctype`"""
|
"""Return document of `reference_doctype`, `reference_doctype`."""
|
||||||
if not hasattr(doc, "parent_doc"):
|
if not hasattr(doc, "parent_doc"):
|
||||||
if doc.reference_doctype and doc.reference_name:
|
if doc.reference_doctype and doc.reference_name:
|
||||||
doc.parent_doc = frappe.get_doc(doc.reference_doctype, doc.reference_name)
|
doc.parent_doc = frappe.get_doc(doc.reference_doctype, doc.reference_name)
|
||||||
|
|
@ -38,8 +38,7 @@ def set_timeline_doc(doc):
|
||||||
|
|
||||||
|
|
||||||
def find(list_of_dict, match_function):
|
def find(list_of_dict, match_function):
|
||||||
"""Returns a dict in a list of dicts on matching the conditions
|
"""Return a dict in a list of dicts on matching the conditions provided in match function.
|
||||||
provided in match function
|
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
list_of_dict = [{'name': 'Suraj'}, {'name': 'Aditya'}]
|
list_of_dict = [{'name': 'Suraj'}, {'name': 'Aditya'}]
|
||||||
|
|
@ -54,8 +53,7 @@ def find(list_of_dict, match_function):
|
||||||
|
|
||||||
|
|
||||||
def find_all(list_of_dict, match_function):
|
def find_all(list_of_dict, match_function):
|
||||||
"""Returns all matching dicts in a list of dicts.
|
"""Return all matching dicts in a list of dicts. Uses matching function to filter out the dicts.
|
||||||
Uses matching function to filter out the dicts
|
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
colored_shapes = [
|
colored_shapes = [
|
||||||
|
|
@ -87,6 +85,6 @@ def ljust_list(_list, length, fill_word=None):
|
||||||
|
|
||||||
|
|
||||||
def html2text(html: str, strip_links=False, wrap=True) -> str:
|
def html2text(html: str, strip_links=False, wrap=True) -> str:
|
||||||
"""Returns the given `html` as markdown text."""
|
"""Return the given `html` as markdown text."""
|
||||||
strip = ["a"] if strip_links else None
|
strip = ["a"] if strip_links else None
|
||||||
return md(html, heading_style="ATX", strip=strip, wrap=wrap)
|
return md(html, heading_style="ATX", strip=strip, wrap=wrap)
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ class Database:
|
||||||
self._conn.select_db(db_name)
|
self._conn.select_db(db_name)
|
||||||
|
|
||||||
def get_connection(self):
|
def get_connection(self):
|
||||||
"""Returns a Database connection object that conforms with https://peps.python.org/pep-0249/#connection-objects"""
|
"""Return a Database connection object that conforms with https://peps.python.org/pep-0249/#connection-objects."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def get_database_size(self):
|
def get_database_size(self):
|
||||||
|
|
@ -160,7 +160,7 @@ class Database:
|
||||||
:param ignore_ddl: Catch exception if table, column missing.
|
:param ignore_ddl: Catch exception if table, column missing.
|
||||||
:param auto_commit: Commit after executing the query.
|
:param auto_commit: Commit after executing the query.
|
||||||
:param update: Update this dict to all rows (if returned `as_dict`).
|
:param update: Update this dict to all rows (if returned `as_dict`).
|
||||||
:param run: Returns query without executing it if False.
|
:param run: Return query without executing it if False.
|
||||||
:param pluck: Get the plucked field only.
|
:param pluck: Get the plucked field only.
|
||||||
:param explain: Print `EXPLAIN` in error log.
|
:param explain: Print `EXPLAIN` in error log.
|
||||||
Examples:
|
Examples:
|
||||||
|
|
@ -397,7 +397,7 @@ class Database:
|
||||||
raise ImplicitCommitError("This statement can cause implicit commit", query)
|
raise ImplicitCommitError("This statement can cause implicit commit", query)
|
||||||
|
|
||||||
def fetch_as_dict(self) -> list[frappe._dict]:
|
def fetch_as_dict(self) -> list[frappe._dict]:
|
||||||
"""Internal. Converts results to dict."""
|
"""Internal. Convert results to dict."""
|
||||||
result = self.last_result
|
result = self.last_result
|
||||||
if result:
|
if result:
|
||||||
keys = [column[0] for column in self._cursor.description]
|
keys = [column[0] for column in self._cursor.description]
|
||||||
|
|
@ -410,7 +410,7 @@ class Database:
|
||||||
frappe.cache.delete_key("db_tables")
|
frappe.cache.delete_key("db_tables")
|
||||||
|
|
||||||
def get_description(self):
|
def get_description(self):
|
||||||
"""Returns result metadata."""
|
"""Return result metadata."""
|
||||||
return self._cursor.description
|
return self._cursor.description
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
@ -419,7 +419,7 @@ class Database:
|
||||||
return [[value for value in row] for row in res]
|
return [[value for value in row] for row in res]
|
||||||
|
|
||||||
def get(self, doctype, filters=None, as_dict=True, cache=False):
|
def get(self, doctype, filters=None, as_dict=True, cache=False):
|
||||||
"""Returns `get_value` with fieldname='*'"""
|
"""Return `get_value` with fieldname='*'."""
|
||||||
return self.get_value(doctype, filters, "*", as_dict=as_dict, cache=cache)
|
return self.get_value(doctype, filters, "*", as_dict=as_dict, cache=cache)
|
||||||
|
|
||||||
def get_value(
|
def get_value(
|
||||||
|
|
@ -438,7 +438,7 @@ class Database:
|
||||||
pluck=False,
|
pluck=False,
|
||||||
distinct=False,
|
distinct=False,
|
||||||
):
|
):
|
||||||
"""Returns a document property or list of properties.
|
"""Return a document property or list of properties.
|
||||||
|
|
||||||
:param doctype: DocType name.
|
:param doctype: DocType name.
|
||||||
:param filters: Filters like `{"x":"y"}` or name of the document. `None` if Single DocType.
|
:param filters: Filters like `{"x":"y"}` or name of the document. `None` if Single DocType.
|
||||||
|
|
@ -510,7 +510,7 @@ class Database:
|
||||||
distinct=False,
|
distinct=False,
|
||||||
limit=None,
|
limit=None,
|
||||||
):
|
):
|
||||||
"""Returns multiple document properties.
|
"""Return multiple document properties.
|
||||||
|
|
||||||
:param doctype: DocType name.
|
:param doctype: DocType name.
|
||||||
:param filters: Filters like `{"x":"y"}` or name of the document.
|
:param filters: Filters like `{"x":"y"}` or name of the document.
|
||||||
|
|
@ -926,11 +926,11 @@ class Database:
|
||||||
self.set_default(key, val, user)
|
self.set_default(key, val, user)
|
||||||
|
|
||||||
def get_global(self, key, user="__global"):
|
def get_global(self, key, user="__global"):
|
||||||
"""Returns a global key value."""
|
"""Return a global key value."""
|
||||||
return self.get_default(key, user)
|
return self.get_default(key, user)
|
||||||
|
|
||||||
def get_default(self, key, parent="__default"):
|
def get_default(self, key, parent="__default"):
|
||||||
"""Returns default value as a list if multiple or single"""
|
"""Return default value as a list if multiple or single."""
|
||||||
d = self.get_defaults(key, parent)
|
d = self.get_defaults(key, parent)
|
||||||
return isinstance(d, list) and d[0] or d
|
return isinstance(d, list) and d[0] or d
|
||||||
|
|
||||||
|
|
@ -1006,7 +1006,7 @@ class Database:
|
||||||
return self.exists("DocField", {"fieldname": fn, "parent": dt})
|
return self.exists("DocField", {"fieldname": fn, "parent": dt})
|
||||||
|
|
||||||
def table_exists(self, doctype, cached=True):
|
def table_exists(self, doctype, cached=True):
|
||||||
"""Returns True if table for given doctype exists."""
|
"""Return True if table for given doctype exists."""
|
||||||
return f"tab{doctype}" in self.get_tables(cached=cached)
|
return f"tab{doctype}" in self.get_tables(cached=cached)
|
||||||
|
|
||||||
def has_table(self, doctype):
|
def has_table(self, doctype):
|
||||||
|
|
@ -1016,7 +1016,7 @@ class Database:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def a_row_exists(self, doctype):
|
def a_row_exists(self, doctype):
|
||||||
"""Returns True if atleast one row exists."""
|
"""Return True if at least one row exists."""
|
||||||
return frappe.get_all(doctype, limit=1, order_by=None, as_list=True)
|
return frappe.get_all(doctype, limit=1, order_by=None, as_list=True)
|
||||||
|
|
||||||
def exists(self, dt, dn=None, cache=False):
|
def exists(self, dt, dn=None, cache=False):
|
||||||
|
|
@ -1055,7 +1055,7 @@ class Database:
|
||||||
return self.get_value(dt, dn, ignore=True, cache=cache, order_by=None)
|
return self.get_value(dt, dn, ignore=True, cache=cache, order_by=None)
|
||||||
|
|
||||||
def count(self, dt, filters=None, debug=False, cache=False, distinct: bool = True):
|
def count(self, dt, filters=None, debug=False, cache=False, distinct: bool = True):
|
||||||
"""Returns `COUNT(*)` for given DocType and filters."""
|
"""Return `COUNT(*)` for given DocType and filters."""
|
||||||
if cache and not filters:
|
if cache and not filters:
|
||||||
cache_count = frappe.cache.get_value(f"doctype:count:{dt}")
|
cache_count = frappe.cache.get_value(f"doctype:count:{dt}")
|
||||||
if cache_count is not None:
|
if cache_count is not None:
|
||||||
|
|
@ -1098,7 +1098,7 @@ class Database:
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_db_table_columns(self, table) -> list[str]:
|
def get_db_table_columns(self, table) -> list[str]:
|
||||||
"""Returns list of column names from given table."""
|
"""Return list of column names from given table."""
|
||||||
columns = frappe.cache.hget("table_columns", table)
|
columns = frappe.cache.hget("table_columns", table)
|
||||||
if columns is None:
|
if columns is None:
|
||||||
information_schema = frappe.qb.Schema("information_schema")
|
information_schema = frappe.qb.Schema("information_schema")
|
||||||
|
|
@ -1116,14 +1116,14 @@ class Database:
|
||||||
return columns
|
return columns
|
||||||
|
|
||||||
def get_table_columns(self, doctype):
|
def get_table_columns(self, doctype):
|
||||||
"""Returns list of column names from given doctype."""
|
"""Return list of column names from given doctype."""
|
||||||
columns = self.get_db_table_columns("tab" + doctype)
|
columns = self.get_db_table_columns("tab" + doctype)
|
||||||
if not columns:
|
if not columns:
|
||||||
raise self.TableMissingError("DocType", doctype)
|
raise self.TableMissingError("DocType", doctype)
|
||||||
return columns
|
return columns
|
||||||
|
|
||||||
def has_column(self, doctype, column):
|
def has_column(self, doctype, column):
|
||||||
"""Returns True if column exists in database."""
|
"""Return True if column exists in database."""
|
||||||
return column in self.get_table_columns(doctype)
|
return column in self.get_table_columns(doctype)
|
||||||
|
|
||||||
def has_index(self, table_name, index_name):
|
def has_index(self, table_name, index_name):
|
||||||
|
|
|
||||||
|
|
@ -191,7 +191,7 @@ class MariaDBDatabase(MariaDBConnectionUtil, MariaDBExceptionUtil, Database):
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_database_size(self):
|
def get_database_size(self):
|
||||||
"""'Returns database size in MB"""
|
"""Return database size in MB."""
|
||||||
db_size = self.sql(
|
db_size = self.sql(
|
||||||
"""
|
"""
|
||||||
SELECT `table_schema` as `database_name`,
|
SELECT `table_schema` as `database_name`,
|
||||||
|
|
@ -314,7 +314,7 @@ class MariaDBDatabase(MariaDBConnectionUtil, MariaDBExceptionUtil, Database):
|
||||||
return "ON DUPLICATE key UPDATE "
|
return "ON DUPLICATE key UPDATE "
|
||||||
|
|
||||||
def get_table_columns_description(self, table_name):
|
def get_table_columns_description(self, table_name):
|
||||||
"""Returns list of column and its description"""
|
"""Return list of columns with descriptions."""
|
||||||
return self.sql(
|
return self.sql(
|
||||||
"""select
|
"""select
|
||||||
column_name as 'name',
|
column_name as 'name',
|
||||||
|
|
@ -339,7 +339,7 @@ class MariaDBDatabase(MariaDBConnectionUtil, MariaDBExceptionUtil, Database):
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_column_type(self, doctype, column):
|
def get_column_type(self, doctype, column):
|
||||||
"""Returns column type from database."""
|
"""Return column type from database."""
|
||||||
information_schema = frappe.qb.Schema("information_schema")
|
information_schema = frappe.qb.Schema("information_schema")
|
||||||
table = get_table_name(doctype)
|
table = get_table_name(doctype)
|
||||||
|
|
||||||
|
|
@ -446,7 +446,7 @@ class MariaDBDatabase(MariaDBConnectionUtil, MariaDBExceptionUtil, Database):
|
||||||
return self.sql("SHOW DATABASES", pluck=True)
|
return self.sql("SHOW DATABASES", pluck=True)
|
||||||
|
|
||||||
def get_tables(self, cached=True):
|
def get_tables(self, cached=True):
|
||||||
"""Returns list of tables"""
|
"""Return list of tables."""
|
||||||
to_query = not cached
|
to_query = not cached
|
||||||
|
|
||||||
if cached:
|
if cached:
|
||||||
|
|
|
||||||
|
|
@ -17,20 +17,20 @@ def like(key: Field, value: str) -> frappe.qb:
|
||||||
key (str): field
|
key (str): field
|
||||||
value (str): criterion
|
value (str): criterion
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
frappe.qb: `frappe.qb object with `LIKE`
|
frappe.qb: `frappe.qb object with `LIKE`
|
||||||
"""
|
"""
|
||||||
return key.like(value)
|
return key.like(value)
|
||||||
|
|
||||||
|
|
||||||
def func_in(key: Field, value: list | tuple) -> frappe.qb:
|
def func_in(key: Field, value: list | tuple) -> frappe.qb:
|
||||||
"""Wrapper method for `IN`
|
"""Wrapper method for `IN`.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key (str): field
|
key (str): field
|
||||||
value (Union[int, str]): criterion
|
value (Union[int, str]): criterion
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
frappe.qb: `frappe.qb object with `IN`
|
frappe.qb: `frappe.qb object with `IN`
|
||||||
"""
|
"""
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
|
|
@ -39,26 +39,26 @@ def func_in(key: Field, value: list | tuple) -> frappe.qb:
|
||||||
|
|
||||||
|
|
||||||
def not_like(key: Field, value: str) -> frappe.qb:
|
def not_like(key: Field, value: str) -> frappe.qb:
|
||||||
"""Wrapper method for `NOT LIKE`
|
"""Wrapper method for `NOT LIKE`.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key (str): field
|
key (str): field
|
||||||
value (str): criterion
|
value (str): criterion
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
frappe.qb: `frappe.qb object with `NOT LIKE`
|
frappe.qb: `frappe.qb object with `NOT LIKE`
|
||||||
"""
|
"""
|
||||||
return key.not_like(value)
|
return key.not_like(value)
|
||||||
|
|
||||||
|
|
||||||
def func_not_in(key: Field, value: list | tuple | str):
|
def func_not_in(key: Field, value: list | tuple | str):
|
||||||
"""Wrapper method for `NOT IN`
|
"""Wrapper method for `NOT IN`.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key (str): field
|
key (str): field
|
||||||
value (Union[int, str]): criterion
|
value (Union[int, str]): criterion
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
frappe.qb: `frappe.qb object with `NOT IN`
|
frappe.qb: `frappe.qb object with `NOT IN`
|
||||||
"""
|
"""
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
|
|
@ -73,20 +73,20 @@ def func_regex(key: Field, value: str) -> frappe.qb:
|
||||||
key (str): field
|
key (str): field
|
||||||
value (str): criterion
|
value (str): criterion
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
frappe.qb: `frappe.qb object with `REGEX`
|
frappe.qb: `frappe.qb object with `REGEX`
|
||||||
"""
|
"""
|
||||||
return key.regex(value)
|
return key.regex(value)
|
||||||
|
|
||||||
|
|
||||||
def func_between(key: Field, value: list | tuple) -> frappe.qb:
|
def func_between(key: Field, value: list | tuple) -> frappe.qb:
|
||||||
"""Wrapper method for `BETWEEN`
|
"""Wrapper method for `BETWEEN`.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key (str): field
|
key (str): field
|
||||||
value (Union[int, str]): criterion
|
value (Union[int, str]): criterion
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
frappe.qb: `frappe.qb object with `BETWEEN`
|
frappe.qb: `frappe.qb object with `BETWEEN`
|
||||||
"""
|
"""
|
||||||
return key[slice(*value)]
|
return key[slice(*value)]
|
||||||
|
|
@ -98,13 +98,13 @@ def func_is(key, value):
|
||||||
|
|
||||||
|
|
||||||
def func_timespan(key: Field, value: str) -> frappe.qb:
|
def func_timespan(key: Field, value: str) -> frappe.qb:
|
||||||
"""Wrapper method for `TIMESPAN`
|
"""Wrapper method for `TIMESPAN`.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key (str): field
|
key (str): field
|
||||||
value (str): criterion
|
value (str): criterion
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
frappe.qb: `frappe.qb object with `TIMESPAN`
|
frappe.qb: `frappe.qb object with `TIMESPAN`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -197,7 +197,7 @@ class PostgresDatabase(PostgresExceptionUtil, Database):
|
||||||
return str(psycopg2.extensions.QuotedString(s))
|
return str(psycopg2.extensions.QuotedString(s))
|
||||||
|
|
||||||
def get_database_size(self):
|
def get_database_size(self):
|
||||||
"""'Returns database size in MB"""
|
"""Return database size in MB"""
|
||||||
db_size = self.sql(
|
db_size = self.sql(
|
||||||
"SELECT (pg_database_size(%s) / 1024 / 1024) as database_size", self.db_name, as_dict=True
|
"SELECT (pg_database_size(%s) / 1024 / 1024) as database_size", self.db_name, as_dict=True
|
||||||
)
|
)
|
||||||
|
|
@ -380,7 +380,7 @@ class PostgresDatabase(PostgresExceptionUtil, Database):
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_table_columns_description(self, table_name):
|
def get_table_columns_description(self, table_name):
|
||||||
"""Returns list of column and its description"""
|
"""Return list of columns with description."""
|
||||||
# pylint: disable=W1401
|
# pylint: disable=W1401
|
||||||
return self.sql(
|
return self.sql(
|
||||||
"""
|
"""
|
||||||
|
|
@ -411,7 +411,7 @@ class PostgresDatabase(PostgresExceptionUtil, Database):
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_column_type(self, doctype, column):
|
def get_column_type(self, doctype, column):
|
||||||
"""Returns column type from database."""
|
"""Return column type from database."""
|
||||||
information_schema = frappe.qb.Schema("information_schema")
|
information_schema = frappe.qb.Schema("information_schema")
|
||||||
table = get_table_name(doctype)
|
table = get_table_name(doctype)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -218,7 +218,7 @@ class Engine:
|
||||||
self.query = self.query.where(operator_fn(_field, _value))
|
self.query = self.query.where(operator_fn(_field, _value))
|
||||||
|
|
||||||
def get_function_object(self, field: str) -> "Function":
|
def get_function_object(self, field: str) -> "Function":
|
||||||
"""Expects field to look like 'SUM(*)' or 'name' or something similar. Returns PyPika Function object"""
|
"""Return PyPika Function object. Expect field to look like 'SUM(*)' or 'name' or something similar."""
|
||||||
func = field.split("(", maxsplit=1)[0].capitalize()
|
func = field.split("(", maxsplit=1)[0].capitalize()
|
||||||
args_start, args_end = len(func) + 1, field.index(")")
|
args_start, args_end = len(func) + 1, field.index(")")
|
||||||
args = field[args_start:args_end].split(",")
|
args = field[args_start:args_end].split(",")
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ def is_a_user_permission_key(key):
|
||||||
|
|
||||||
|
|
||||||
def not_in_user_permission(key, value, user=None):
|
def not_in_user_permission(key, value, user=None):
|
||||||
# returns true or false based on if value exist in user permission
|
# return true or false based on if value exist in user permission
|
||||||
user = user or frappe.session.user
|
user = user or frappe.session.user
|
||||||
user_permission = get_user_permissions(user).get(frappe.unscrub(key)) or []
|
user_permission = get_user_permissions(user).get(frappe.unscrub(key)) or []
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ def update_event(args, field_map):
|
||||||
|
|
||||||
|
|
||||||
def get_event_conditions(doctype, filters=None):
|
def get_event_conditions(doctype, filters=None):
|
||||||
"""Returns SQL conditions with user permissions and filters for event queries"""
|
"""Return SQL conditions with user permissions and filters for event queries."""
|
||||||
from frappe.desk.reportview import get_filters_cond
|
from frappe.desk.reportview import get_filters_cond
|
||||||
|
|
||||||
if not frappe.has_permission(doctype):
|
if not frappe.has_permission(doctype):
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ class Workspace:
|
||||||
)
|
)
|
||||||
|
|
||||||
def is_permitted(self):
|
def is_permitted(self):
|
||||||
"""Returns true if Has Role is not set or the user is allowed."""
|
"""Return true if `Has Role` is not set or the user is allowed."""
|
||||||
from frappe.utils import has_common
|
from frappe.utils import has_common
|
||||||
|
|
||||||
allowed = [d.role for d in self.doc.roles]
|
allowed = [d.role for d in self.doc.roles]
|
||||||
|
|
@ -383,13 +383,12 @@ class Workspace:
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
@frappe.read_only()
|
@frappe.read_only()
|
||||||
def get_desktop_page(page):
|
def get_desktop_page(page):
|
||||||
"""Applies permissions, customizations and returns the configruration for a page
|
"""Apply permissions, customizations and return the configuration for a page on desk.
|
||||||
on desk.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
page (json): page data
|
page (json): page data
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
dict: dictionary of cards, charts and shortcuts to be displayed on website
|
dict: dictionary of cards, charts and shortcuts to be displayed on website
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
|
@ -503,7 +502,7 @@ def get_custom_doctype_list(module):
|
||||||
|
|
||||||
|
|
||||||
def get_custom_report_list(module):
|
def get_custom_report_list(module):
|
||||||
"""Returns list on new style reports for modules."""
|
"""Return list on new style reports for modules."""
|
||||||
reports = frappe.get_all(
|
reports = frappe.get_all(
|
||||||
"Report",
|
"Report",
|
||||||
fields=["name", "ref_doctype", "report_type"],
|
fields=["name", "ref_doctype", "report_type"],
|
||||||
|
|
@ -617,14 +616,14 @@ def new_widget(config, doctype, parentfield):
|
||||||
|
|
||||||
|
|
||||||
def prepare_widget(config, doctype, parentfield):
|
def prepare_widget(config, doctype, parentfield):
|
||||||
"""Create widget child table entries with parent details
|
"""Create widget child table entries with parent details.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
config (dict): Dictionary containing widget config
|
config (dict): Dictionary containing widget config
|
||||||
doctype (string): Doctype name of the child table
|
doctype (string): Doctype name of the child table
|
||||||
parentfield (string): Parent field for the child table
|
parentfield (string): Parent field for the child table
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
TYPE: List of Document objects
|
TYPE: List of Document objects
|
||||||
"""
|
"""
|
||||||
if not config:
|
if not config:
|
||||||
|
|
|
||||||
|
|
@ -77,15 +77,15 @@ class DocTags:
|
||||||
self.dt = dt
|
self.dt = dt
|
||||||
|
|
||||||
def get_tag_fields(self):
|
def get_tag_fields(self):
|
||||||
"""returns tag_fields property"""
|
"""Return `tag_fields` property."""
|
||||||
return frappe.db.get_value("DocType", self.dt, "tag_fields")
|
return frappe.db.get_value("DocType", self.dt, "tag_fields")
|
||||||
|
|
||||||
def get_tags(self, dn):
|
def get_tags(self, dn):
|
||||||
"""returns tag for a particular item"""
|
"""Return tag for a particular item."""
|
||||||
return (frappe.db.get_value(self.dt, dn, "_user_tags", ignore=1) or "").strip()
|
return (frappe.db.get_value(self.dt, dn, "_user_tags", ignore=1) or "").strip()
|
||||||
|
|
||||||
def add(self, dn, tag):
|
def add(self, dn, tag):
|
||||||
"""add a new user tag"""
|
"""Add a new user tag."""
|
||||||
tl = self.get_tags(dn).split(",")
|
tl = self.get_tags(dn).split(",")
|
||||||
if tag not in tl:
|
if tag not in tl:
|
||||||
tl.append(tag)
|
tl.append(tag)
|
||||||
|
|
@ -94,16 +94,16 @@ class DocTags:
|
||||||
self.update(dn, tl)
|
self.update(dn, tl)
|
||||||
|
|
||||||
def remove(self, dn, tag):
|
def remove(self, dn, tag):
|
||||||
"""remove a user tag"""
|
"""Remove a user tag."""
|
||||||
tl = self.get_tags(dn).split(",")
|
tl = self.get_tags(dn).split(",")
|
||||||
self.update(dn, filter(lambda x: x.lower() != tag.lower(), tl))
|
self.update(dn, filter(lambda x: x.lower() != tag.lower(), tl))
|
||||||
|
|
||||||
def remove_all(self, dn):
|
def remove_all(self, dn):
|
||||||
"""remove all user tags (call before delete)"""
|
"""Remove all user tags (call before delete)."""
|
||||||
self.update(dn, [])
|
self.update(dn, [])
|
||||||
|
|
||||||
def update(self, dn, tl):
|
def update(self, dn, tl):
|
||||||
"""updates the _user_tag column in the table"""
|
"""Update the `_user_tag` column in the table."""
|
||||||
|
|
||||||
if not tl:
|
if not tl:
|
||||||
tags = ""
|
tags = ""
|
||||||
|
|
@ -128,16 +128,15 @@ class DocTags:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
"""adds the _user_tags column if not exists"""
|
"""Add the `_user_tags` column if not exists."""
|
||||||
from frappe.database.schema import add_column
|
from frappe.database.schema import add_column
|
||||||
|
|
||||||
add_column(self.dt, "_user_tags", "Data")
|
add_column(self.dt, "_user_tags", "Data")
|
||||||
|
|
||||||
|
|
||||||
def delete_tags_for_document(doc):
|
def delete_tags_for_document(doc):
|
||||||
"""
|
"""Delete the Tag Link entry of a document that has been deleted.
|
||||||
Delete the Tag Link entry of a document that has
|
|
||||||
been deleted
|
|
||||||
:param doc: Deleted document
|
:param doc: Deleted document
|
||||||
"""
|
"""
|
||||||
if not frappe.db.table_exists("Tag Link"):
|
if not frappe.db.table_exists("Tag Link"):
|
||||||
|
|
@ -147,7 +146,7 @@ def delete_tags_for_document(doc):
|
||||||
|
|
||||||
|
|
||||||
def update_tags(doc, tags):
|
def update_tags(doc, tags):
|
||||||
"""Adds tags for documents
|
"""Add tags for documents.
|
||||||
|
|
||||||
:param doc: Document to be added to global tags
|
:param doc: Document to be added to global tags
|
||||||
"""
|
"""
|
||||||
|
|
@ -181,8 +180,8 @@ def update_tags(doc, tags):
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_documents_for_tag(tag):
|
def get_documents_for_tag(tag):
|
||||||
"""
|
"""Search for given text in Tag Link.
|
||||||
Search for given text in Tag Link
|
|
||||||
:param tag: tag to be searched
|
:param tag: tag to be searched
|
||||||
"""
|
"""
|
||||||
# remove hastag `#` from tag
|
# remove hastag `#` from tag
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,7 @@ class ToDo(Document):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_owners(cls, filters=None):
|
def get_owners(cls, filters=None):
|
||||||
"""Returns list of owners after applying filters on todo's."""
|
"""Return list of owners after applying filters on ToDos."""
|
||||||
rows = frappe.get_all(cls.DocType, filters=filters or {}, fields=["allocated_to"])
|
rows = frappe.get_all(cls.DocType, filters=filters or {}, fields=["allocated_to"])
|
||||||
return [parse_addr(row.allocated_to)[1] for row in rows if row.allocated_to]
|
return [parse_addr(row.allocated_to)[1] for row in rows if row.allocated_to]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ class SubmittableDocumentTree:
|
||||||
return self._references_across_doctypes.get(doctype, [])
|
return self._references_across_doctypes.get(doctype, [])
|
||||||
|
|
||||||
def get_document_sources(self):
|
def get_document_sources(self):
|
||||||
"""Returns list of doctypes from where we access submittable documents."""
|
"""Return list of doctypes from where we access submittable documents."""
|
||||||
return list(set(self.get_link_sources() + [self.root_doctype]))
|
return list(set(self.get_link_sources() + [self.root_doctype]))
|
||||||
|
|
||||||
def get_link_sources(self):
|
def get_link_sources(self):
|
||||||
|
|
@ -139,7 +139,7 @@ class SubmittableDocumentTree:
|
||||||
return list(set(self.get_submittable_doctypes()) - set(get_exempted_doctypes() or []))
|
return list(set(self.get_submittable_doctypes()) - set(get_exempted_doctypes() or []))
|
||||||
|
|
||||||
def get_submittable_doctypes(self) -> list[str]:
|
def get_submittable_doctypes(self) -> list[str]:
|
||||||
"""Returns list of submittable doctypes."""
|
"""Return list of submittable doctypes."""
|
||||||
if not self._submittable_doctypes:
|
if not self._submittable_doctypes:
|
||||||
self._submittable_doctypes = frappe.get_all(
|
self._submittable_doctypes = frappe.get_all(
|
||||||
"DocType", {"is_submittable": 1}, pluck="name", order_by=None
|
"DocType", {"is_submittable": 1}, pluck="name", order_by=None
|
||||||
|
|
@ -148,7 +148,7 @@ class SubmittableDocumentTree:
|
||||||
|
|
||||||
|
|
||||||
def get_child_tables_of_doctypes(doctypes: list[str] = None):
|
def get_child_tables_of_doctypes(doctypes: list[str] = None):
|
||||||
"""Returns child tables by doctype."""
|
"""Return child tables by doctype."""
|
||||||
filters = [["fieldtype", "=", "Table"]]
|
filters = [["fieldtype", "=", "Table"]]
|
||||||
filters_for_docfield = filters
|
filters_for_docfield = filters
|
||||||
filters_for_customfield = filters
|
filters_for_customfield = filters
|
||||||
|
|
@ -387,7 +387,7 @@ def validate_linked_doc(docinfo, ignore_doctypes_on_cancel_all=None):
|
||||||
docinfo (dict): The document to check for submitted and non-exempt from auto-cancel
|
docinfo (dict): The document to check for submitted and non-exempt from auto-cancel
|
||||||
ignore_doctypes_on_cancel_all (list) - List of doctypes to ignore while cancelling.
|
ignore_doctypes_on_cancel_all (list) - List of doctypes to ignore while cancelling.
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
bool: True if linked document passes all validations, else False
|
bool: True if linked document passes all validations, else False
|
||||||
"""
|
"""
|
||||||
# ignore doctype to cancel
|
# ignore doctype to cancel
|
||||||
|
|
|
||||||
|
|
@ -274,7 +274,7 @@ def _get_communications(doctype, name, start=0, limit=20):
|
||||||
def get_communication_data(
|
def get_communication_data(
|
||||||
doctype, name, start=0, limit=20, after=None, fields=None, group_by=None, as_dict=True
|
doctype, name, start=0, limit=20, after=None, fields=None, group_by=None, as_dict=True
|
||||||
):
|
):
|
||||||
"""Returns list of communications for a given document"""
|
"""Return list of communications for a given document."""
|
||||||
if not fields:
|
if not fields:
|
||||||
fields = """
|
fields = """
|
||||||
C.name, C.communication_type, C.communication_medium,
|
C.name, C.communication_type, C.communication_medium,
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ def generate_report_result(
|
||||||
|
|
||||||
|
|
||||||
def normalize_result(result, columns):
|
def normalize_result(result, columns):
|
||||||
# Converts to list of dicts from list of lists/tuples
|
# Convert to list of dicts from list of lists/tuples
|
||||||
data = []
|
data = []
|
||||||
column_names = [column["fieldname"] for column in columns]
|
column_names = [column["fieldname"] for column in columns]
|
||||||
if result and isinstance(result[0], (list, tuple)):
|
if result and isinstance(result[0], (list, tuple)):
|
||||||
|
|
@ -603,11 +603,11 @@ def has_match(
|
||||||
columns_dict,
|
columns_dict,
|
||||||
user,
|
user,
|
||||||
):
|
):
|
||||||
"""Returns True if after evaluating permissions for each linked doctype
|
"""Return True if after evaluating permissions for each linked doctype:
|
||||||
- There is an owner match for the ref_doctype
|
- There is an owner match for the ref_doctype
|
||||||
- `and` There is a user permission match for all linked doctypes
|
- `and` There is a user permission match for all linked doctypes
|
||||||
|
|
||||||
Returns True if the row is empty
|
Return True if the row is empty.
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
Each doctype could have multiple conflicting user permission doctypes.
|
Each doctype could have multiple conflicting user permission doctypes.
|
||||||
|
|
@ -705,9 +705,10 @@ def get_linked_doctypes(columns, data):
|
||||||
|
|
||||||
|
|
||||||
def get_columns_dict(columns):
|
def get_columns_dict(columns):
|
||||||
"""Returns a dict with column docfield values as dict
|
"""Return a dict with column docfield values as dict.
|
||||||
|
|
||||||
The keys for the dict are both idx and fieldname,
|
The keys for the dict are both idx and fieldname,
|
||||||
so either index or fieldname can be used to search for a column's docfield properties
|
so either index or fieldname can be used to search for a column's docfield properties.
|
||||||
"""
|
"""
|
||||||
columns_dict = frappe._dict()
|
columns_dict = frappe._dict()
|
||||||
for idx, col in enumerate(columns):
|
for idx, col in enumerate(columns):
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ class AutoEmailReport(Document):
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_report_content(self):
|
def get_report_content(self):
|
||||||
"""Returns file in for the report in given format"""
|
"""Return file for the report in given format."""
|
||||||
report = frappe.get_doc("Report", self.report)
|
report = frappe.get_doc("Report", self.report)
|
||||||
|
|
||||||
self.filters = frappe.parse_json(self.filters) if self.filters else {}
|
self.filters = frappe.parse_json(self.filters) if self.filters else {}
|
||||||
|
|
|
||||||
|
|
@ -237,7 +237,7 @@ class EmailAccount(Document):
|
||||||
return frappe.db.get_value("Email Domain", domain, EMAIL_DOMAIN_FIELDS, as_dict=True)
|
return frappe.db.get_value("Email Domain", domain, EMAIL_DOMAIN_FIELDS, as_dict=True)
|
||||||
|
|
||||||
def get_incoming_server(self, in_receive=False, email_sync_rule="UNSEEN"):
|
def get_incoming_server(self, in_receive=False, email_sync_rule="UNSEEN"):
|
||||||
"""Returns logged in POP3/IMAP connection object."""
|
"""Return logged in POP3/IMAP connection object."""
|
||||||
oauth_token = self.get_oauth_token()
|
oauth_token = self.get_oauth_token()
|
||||||
args = frappe._dict(
|
args = frappe._dict(
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ class EmailTemplate(Document):
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_email_template(template_name, doc):
|
def get_email_template(template_name, doc):
|
||||||
"""Returns the processed HTML of a email template with the given doc"""
|
"""Return the processed HTML of a email template with the given doc"""
|
||||||
|
|
||||||
email_template = frappe.get_doc("Email Template", template_name)
|
email_template = frappe.get_doc("Email Template", template_name)
|
||||||
return email_template.get_formatted_email(doc)
|
return email_template.get_formatted_email(doc)
|
||||||
|
|
|
||||||
|
|
@ -394,7 +394,7 @@ def get_email_html(template, args, subject, header=None, with_container=False):
|
||||||
|
|
||||||
|
|
||||||
def inline_style_in_html(html):
|
def inline_style_in_html(html):
|
||||||
"""Convert email.css and html to inline-styled html"""
|
"""Convert email.css and html to inline-styled html."""
|
||||||
from premailer import Premailer
|
from premailer import Premailer
|
||||||
|
|
||||||
from frappe.utils.jinja_globals import bundled_asset
|
from frappe.utils.jinja_globals import bundled_asset
|
||||||
|
|
@ -460,7 +460,7 @@ def add_attachment(fname, fcontent, content_type=None, parent=None, content_id=N
|
||||||
|
|
||||||
|
|
||||||
def get_message_id():
|
def get_message_id():
|
||||||
"""Returns Message ID created from doctype and name"""
|
"""Return Message ID created from doctype and name."""
|
||||||
return email.utils.make_msgid(domain=frappe.local.site)
|
return email.utils.make_msgid(domain=frappe.local.site)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,7 @@ class EmailServer:
|
||||||
return
|
return
|
||||||
|
|
||||||
def get_messages(self, folder="INBOX"):
|
def get_messages(self, folder="INBOX"):
|
||||||
"""Returns new email messages."""
|
"""Return new email messages."""
|
||||||
|
|
||||||
self.latest_messages = []
|
self.latest_messages = []
|
||||||
self.seen_status = {}
|
self.seen_status = {}
|
||||||
|
|
@ -864,7 +864,7 @@ class InboundMail(Email):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_email_fields(doctype):
|
def get_email_fields(doctype):
|
||||||
"""Returns Email related fields of a doctype."""
|
"""Return Email related fields of a doctype."""
|
||||||
fields = frappe._dict()
|
fields = frappe._dict()
|
||||||
|
|
||||||
email_fields = ["subject_field", "sender_field", "sender_name_field"]
|
email_fields = ["subject_field", "sender_field", "sender_name_field"]
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ class FrappeClient:
|
||||||
def get_list(
|
def get_list(
|
||||||
self, doctype, fields='["name"]', filters=None, limit_start=0, limit_page_length=None
|
self, doctype, fields='["name"]', filters=None, limit_start=0, limit_page_length=None
|
||||||
):
|
):
|
||||||
"""Returns list of records of a particular type"""
|
"""Return list of records of a particular type."""
|
||||||
if not isinstance(fields, str):
|
if not isinstance(fields, str):
|
||||||
fields = json.dumps(fields)
|
fields = json.dumps(fields)
|
||||||
params = {
|
params = {
|
||||||
|
|
@ -173,7 +173,7 @@ class FrappeClient:
|
||||||
return self.post_request({"cmd": "frappe.client.submit", "doc": frappe.as_json(doc)})
|
return self.post_request({"cmd": "frappe.client.submit", "doc": frappe.as_json(doc)})
|
||||||
|
|
||||||
def get_value(self, doctype, fieldname=None, filters=None):
|
def get_value(self, doctype, fieldname=None, filters=None):
|
||||||
"""Returns a value form a document
|
"""Return a value from a document.
|
||||||
|
|
||||||
:param doctype: DocType to be queried
|
:param doctype: DocType to be queried
|
||||||
:param fieldname: Field to be returned (default `name`)
|
:param fieldname: Field to be returned (default `name`)
|
||||||
|
|
@ -212,7 +212,7 @@ class FrappeClient:
|
||||||
return self.post_request({"cmd": "frappe.client.cancel", "doctype": doctype, "name": name})
|
return self.post_request({"cmd": "frappe.client.cancel", "doctype": doctype, "name": name})
|
||||||
|
|
||||||
def get_doc(self, doctype, name="", filters=None, fields=None):
|
def get_doc(self, doctype, name="", filters=None, fields=None):
|
||||||
"""Returns a single remote document
|
"""Return a single remote document.
|
||||||
|
|
||||||
:param doctype: DocType of the document to be returned
|
:param doctype: DocType of the document to be returned
|
||||||
:param name: (optional) `name` of the document to be returned
|
:param name: (optional) `name` of the document to be returned
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ def get_coords(doctype, filters, type):
|
||||||
|
|
||||||
|
|
||||||
def convert_to_geojson(type, coords):
|
def convert_to_geojson(type, coords):
|
||||||
"""Converts GPS coordinates to geoJSON string."""
|
"""Convert GPS coordinates to geoJSON string."""
|
||||||
geojson = {"type": "FeatureCollection", "features": None}
|
geojson = {"type": "FeatureCollection", "features": None}
|
||||||
|
|
||||||
if type == "location_field":
|
if type == "location_field":
|
||||||
|
|
@ -90,7 +90,7 @@ def return_coordinates(doctype, filters_sql):
|
||||||
|
|
||||||
|
|
||||||
def get_coords_conditions(doctype, filters=None):
|
def get_coords_conditions(doctype, filters=None):
|
||||||
"""Returns SQL conditions with user permissions and filters for event queries."""
|
"""Return SQL conditions with user permissions and filters for event queries."""
|
||||||
from frappe.desk.reportview import get_filters_cond
|
from frappe.desk.reportview import get_filters_cond
|
||||||
|
|
||||||
if not frappe.has_permission(doctype):
|
if not frappe.has_permission(doctype):
|
||||||
|
|
|
||||||
|
|
@ -419,7 +419,7 @@ def _delete_modules(modules: list[str], dry_run: bool) -> list[str]:
|
||||||
|
|
||||||
Note: All record linked linked to Module Def are also deleted.
|
Note: All record linked linked to Module Def are also deleted.
|
||||||
|
|
||||||
Returns: list of deleted doctypes."""
|
Return: list of deleted doctypes."""
|
||||||
drop_doctypes = []
|
drop_doctypes = []
|
||||||
|
|
||||||
doctype_link_field_map = _get_module_linked_doctype_field_map()
|
doctype_link_field_map = _get_module_linked_doctype_field_map()
|
||||||
|
|
@ -461,7 +461,7 @@ def _delete_linked_documents(
|
||||||
def _get_module_linked_doctype_field_map() -> dict[str, str]:
|
def _get_module_linked_doctype_field_map() -> dict[str, str]:
|
||||||
"""Get all the doctypes which have module linked with them.
|
"""Get all the doctypes which have module linked with them.
|
||||||
|
|
||||||
returns ordered dictionary with doctype->link field mapping."""
|
Return ordered dictionary with doctype->link field mapping."""
|
||||||
|
|
||||||
# Hardcoded to change order of deletion
|
# Hardcoded to change order of deletion
|
||||||
ordered_doctypes = [
|
ordered_doctypes = [
|
||||||
|
|
@ -672,7 +672,7 @@ def extract_sql_from_archive(sql_file_path):
|
||||||
Args:
|
Args:
|
||||||
sql_file_path (str): Path of the SQL file
|
sql_file_path (str): Path of the SQL file
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
str: Path of the decompressed SQL file
|
str: Path of the decompressed SQL file
|
||||||
"""
|
"""
|
||||||
from frappe.utils import get_bench_relative_path
|
from frappe.utils import get_bench_relative_path
|
||||||
|
|
|
||||||
|
|
@ -202,9 +202,7 @@ def sync(g_calendar=None):
|
||||||
|
|
||||||
|
|
||||||
def get_google_calendar_object(g_calendar):
|
def get_google_calendar_object(g_calendar):
|
||||||
"""
|
"""Return an object of Google Calendar along with Google Calendar doc."""
|
||||||
Returns an object of Google Calendar along with Google Calendar doc.
|
|
||||||
"""
|
|
||||||
google_settings = frappe.get_doc("Google Settings")
|
google_settings = frappe.get_doc("Google Settings")
|
||||||
account = frappe.get_doc("Google Calendar", g_calendar)
|
account = frappe.get_doc("Google Calendar", g_calendar)
|
||||||
|
|
||||||
|
|
@ -257,8 +255,8 @@ def check_google_calendar(account, google_calendar):
|
||||||
|
|
||||||
|
|
||||||
def sync_events_from_google_calendar(g_calendar, method=None):
|
def sync_events_from_google_calendar(g_calendar, method=None):
|
||||||
"""
|
"""Sync Events from Google Calendar in Framework Calendar.
|
||||||
Syncs Events from Google Calendar in Framework Calendar.
|
|
||||||
Google Calendar returns nextSyncToken when all the events in Google Calendar are fetched.
|
Google Calendar returns nextSyncToken when all the events in Google Calendar are fetched.
|
||||||
nextSyncToken is returned at the very last page
|
nextSyncToken is returned at the very last page
|
||||||
https://developers.google.com/calendar/v3/sync
|
https://developers.google.com/calendar/v3/sync
|
||||||
|
|
@ -685,12 +683,10 @@ def format_date_according_to_google_calendar(all_day, starts_on, ends_on=None):
|
||||||
|
|
||||||
|
|
||||||
def parse_google_calendar_recurrence_rule(repeat_day_week_number, repeat_day_name):
|
def parse_google_calendar_recurrence_rule(repeat_day_week_number, repeat_day_name):
|
||||||
"""
|
"""Return (repeat_on) exact date for combination eg 4TH viz. 4th thursday of a month."""
|
||||||
Returns (repeat_on) exact date for combination eg 4TH viz. 4th thursday of a month
|
|
||||||
"""
|
|
||||||
if repeat_day_week_number < 0:
|
if repeat_day_week_number < 0:
|
||||||
# Consider a month with 5 weeks and event is to be repeated in last week of every month, google caledar considers
|
# Consider a month with 5 weeks and event is to be repeated in last week of every month, google caledar considers
|
||||||
# a month has 4 weeks and hence itll return -1 for a month with 5 weeks.
|
# a month has 4 weeks and hence it'll return -1 for a month with 5 weeks.
|
||||||
repeat_day_week_number = 4
|
repeat_day_week_number = 4
|
||||||
|
|
||||||
weekdays = get_weekdays()
|
weekdays = get_weekdays()
|
||||||
|
|
@ -714,9 +710,7 @@ def parse_google_calendar_recurrence_rule(repeat_day_week_number, repeat_day_nam
|
||||||
|
|
||||||
|
|
||||||
def repeat_on_to_google_calendar_recurrence_rule(doc):
|
def repeat_on_to_google_calendar_recurrence_rule(doc):
|
||||||
"""
|
"""Return event (repeat_on) in Google Calendar format ie RRULE:FREQ=WEEKLY;BYDAY=MO,TU,TH."""
|
||||||
Returns event (repeat_on) in Google Calendar format ie RRULE:FREQ=WEEKLY;BYDAY=MO,TU,TH
|
|
||||||
"""
|
|
||||||
recurrence = framework_frequencies.get(doc.repeat_on)
|
recurrence = framework_frequencies.get(doc.repeat_on)
|
||||||
weekdays = get_weekdays()
|
weekdays = get_weekdays()
|
||||||
|
|
||||||
|
|
@ -732,8 +726,8 @@ def repeat_on_to_google_calendar_recurrence_rule(doc):
|
||||||
|
|
||||||
|
|
||||||
def get_week_number(dt):
|
def get_week_number(dt):
|
||||||
"""
|
"""Return the week number of the month for the specified date.
|
||||||
Returns the week number of the month for the specified date.
|
|
||||||
https://stackoverflow.com/questions/3806473/python-week-number-of-the-month/16804556
|
https://stackoverflow.com/questions/3806473/python-week-number-of-the-month/16804556
|
||||||
"""
|
"""
|
||||||
from math import ceil
|
from math import ceil
|
||||||
|
|
@ -771,9 +765,7 @@ def get_conference_data(doc):
|
||||||
|
|
||||||
|
|
||||||
def get_attendees(doc):
|
def get_attendees(doc):
|
||||||
"""
|
"""Return a list of dicts with attendee emails, if available in event_participants table."""
|
||||||
Returns a list of dicts with attendee emails, if available in event_participants table
|
|
||||||
"""
|
|
||||||
attendees, email_not_found = [], []
|
attendees, email_not_found = [], []
|
||||||
|
|
||||||
for participant in doc.event_participants:
|
for participant in doc.event_participants:
|
||||||
|
|
|
||||||
|
|
@ -74,9 +74,7 @@ def authorize_access(g_contact, reauthorize=False, code=None):
|
||||||
|
|
||||||
|
|
||||||
def get_google_contacts_object(g_contact):
|
def get_google_contacts_object(g_contact):
|
||||||
"""
|
"""Return an object of Google Calendar along with Google Calendar doc."""
|
||||||
Returns an object of Google Calendar along with Google Calendar doc.
|
|
||||||
"""
|
|
||||||
account = frappe.get_doc("Google Contacts", g_contact)
|
account = frappe.get_doc("Google Contacts", g_contact)
|
||||||
oauth_obj = GoogleOAuth("contacts")
|
oauth_obj = GoogleOAuth("contacts")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,9 +88,7 @@ def authorize_access(reauthorize=False, code=None):
|
||||||
|
|
||||||
|
|
||||||
def get_google_drive_object():
|
def get_google_drive_object():
|
||||||
"""
|
"""Return an object of Google Drive."""
|
||||||
Returns an object of Google Drive.
|
|
||||||
"""
|
|
||||||
account = frappe.get_doc("Google Drive")
|
account = frappe.get_doc("Google Drive")
|
||||||
oauth_obj = GoogleOAuth("drive")
|
oauth_obj = GoogleOAuth("drive")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ class OAuthProviderSettings(Document):
|
||||||
|
|
||||||
|
|
||||||
def get_oauth_settings():
|
def get_oauth_settings():
|
||||||
"""Returns oauth settings"""
|
"""Return OAuth settings."""
|
||||||
return frappe._dict(
|
return frappe._dict(
|
||||||
{
|
{
|
||||||
"skip_authorization": frappe.db.get_single_value(
|
"skip_authorization": frappe.db.get_single_value(
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ class GoogleOAuth:
|
||||||
frappe.throw(frappe._("Please update {} before continuing.").format(google_settings))
|
frappe.throw(frappe._("Please update {} before continuing.").format(google_settings))
|
||||||
|
|
||||||
def authorize(self, oauth_code: str) -> dict[str, str | int]:
|
def authorize(self, oauth_code: str) -> dict[str, str | int]:
|
||||||
"""Returns a dict with access and refresh token.
|
"""Return a dict with access and refresh token.
|
||||||
|
|
||||||
:param oauth_code: code got back from google upon successful auhtorization
|
:param oauth_code: code got back from google upon successful auhtorization
|
||||||
"""
|
"""
|
||||||
|
|
@ -99,7 +99,7 @@ class GoogleOAuth:
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_authentication_url(self, state: dict[str, str]) -> dict[str, str]:
|
def get_authentication_url(self, state: dict[str, str]) -> dict[str, str]:
|
||||||
"""Returns google authentication url.
|
"""Return Google authentication url.
|
||||||
|
|
||||||
:param state: dict of values which you need on callback (for calling methods, redirection back to the form, doc name, etc)
|
:param state: dict of values which you need on callback (for calling methods, redirection back to the form, doc name, etc)
|
||||||
"""
|
"""
|
||||||
|
|
@ -117,7 +117,7 @@ class GoogleOAuth:
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_google_service_object(self, access_token: str, refresh_token: str):
|
def get_google_service_object(self, access_token: str, refresh_token: str):
|
||||||
"""Returns google service object"""
|
"""Return Google service object."""
|
||||||
|
|
||||||
credentials_dict = {
|
credentials_dict = {
|
||||||
"token": access_token,
|
"token": access_token,
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ def make_request(
|
||||||
|
|
||||||
|
|
||||||
def make_get_request(url: str, **kwargs):
|
def make_get_request(url: str, **kwargs):
|
||||||
"""Makes a 'GET' HTTP request to the given `url` and returns processed response.
|
"""Make a 'GET' HTTP request to the given `url` and return processed response.
|
||||||
|
|
||||||
You can optionally pass the below parameters:
|
You can optionally pass the below parameters:
|
||||||
|
|
||||||
|
|
@ -46,7 +46,7 @@ def make_get_request(url: str, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
def make_post_request(url: str, **kwargs):
|
def make_post_request(url: str, **kwargs):
|
||||||
"""Makes a 'POST' HTTP request to the given `url` and returns processed response.
|
"""Make a 'POST' HTTP request to the given `url` and return processed response.
|
||||||
|
|
||||||
You can optionally pass the below parameters:
|
You can optionally pass the below parameters:
|
||||||
|
|
||||||
|
|
@ -60,7 +60,7 @@ def make_post_request(url: str, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
def make_put_request(url: str, **kwargs):
|
def make_put_request(url: str, **kwargs):
|
||||||
"""Makes a 'PUT' HTTP request to the given `url` and returns processed response.
|
"""Make a 'PUT' HTTP request to the given `url` and return processed response.
|
||||||
|
|
||||||
You can optionally pass the below parameters:
|
You can optionally pass the below parameters:
|
||||||
|
|
||||||
|
|
@ -74,7 +74,7 @@ def make_put_request(url: str, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
def make_patch_request(url: str, **kwargs):
|
def make_patch_request(url: str, **kwargs):
|
||||||
"""Makes a 'PATCH' HTTP request to the given `url` and returns processed response.
|
"""Make a 'PATCH' HTTP request to the given `url` and return processed response.
|
||||||
|
|
||||||
You can optionally pass the below parameters:
|
You can optionally pass the below parameters:
|
||||||
|
|
||||||
|
|
@ -88,7 +88,7 @@ def make_patch_request(url: str, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
def make_delete_request(url: str, **kwargs):
|
def make_delete_request(url: str, **kwargs):
|
||||||
"""Makes a 'DELETE' HTTP request to the given `url` and returns processed response.
|
"""Make a 'DELETE' HTTP request to the given `url` and return processed response.
|
||||||
|
|
||||||
You can optionally pass the below parameters:
|
You can optionally pass the below parameters:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,7 @@ class SiteMigration:
|
||||||
frappe.get_attr(fn)()
|
frappe.get_attr(fn)()
|
||||||
|
|
||||||
def required_services_running(self) -> bool:
|
def required_services_running(self) -> bool:
|
||||||
"""Returns True if all required services are running. Returns False and prints
|
"""Return True if all required services are running. Return False and print
|
||||||
instructions to stdout when required services are not available.
|
instructions to stdout when required services are not available.
|
||||||
"""
|
"""
|
||||||
service_status = check_connection(redis_services=["redis_cache"])
|
service_status = check_connection(redis_services=["redis_cache"])
|
||||||
|
|
|
||||||
|
|
@ -55,9 +55,9 @@ DOCTYPES_FOR_DOCTYPE = {"DocType", *TABLE_DOCTYPES_FOR_DOCTYPE.values()}
|
||||||
|
|
||||||
|
|
||||||
def get_controller(doctype):
|
def get_controller(doctype):
|
||||||
"""
|
"""Return the locally cached **class** object of the given DocType.
|
||||||
Returns the locally cached **class** object of the given DocType.
|
|
||||||
For `custom` type, returns `frappe.model.document.Document`.
|
For `custom` type, return `frappe.model.document.Document`.
|
||||||
|
|
||||||
:param doctype: DocType name as string.
|
:param doctype: DocType name as string.
|
||||||
"""
|
"""
|
||||||
|
|
@ -146,9 +146,9 @@ class BaseDocument:
|
||||||
return get_permitted_fields(doctype=self.doctype, parenttype=getattr(self, "parenttype", None))
|
return get_permitted_fields(doctype=self.doctype, parenttype=getattr(self, "parenttype", None))
|
||||||
|
|
||||||
def __getstate__(self):
|
def __getstate__(self):
|
||||||
"""
|
"""Return a copy of `__dict__` excluding unpicklable values like `meta`.
|
||||||
|
|
||||||
Called when pickling.
|
Called when pickling.
|
||||||
Returns a copy of `__dict__` excluding unpicklable values like `meta`.
|
|
||||||
More info: https://docs.python.org/3/library/pickle.html#handling-stateful-objects
|
More info: https://docs.python.org/3/library/pickle.html#handling-stateful-objects
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -633,7 +633,7 @@ class BaseDocument:
|
||||||
|
|
||||||
def get_field_name_by_key_name(self, key_name):
|
def get_field_name_by_key_name(self, key_name):
|
||||||
"""MariaDB stores a mapping between `key_name` and `column_name`.
|
"""MariaDB stores a mapping between `key_name` and `column_name`.
|
||||||
This function returns the `column_name` associated with the `key_name` passed
|
Return the `column_name` associated with the `key_name` passed.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key_name (str): The name of the database index.
|
key_name (str): The name of the database index.
|
||||||
|
|
@ -641,7 +641,7 @@ class BaseDocument:
|
||||||
Raises:
|
Raises:
|
||||||
IndexError: If the key is not found in the table.
|
IndexError: If the key is not found in the table.
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
str: The column name associated with the key.
|
str: The column name associated with the key.
|
||||||
"""
|
"""
|
||||||
return frappe.db.sql(
|
return frappe.db.sql(
|
||||||
|
|
@ -660,12 +660,12 @@ class BaseDocument:
|
||||||
)[0].get("Column_name")
|
)[0].get("Column_name")
|
||||||
|
|
||||||
def get_label_from_fieldname(self, fieldname):
|
def get_label_from_fieldname(self, fieldname):
|
||||||
"""Returns the associated label for fieldname
|
"""Return the associated label for fieldname.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
fieldname (str): The fieldname in the DocType to use to pull the label.
|
fieldname (str): The fieldname in the DocType to use to pull the label.
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
str: The label associated with the fieldname, if found, otherwise `None`.
|
str: The label associated with the fieldname, if found, otherwise `None`.
|
||||||
"""
|
"""
|
||||||
df = self.meta.get_field(fieldname)
|
df = self.meta.get_field(fieldname)
|
||||||
|
|
@ -743,7 +743,7 @@ class BaseDocument:
|
||||||
return missing
|
return missing
|
||||||
|
|
||||||
def get_invalid_links(self, is_submittable=False):
|
def get_invalid_links(self, is_submittable=False):
|
||||||
"""Returns list of invalid links and also updates fetch values if not set"""
|
"""Return list of invalid links and also update fetch values if not set."""
|
||||||
|
|
||||||
def get_msg(df, docname):
|
def get_msg(df, docname):
|
||||||
# check if parentfield exists (only applicable for child table doctype)
|
# check if parentfield exists (only applicable for child table doctype)
|
||||||
|
|
@ -1112,7 +1112,7 @@ class BaseDocument:
|
||||||
return "".join(set(pwd)) == "*"
|
return "".join(set(pwd)) == "*"
|
||||||
|
|
||||||
def precision(self, fieldname, parentfield=None) -> int | None:
|
def precision(self, fieldname, parentfield=None) -> int | None:
|
||||||
"""Returns float precision for a particular field (or get global default).
|
"""Return float precision for a particular field (or get global default).
|
||||||
|
|
||||||
:param fieldname: Fieldname for which precision is required.
|
:param fieldname: Fieldname for which precision is required.
|
||||||
:param parentfield: If fieldname is in child table."""
|
:param parentfield: If fieldname is in child table."""
|
||||||
|
|
@ -1174,7 +1174,7 @@ class BaseDocument:
|
||||||
return format_value(val, df=df, doc=doc, currency=currency, format=format)
|
return format_value(val, df=df, doc=doc, currency=currency, format=format)
|
||||||
|
|
||||||
def is_print_hide(self, fieldname, df=None, for_print=True):
|
def is_print_hide(self, fieldname, df=None, for_print=True):
|
||||||
"""Returns true if fieldname is to be hidden for print.
|
"""Return True if fieldname is to be hidden for print.
|
||||||
|
|
||||||
Print Hide can be set via the Print Format Builder or in the controller as a list
|
Print Hide can be set via the Print Format Builder or in the controller as a list
|
||||||
of hidden fields. Example
|
of hidden fields. Example
|
||||||
|
|
@ -1203,7 +1203,8 @@ class BaseDocument:
|
||||||
return print_hide
|
return print_hide
|
||||||
|
|
||||||
def in_format_data(self, fieldname):
|
def in_format_data(self, fieldname):
|
||||||
"""Returns True if shown via Print Format::`format_data` property.
|
"""Return True if shown via Print Format::`format_data` property.
|
||||||
|
|
||||||
Called from within standard print format."""
|
Called from within standard print format."""
|
||||||
doc = getattr(self, "parent_doc", self)
|
doc = getattr(self, "parent_doc", self)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -335,7 +335,7 @@ class DatabaseQuery:
|
||||||
return args
|
return args
|
||||||
|
|
||||||
def parse_args(self):
|
def parse_args(self):
|
||||||
"""Convert fields and filters from strings to list, dicts"""
|
"""Convert fields and filters from strings to list, dicts."""
|
||||||
if isinstance(self.fields, str):
|
if isinstance(self.fields, str):
|
||||||
if self.fields == "*":
|
if self.fields == "*":
|
||||||
self.fields = ["*"]
|
self.fields = ["*"]
|
||||||
|
|
@ -715,7 +715,8 @@ class DatabaseQuery:
|
||||||
j = j + len(permitted_fields) - 1
|
j = j + len(permitted_fields) - 1
|
||||||
|
|
||||||
def prepare_filter_condition(self, f):
|
def prepare_filter_condition(self, f):
|
||||||
"""Returns a filter condition in the format:
|
"""Return a filter condition in the format:
|
||||||
|
|
||||||
ifnull(`tabDocType`.`fieldname`, fallback) operator "value"
|
ifnull(`tabDocType`.`fieldname`, fallback) operator "value"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -1339,7 +1340,7 @@ def get_date_range(operator: str, value: str):
|
||||||
|
|
||||||
|
|
||||||
def requires_owner_constraint(role_permissions):
|
def requires_owner_constraint(role_permissions):
|
||||||
"""Returns True if "select" or "read" isn't available without being creator."""
|
"""Return True if "select" or "read" isn't available without being creator."""
|
||||||
|
|
||||||
if not role_permissions.get("has_if_owner_enabled"):
|
if not role_permissions.get("has_if_owner_enabled"):
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ if TYPE_CHECKING:
|
||||||
|
|
||||||
|
|
||||||
def get_doc(*args, **kwargs):
|
def get_doc(*args, **kwargs):
|
||||||
"""returns a frappe.model.Document object.
|
"""Return a `frappe.model.Document` object.
|
||||||
|
|
||||||
:param arg1: Document dict or DocType name.
|
:param arg1: Document dict or DocType name.
|
||||||
:param arg2: [optional] document name.
|
:param arg2: [optional] document name.
|
||||||
|
|
@ -454,7 +454,7 @@ class Document(BaseDocument):
|
||||||
return getattr(self, "_doc_before_save", None)
|
return getattr(self, "_doc_before_save", None)
|
||||||
|
|
||||||
def has_value_changed(self, fieldname):
|
def has_value_changed(self, fieldname):
|
||||||
"""Returns true if value is changed before and after saving"""
|
"""Return True if value has changed before and after saving."""
|
||||||
previous = self.get_doc_before_save()
|
previous = self.get_doc_before_save()
|
||||||
return previous.get(fieldname) != self.get(fieldname) if previous else True
|
return previous.get(fieldname) != self.get(fieldname) if previous else True
|
||||||
|
|
||||||
|
|
@ -924,7 +924,7 @@ class Document(BaseDocument):
|
||||||
frappe.throw(_("Cannot link cancelled document: {0}").format(msg), frappe.CancelledLinkError)
|
frappe.throw(_("Cannot link cancelled document: {0}").format(msg), frappe.CancelledLinkError)
|
||||||
|
|
||||||
def get_all_children(self, parenttype=None) -> list["Document"]:
|
def get_all_children(self, parenttype=None) -> list["Document"]:
|
||||||
"""Returns all children documents from **Table** type fields in a list."""
|
"""Return all children documents from **Table** type fields in a list."""
|
||||||
|
|
||||||
children = []
|
children = []
|
||||||
|
|
||||||
|
|
@ -977,7 +977,7 @@ class Document(BaseDocument):
|
||||||
if self.flags.notifications is None:
|
if self.flags.notifications is None:
|
||||||
|
|
||||||
def _get_notifications():
|
def _get_notifications():
|
||||||
"""returns enabled notifications for the current doctype"""
|
"""Return enabled notifications for the current doctype."""
|
||||||
|
|
||||||
return frappe.get_all(
|
return frappe.get_all(
|
||||||
"Notification",
|
"Notification",
|
||||||
|
|
@ -1379,7 +1379,7 @@ class Document(BaseDocument):
|
||||||
doc.set(fieldname, flt(doc.get(fieldname), self.precision(fieldname, doc.get("parentfield"))))
|
doc.set(fieldname, flt(doc.get(fieldname), self.precision(fieldname, doc.get("parentfield"))))
|
||||||
|
|
||||||
def get_url(self):
|
def get_url(self):
|
||||||
"""Returns Desk URL for this document."""
|
"""Return Desk URL for this document."""
|
||||||
return get_absolute_url(self.doctype, self.name)
|
return get_absolute_url(self.doctype, self.name)
|
||||||
|
|
||||||
def add_comment(
|
def add_comment(
|
||||||
|
|
@ -1453,7 +1453,7 @@ class Document(BaseDocument):
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_signature(self):
|
def get_signature(self):
|
||||||
"""Returns signature (hash) for private URL."""
|
"""Return signature (hash) for private URL."""
|
||||||
return hashlib.sha224(get_datetime_str(self.creation).encode()).hexdigest()
|
return hashlib.sha224(get_datetime_str(self.creation).encode()).hexdigest()
|
||||||
|
|
||||||
def get_document_share_key(self, expires_on=None, no_expiry=False):
|
def get_document_share_key(self, expires_on=None, no_expiry=False):
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ from frappe.utils import cstr
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_mapped_doc(method, source_name, selected_children=None, args=None):
|
def make_mapped_doc(method, source_name, selected_children=None, args=None):
|
||||||
"""Returns the mapped document calling the given mapper method.
|
"""Return the mapped document calling the given mapper method.
|
||||||
Sets selected_children as flags for the `get_mapped_doc` method.
|
Set `selected_children` as flags for the `get_mapped_doc` method.
|
||||||
|
|
||||||
Called from `open_mapped_doc` from create_new.js"""
|
Called from `open_mapped_doc` from create_new.js"""
|
||||||
|
|
||||||
|
|
@ -38,11 +38,12 @@ def make_mapped_doc(method, source_name, selected_children=None, args=None):
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def map_docs(method, source_names, target_doc, args=None):
|
def map_docs(method, source_names, target_doc, args=None):
|
||||||
'''Returns the mapped document calling the given mapper method
|
"""Return the mapped document calling the given mapper method with each of the given source docs on the target doc.
|
||||||
with each of the given source docs on the target doc
|
|
||||||
|
|
||||||
:param args: Args as string to pass to the mapper method
|
:param args: Args as string to pass to the mapper method
|
||||||
E.g. args: "{ 'supplier': 'XYZ' }"'''
|
|
||||||
|
e.g. args: "{ 'supplier': 'XYZ' }"
|
||||||
|
"""
|
||||||
|
|
||||||
method = frappe.get_attr(method)
|
method = frappe.get_attr(method)
|
||||||
if method not in frappe.whitelisted:
|
if method not in frappe.whitelisted:
|
||||||
|
|
|
||||||
|
|
@ -208,7 +208,7 @@ class Meta(Document):
|
||||||
return self._table_fields
|
return self._table_fields
|
||||||
|
|
||||||
def get_global_search_fields(self):
|
def get_global_search_fields(self):
|
||||||
"""Returns list of fields with `in_global_search` set and `name` if set"""
|
"""Return list of fields with `in_global_search` set and `name` if set."""
|
||||||
fields = self.get("fields", {"in_global_search": 1, "fieldtype": ["not in", no_value_fields]})
|
fields = self.get("fields", {"in_global_search": 1, "fieldtype": ["not in", no_value_fields]})
|
||||||
if getattr(self, "show_name_in_global_search", None):
|
if getattr(self, "show_name_in_global_search", None):
|
||||||
fields.append(frappe._dict(fieldtype="Data", fieldname="name", label="Name"))
|
fields.append(frappe._dict(fieldtype="Data", fieldname="name", label="Name"))
|
||||||
|
|
@ -233,17 +233,17 @@ class Meta(Document):
|
||||||
return TABLE_DOCTYPES_FOR_DOCTYPE.get(fieldname)
|
return TABLE_DOCTYPES_FOR_DOCTYPE.get(fieldname)
|
||||||
|
|
||||||
def get_field(self, fieldname):
|
def get_field(self, fieldname):
|
||||||
"""Return docfield from meta"""
|
"""Return docfield from meta."""
|
||||||
|
|
||||||
return self._fields.get(fieldname)
|
return self._fields.get(fieldname)
|
||||||
|
|
||||||
def has_field(self, fieldname):
|
def has_field(self, fieldname):
|
||||||
"""Returns True if fieldname exists"""
|
"""Return True if fieldname exists."""
|
||||||
|
|
||||||
return fieldname in self._fields
|
return fieldname in self._fields
|
||||||
|
|
||||||
def get_label(self, fieldname):
|
def get_label(self, fieldname):
|
||||||
"""Get label of the given fieldname"""
|
"""Return label of the given fieldname."""
|
||||||
if df := self.get_field(fieldname):
|
if df := self.get_field(fieldname):
|
||||||
return df.get("label")
|
return df.get("label")
|
||||||
|
|
||||||
|
|
@ -273,8 +273,8 @@ class Meta(Document):
|
||||||
return search_fields
|
return search_fields
|
||||||
|
|
||||||
def get_fields_to_fetch(self, link_fieldname=None):
|
def get_fields_to_fetch(self, link_fieldname=None):
|
||||||
"""Returns a list of docfield objects for fields whose values
|
"""Return a list of docfield objects for fields whose values
|
||||||
are to be fetched and updated for a particular link field
|
are to be fetched and updated for a particular link field.
|
||||||
|
|
||||||
These fields are of type Data, Link, Text, Readonly and their
|
These fields are of type Data, Link, Text, Readonly and their
|
||||||
fetch_from property is set as `link_fieldname`.`source_fieldname`"""
|
fetch_from property is set as `link_fieldname`.`source_fieldname`"""
|
||||||
|
|
@ -615,7 +615,7 @@ class Meta(Document):
|
||||||
return permissions
|
return permissions
|
||||||
|
|
||||||
def get_dashboard_data(self):
|
def get_dashboard_data(self):
|
||||||
"""Returns dashboard setup related to this doctype.
|
"""Return dashboard setup related to this doctype.
|
||||||
|
|
||||||
This method will return the `data` property in the `[doctype]_dashboard.py`
|
This method will return the `data` property in the `[doctype]_dashboard.py`
|
||||||
file in the doctype's folder, along with any overrides or extensions
|
file in the doctype's folder, along with any overrides or extensions
|
||||||
|
|
@ -695,7 +695,7 @@ class Meta(Document):
|
||||||
return self.get_web_template(suffix="_list")
|
return self.get_web_template(suffix="_list")
|
||||||
|
|
||||||
def get_web_template(self, suffix=""):
|
def get_web_template(self, suffix=""):
|
||||||
"""Returns the relative path of the row template for this doctype"""
|
"""Return the relative path of the row template for this doctype."""
|
||||||
module_name = frappe.scrub(self.module)
|
module_name = frappe.scrub(self.module)
|
||||||
doctype = frappe.scrub(self.name)
|
doctype = frappe.scrub(self.name)
|
||||||
template_path = frappe.get_module_path(
|
template_path = frappe.get_module_path(
|
||||||
|
|
|
||||||
|
|
@ -334,7 +334,7 @@ def parse_naming_series(
|
||||||
|
|
||||||
|
|
||||||
def has_custom_parser(e):
|
def has_custom_parser(e):
|
||||||
"""Returns true if the naming series part has a custom parser"""
|
"""Return True if the naming series part has a custom parser."""
|
||||||
return frappe.get_hooks("naming_series_variables", {}).get(e)
|
return frappe.get_hooks("naming_series_variables", {}).get(e)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,7 @@ def update_document_title(
|
||||||
**kwargs,
|
**kwargs,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Update the name or title of a document. Returns `name` if document was renamed,
|
Update the name or title of a document. Return `name` if document was renamed, `docname` if renaming operation was queued.
|
||||||
`docname` if renaming operation was queued.
|
|
||||||
|
|
||||||
:param doctype: DocType of the document
|
:param doctype: DocType of the document
|
||||||
:param docname: Name of the document
|
:param docname: Name of the document
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ def render_include(content):
|
||||||
|
|
||||||
|
|
||||||
def get_fetch_values(doctype, fieldname, value):
|
def get_fetch_values(doctype, fieldname, value):
|
||||||
"""Returns fetch value dict for the given object
|
"""Return fetch value dict for the given object.
|
||||||
|
|
||||||
:param doctype: Target doctype
|
:param doctype: Target doctype
|
||||||
:param fieldname: Link fieldname selected
|
:param fieldname: Link fieldname selected
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,10 @@ from frappe.utils import get_datetime, now
|
||||||
|
|
||||||
|
|
||||||
def calculate_hash(path: str) -> str:
|
def calculate_hash(path: str) -> str:
|
||||||
"""Calculate md5 hash of the file in binary mode
|
"""Calculate and return md5 hash of the file in binary mode.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path (str): Path to the file to be hashed
|
path (str): Path to the file to be hashed
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: The calculated hash
|
|
||||||
"""
|
"""
|
||||||
hash_md5 = hashlib.md5(usedforsecurity=False)
|
hash_md5 = hashlib.md5(usedforsecurity=False)
|
||||||
with open(path, "rb") as f:
|
with open(path, "rb") as f:
|
||||||
|
|
@ -82,8 +79,8 @@ def import_file_by_path(
|
||||||
pre_process=None,
|
pre_process=None,
|
||||||
ignore_version: bool = None,
|
ignore_version: bool = None,
|
||||||
reset_permissions: bool = False,
|
reset_permissions: bool = False,
|
||||||
):
|
) -> bool:
|
||||||
"""Import file from the given path
|
"""Import file from the given path.
|
||||||
|
|
||||||
Some conditions decide if a file should be imported or not.
|
Some conditions decide if a file should be imported or not.
|
||||||
Evaluation takes place in the order they are mentioned below.
|
Evaluation takes place in the order they are mentioned below.
|
||||||
|
|
@ -107,8 +104,7 @@ def import_file_by_path(
|
||||||
ignore_version (bool, optional): ignore current version. Defaults to None.
|
ignore_version (bool, optional): ignore current version. Defaults to None.
|
||||||
reset_permissions (bool, optional): reset permissions for the file. Defaults to False.
|
reset_permissions (bool, optional): reset permissions for the file. Defaults to False.
|
||||||
|
|
||||||
Returns:
|
Return True if import takes place, False if it wasn't imported.
|
||||||
[bool]: True if import takes place. False if it wasn't imported.
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
docs = read_doc_from_file(path)
|
docs = read_doc_from_file(path)
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,9 @@ doctype_python_modules = {}
|
||||||
|
|
||||||
|
|
||||||
def export_module_json(doc: "Document", is_standard: bool, module: str) -> str | None:
|
def export_module_json(doc: "Document", is_standard: bool, module: str) -> str | None:
|
||||||
"""Make a folder for the given doc and add its json file (make it a standard
|
"""Make a folder for the given doc and add its json file (make it a standard object that will be synced).
|
||||||
object that will be synced)
|
|
||||||
|
|
||||||
Returns the absolute file_path without the extension.
|
Return the absolute file_path without the extension.
|
||||||
Eg: For exporting a Print Format "_Test Print Format 1", the return value will be
|
Eg: For exporting a Print Format "_Test Print Format 1", the return value will be
|
||||||
`/home/gavin/frappe-bench/apps/frappe/frappe/core/print_format/_test_print_format_1/_test_print_format_1`
|
`/home/gavin/frappe-bench/apps/frappe/frappe/core/print_format/_test_print_format_1/_test_print_format_1`
|
||||||
"""
|
"""
|
||||||
|
|
@ -181,12 +180,12 @@ def sync_customizations_for_doctype(data: dict, folder: str, filename: str = "")
|
||||||
|
|
||||||
|
|
||||||
def scrub_dt_dn(dt: str, dn: str) -> tuple[str, str]:
|
def scrub_dt_dn(dt: str, dn: str) -> tuple[str, str]:
|
||||||
"""Returns in lowercase and code friendly names of doctype and name for certain types"""
|
"""Return in lowercase and code friendly names of doctype and name for certain types."""
|
||||||
return scrub(dt), scrub(dn)
|
return scrub(dt), scrub(dn)
|
||||||
|
|
||||||
|
|
||||||
def get_doc_path(module: str, doctype: str, name: str) -> str:
|
def get_doc_path(module: str, doctype: str, name: str) -> str:
|
||||||
"""Returns path of a doc in a module"""
|
"""Return path of a doc in a module."""
|
||||||
return os.path.join(get_module_path(module), *scrub_dt_dn(doctype, name))
|
return os.path.join(get_module_path(module), *scrub_dt_dn(doctype, name))
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -213,7 +212,7 @@ def export_doc(doctype, name, module=None):
|
||||||
|
|
||||||
|
|
||||||
def get_doctype_module(doctype: str) -> str:
|
def get_doctype_module(doctype: str) -> str:
|
||||||
"""Returns **Module Def** name of given doctype."""
|
"""Return **Module Def** name of given doctype."""
|
||||||
doctype_module_map = frappe.cache.get_value(
|
doctype_module_map = frappe.cache.get_value(
|
||||||
"doctype_modules",
|
"doctype_modules",
|
||||||
generator=lambda: dict(frappe.qb.from_("DocType").select("name", "module").run()),
|
generator=lambda: dict(frappe.qb.from_("DocType").select("name", "module").run()),
|
||||||
|
|
@ -226,7 +225,7 @@ def get_doctype_module(doctype: str) -> str:
|
||||||
|
|
||||||
|
|
||||||
def load_doctype_module(doctype, module=None, prefix="", suffix=""):
|
def load_doctype_module(doctype, module=None, prefix="", suffix=""):
|
||||||
"""Returns the module object for given doctype.
|
"""Return the module object for given doctype.
|
||||||
|
|
||||||
Note: This will return the standard defined module object for the doctype irrespective
|
Note: This will return the standard defined module object for the doctype irrespective
|
||||||
of the `override_doctype_class` hook.
|
of the `override_doctype_class` hook.
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ def execute():
|
||||||
|
|
||||||
|
|
||||||
def get_doctypes_to_skip(doctype, user):
|
def get_doctypes_to_skip(doctype, user):
|
||||||
"""Returns doctypes to be skipped from user permission check"""
|
"""Return doctypes to be skipped from user permission check."""
|
||||||
doctypes_to_skip = []
|
doctypes_to_skip = []
|
||||||
valid_perms = get_user_valid_perms(user) or []
|
valid_perms = get_user_valid_perms(user) or []
|
||||||
for perm in valid_perms:
|
for perm in valid_perms:
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import frappe
|
||||||
|
|
||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
"""Convert Query Report json to support other content"""
|
"""Convert Query Report json to support other content."""
|
||||||
records = frappe.get_all("Report", filters={"json": ["!=", ""]}, fields=["name", "json"])
|
records = frappe.get_all("Report", filters={"json": ["!=", ""]}, fields=["name", "json"])
|
||||||
for record in records:
|
for record in records:
|
||||||
jstr = record["json"]
|
jstr = record["json"]
|
||||||
|
|
|
||||||
|
|
@ -63,8 +63,8 @@ def has_permission(
|
||||||
*,
|
*,
|
||||||
parent_doctype=None,
|
parent_doctype=None,
|
||||||
):
|
):
|
||||||
"""Returns True if user has permission `ptype` for given `doctype`.
|
"""Return True if user has permission `ptype` for given `doctype`.
|
||||||
If `doc` is passed, it also checks user, share and owner permissions.
|
If `doc` is passed, also check user, share and owner permissions.
|
||||||
|
|
||||||
:param doctype: DocType to check permission for
|
:param doctype: DocType to check permission for
|
||||||
:param ptype: Permission Type to check
|
:param ptype: Permission Type to check
|
||||||
|
|
@ -159,7 +159,7 @@ def has_permission(
|
||||||
|
|
||||||
|
|
||||||
def get_doc_permissions(doc, user=None, ptype=None):
|
def get_doc_permissions(doc, user=None, ptype=None):
|
||||||
"""Returns a dict of evaluated permissions for given `doc` like `{"read":1, "write":1}`"""
|
"""Return a dict of evaluated permissions for given `doc` like `{"read":1, "write":1}`"""
|
||||||
if not user:
|
if not user:
|
||||||
user = frappe.session.user
|
user = frappe.session.user
|
||||||
|
|
||||||
|
|
@ -204,7 +204,7 @@ def get_doc_permissions(doc, user=None, ptype=None):
|
||||||
|
|
||||||
def get_role_permissions(doctype_meta, user=None, is_owner=None):
|
def get_role_permissions(doctype_meta, user=None, is_owner=None):
|
||||||
"""
|
"""
|
||||||
Returns dict of evaluated role permissions like
|
Return dict of evaluated role permissions like:
|
||||||
{
|
{
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"write": 0,
|
"write": 0,
|
||||||
|
|
@ -272,7 +272,7 @@ def get_user_permissions(user):
|
||||||
|
|
||||||
|
|
||||||
def has_user_permission(doc, user=None):
|
def has_user_permission(doc, user=None):
|
||||||
"""Returns True if User is allowed to view considering User Permissions"""
|
"""Return True if User is allowed to view considering User Permissions."""
|
||||||
from frappe.core.doctype.user_permission.user_permission import get_user_permissions
|
from frappe.core.doctype.user_permission.user_permission import get_user_permissions
|
||||||
|
|
||||||
user_permissions = get_user_permissions(user)
|
user_permissions = get_user_permissions(user)
|
||||||
|
|
@ -374,7 +374,7 @@ def has_user_permission(doc, user=None):
|
||||||
|
|
||||||
|
|
||||||
def has_controller_permissions(doc, ptype, user=None):
|
def has_controller_permissions(doc, ptype, user=None):
|
||||||
"""Returns controller permissions if defined. None if not defined"""
|
"""Return controller permissions if defined, None if not defined."""
|
||||||
if not user:
|
if not user:
|
||||||
user = frappe.session.user
|
user = frappe.session.user
|
||||||
|
|
||||||
|
|
@ -415,7 +415,7 @@ def get_valid_perms(doctype=None, user=None):
|
||||||
|
|
||||||
|
|
||||||
def get_all_perms(role):
|
def get_all_perms(role):
|
||||||
"""Returns valid permissions for a given role"""
|
"""Return valid permissions for a given role."""
|
||||||
perms = frappe.get_all("DocPerm", fields="*", filters=dict(role=role))
|
perms = frappe.get_all("DocPerm", fields="*", filters=dict(role=role))
|
||||||
custom_perms = frappe.get_all("Custom DocPerm", fields="*", filters=dict(role=role))
|
custom_perms = frappe.get_all("Custom DocPerm", fields="*", filters=dict(role=role))
|
||||||
doctypes_with_custom_perms = frappe.get_all("Custom DocPerm", pluck="parent", distinct=True)
|
doctypes_with_custom_perms = frappe.get_all("Custom DocPerm", pluck="parent", distinct=True)
|
||||||
|
|
@ -462,7 +462,7 @@ def get_roles(user=None, with_standard=True):
|
||||||
|
|
||||||
|
|
||||||
def get_doctype_roles(doctype, access_type="read"):
|
def get_doctype_roles(doctype, access_type="read"):
|
||||||
"""Returns a list of roles that are allowed to access passed doctype."""
|
"""Return a list of roles that are allowed to access the given `doctype`."""
|
||||||
meta = frappe.get_meta(doctype)
|
meta = frappe.get_meta(doctype)
|
||||||
return [d.role for d in meta.get("permissions") if d.get(access_type)]
|
return [d.role for d in meta.get("permissions") if d.get(access_type)]
|
||||||
|
|
||||||
|
|
@ -474,7 +474,7 @@ def get_perms_for(roles, perm_doctype="DocPerm"):
|
||||||
|
|
||||||
|
|
||||||
def get_doctypes_with_custom_docperms():
|
def get_doctypes_with_custom_docperms():
|
||||||
"""Returns all the doctypes with Custom Docperms"""
|
"""Return all the doctypes with Custom Docperms."""
|
||||||
|
|
||||||
doctypes = frappe.get_all("Custom DocPerm", fields=["parent"], distinct=1)
|
doctypes = frappe.get_all("Custom DocPerm", fields=["parent"], distinct=1)
|
||||||
return [d.parent for d in doctypes]
|
return [d.parent for d in doctypes]
|
||||||
|
|
@ -655,22 +655,18 @@ def get_doc_name(doc):
|
||||||
|
|
||||||
|
|
||||||
def allow_everything():
|
def allow_everything():
|
||||||
"""
|
"""Return a dict with access to everything, eg. {"read": 1, "write": 1, ...}."""
|
||||||
returns a dict with access to everything
|
|
||||||
eg. {"read": 1, "write": 1, ...}
|
|
||||||
"""
|
|
||||||
return {ptype: 1 for ptype in rights}
|
return {ptype: 1 for ptype in rights}
|
||||||
|
|
||||||
|
|
||||||
def get_allowed_docs_for_doctype(user_permissions, doctype):
|
def get_allowed_docs_for_doctype(user_permissions, doctype):
|
||||||
"""Returns all the docs from the passed user_permissions that are
|
"""Return all the docs from the passed `user_permissions` that are allowed under provided doctype."""
|
||||||
allowed under provided doctype"""
|
|
||||||
return filter_allowed_docs_for_doctype(user_permissions, doctype, with_default_doc=False)
|
return filter_allowed_docs_for_doctype(user_permissions, doctype, with_default_doc=False)
|
||||||
|
|
||||||
|
|
||||||
def filter_allowed_docs_for_doctype(user_permissions, doctype, with_default_doc=True):
|
def filter_allowed_docs_for_doctype(user_permissions, doctype, with_default_doc=True):
|
||||||
"""Returns all the docs from the passed user_permissions that are
|
"""Return all the docs from the passed `user_permissions` that are
|
||||||
allowed under provided doctype along with default doc value if with_default_doc is set"""
|
allowed under provided doctype along with default doc value if `with_default_doc` is set."""
|
||||||
allowed_doc = []
|
allowed_doc = []
|
||||||
default_doc = None
|
default_doc = None
|
||||||
for doc in user_permissions:
|
for doc in user_permissions:
|
||||||
|
|
|
||||||
|
|
@ -88,11 +88,7 @@ class ConstantColumn(Term):
|
||||||
alias = None
|
alias = None
|
||||||
|
|
||||||
def __init__(self, value: str) -> None:
|
def __init__(self, value: str) -> None:
|
||||||
"""[ Returns a pseudo column with a constant value in all the rows]
|
"""Return a pseudo column with the given constant `value` in all the rows."""
|
||||||
|
|
||||||
Args:
|
|
||||||
value (str): [ Value of the column ]
|
|
||||||
"""
|
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
def get_sql(self, quote_char: str | None = None, **kwargs: Any) -> str:
|
def get_sql(self, quote_char: str | None = None, **kwargs: Any) -> str:
|
||||||
|
|
|
||||||
|
|
@ -15,24 +15,20 @@ class NamedParameterWrapper:
|
||||||
self.parameters = {}
|
self.parameters = {}
|
||||||
|
|
||||||
def get_sql(self, param_value: Any, **kwargs) -> str:
|
def get_sql(self, param_value: Any, **kwargs) -> str:
|
||||||
"""returns SQL for a parameter, while adding the real value in a dict
|
"""Return SQL for a parameter, while adding the real value in a dict.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
param_value (Any): Value of the parameter
|
param_value (Any): Value of the parameter
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
str: parameter used in the SQL query
|
str: parameter used in the SQL query
|
||||||
"""
|
"""
|
||||||
param_key = f"%(param{len(self.parameters) + 1})s"
|
param_key = f"%(param{len(self.parameters) + 1})s"
|
||||||
self.parameters[param_key[2:-2]] = param_value
|
self.parameters[param_key[2:-2]] = param_value
|
||||||
return param_key
|
return param_key
|
||||||
|
|
||||||
def get_parameters(self) -> dict[str, Any]:
|
def get_parameters(self) -> dict[str, Any]:
|
||||||
"""get dict with parameters and values
|
"""Get dict with parameters and values."""
|
||||||
|
|
||||||
Returns:
|
|
||||||
Dict[str, Any]: parameter dict
|
|
||||||
"""
|
|
||||||
return self.parameters
|
return self.parameters
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,13 +42,10 @@ class BuilderIdentificationFailed(Exception):
|
||||||
|
|
||||||
|
|
||||||
def get_query_builder(type_of_db: str) -> Postgres | MariaDB:
|
def get_query_builder(type_of_db: str) -> Postgres | MariaDB:
|
||||||
"""[return the query builder object]
|
"""Return the query builder object.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
type_of_db (str): [string value of the db used]
|
type_of_db: string value of the db used
|
||||||
|
|
||||||
Returns:
|
|
||||||
Query: [Query object]
|
|
||||||
"""
|
"""
|
||||||
db = db_type_is(type_of_db)
|
db = db_type_is(type_of_db)
|
||||||
picks = {db_type_is.MARIADB: MariaDB, db_type_is.POSTGRES: Postgres}
|
picks = {db_type_is.MARIADB: MariaDB, db_type_is.POSTGRES: Postgres}
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ def rate_limit(
|
||||||
:param ip_based: flag to allow ip based rate-limiting
|
:param ip_based: flag to allow ip based rate-limiting
|
||||||
:type ip_based: Boolean
|
:type ip_based: Boolean
|
||||||
|
|
||||||
:returns: a decorator function that limit the number of requests per endpoint
|
Return: a decorator function that limit the number of requests per endpoint
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def ratelimit_decorator(fn):
|
def ratelimit_decorator(fn):
|
||||||
|
|
|
||||||
|
|
@ -107,16 +107,13 @@ class FullTextSearch:
|
||||||
|
|
||||||
writer.commit(optimize=True)
|
writer.commit(optimize=True)
|
||||||
|
|
||||||
def search(self, text, scope=None, limit=20):
|
def search(self, text: str, scope: str | None = None, limit: int = 20) -> list[frappe._dict]:
|
||||||
"""Search from the current index
|
"""Search from the current index.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
text (str): String to search for
|
text: String to search for
|
||||||
scope (str, optional): Scope to limit the search. Defaults to None.
|
scope: Scope to limit the search. Defaults to None.
|
||||||
limit (int, optional): Limit number of search results. Defaults to 20.
|
limit: Limit number of search results. Defaults to 20.
|
||||||
|
|
||||||
Returns:
|
|
||||||
[List(_dict)]: Search results
|
|
||||||
"""
|
"""
|
||||||
ix = self.get_index()
|
ix = self.get_index()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,10 +27,9 @@ class WebsiteSearch(FullTextSearch):
|
||||||
return "path"
|
return "path"
|
||||||
|
|
||||||
def get_items_to_index(self):
|
def get_items_to_index(self):
|
||||||
"""Get all routes to be indexed, this includes the static pages
|
"""Get all routes to be indexed, this includes the static pages in www/ and routes from published documents.
|
||||||
in www/ and routes from published documents
|
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
self (object): FullTextSearch Instance
|
self (object): FullTextSearch Instance
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -49,14 +48,13 @@ class WebsiteSearch(FullTextSearch):
|
||||||
|
|
||||||
return self.get_items_to_index()
|
return self.get_items_to_index()
|
||||||
|
|
||||||
def get_document_to_index(self, route):
|
def get_document_to_index(self, route: str) -> frappe._dict | None:
|
||||||
"""Render a page and parse it using BeautifulSoup
|
"""Render a page and parse it using `BeautifulSoup`.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path (str): route of the page to be parsed
|
path: route of the page to be parsed
|
||||||
|
|
||||||
Returns:
|
Return a dictionary with title, path and content.
|
||||||
document (_dict): A dictionary with title, path and content
|
|
||||||
"""
|
"""
|
||||||
frappe.set_user("Guest")
|
frappe.set_user("Guest")
|
||||||
frappe.local.no_cache = True
|
frappe.local.no_cache = True
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ def clear_sessions(user=None, keep_current=False, force=False):
|
||||||
|
|
||||||
|
|
||||||
def get_sessions_to_clear(user=None, keep_current=False):
|
def get_sessions_to_clear(user=None, keep_current=False):
|
||||||
"""Returns sessions of the current user. Called at login / logout
|
"""Return sessions of the current user. Called at login / logout.
|
||||||
|
|
||||||
:param user: user name (default: current user)
|
:param user: user name (default: current user)
|
||||||
:param keep_current: keep current session (default: false)
|
:param keep_current: keep current session (default: false)
|
||||||
|
|
@ -109,7 +109,7 @@ def clear_all_sessions(reason=None):
|
||||||
|
|
||||||
|
|
||||||
def get_expired_sessions():
|
def get_expired_sessions():
|
||||||
"""Returns list of expired sessions"""
|
"""Return list of expired sessions."""
|
||||||
|
|
||||||
sessions = frappe.qb.DocType("Sessions")
|
sessions = frappe.qb.DocType("Sessions")
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -43,14 +43,7 @@ CLI_CONTEXT = frappe._dict(sites=[TEST_SITE])
|
||||||
|
|
||||||
|
|
||||||
def clean(value) -> str:
|
def clean(value) -> str:
|
||||||
"""Strips and converts bytes to str
|
"""Strip and convert bytes to str."""
|
||||||
|
|
||||||
Args:
|
|
||||||
value ([type]): [description]
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
[type]: [description]
|
|
||||||
"""
|
|
||||||
if isinstance(value, bytes):
|
if isinstance(value, bytes):
|
||||||
value = value.decode()
|
value = value.decode()
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
|
|
@ -59,13 +52,13 @@ def clean(value) -> str:
|
||||||
|
|
||||||
|
|
||||||
def missing_in_backup(doctypes: list, file: os.PathLike) -> list:
|
def missing_in_backup(doctypes: list, file: os.PathLike) -> list:
|
||||||
"""Returns list of missing doctypes in the backup.
|
"""Return list of missing doctypes in the backup.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
doctypes (list): List of DocTypes to be checked
|
doctypes (list): List of DocTypes to be checked
|
||||||
file (str): Path of the database file
|
file (str): Path of the database file
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
doctypes(list): doctypes that are missing in backup
|
doctypes(list): doctypes that are missing in backup
|
||||||
"""
|
"""
|
||||||
predicate = 'COPY public."tab{}"' if frappe.conf.db_type == "postgres" else "CREATE TABLE `tab{}`"
|
predicate = 'COPY public."tab{}"' if frappe.conf.db_type == "postgres" else "CREATE TABLE `tab{}`"
|
||||||
|
|
@ -76,14 +69,13 @@ def missing_in_backup(doctypes: list, file: os.PathLike) -> list:
|
||||||
|
|
||||||
|
|
||||||
def exists_in_backup(doctypes: list, file: os.PathLike) -> bool:
|
def exists_in_backup(doctypes: list, file: os.PathLike) -> bool:
|
||||||
"""Checks if the list of doctypes exist in the database.sql.gz file supplied
|
"""Check if the list of doctypes exist in the database.sql.gz file supplied.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
doctypes (list): List of DocTypes to be checked
|
doctypes (list): List of DocTypes to be checked
|
||||||
file (str): Path of the database file
|
file (str): Path of the database file
|
||||||
|
|
||||||
Returns:
|
Return True if all tables exist.
|
||||||
bool: True if all tables exist
|
|
||||||
"""
|
"""
|
||||||
missing_doctypes = missing_in_backup(doctypes, file)
|
missing_doctypes = missing_in_backup(doctypes, file)
|
||||||
return len(missing_doctypes) == 0
|
return len(missing_doctypes) == 0
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ def set_default_language(lang):
|
||||||
|
|
||||||
|
|
||||||
def get_lang_dict():
|
def get_lang_dict():
|
||||||
"""Returns all languages in dict format, full name is the key e.g. `{"english":"en"}`"""
|
"""Return all languages in dict format, full name is the key e.g. `{"english":"en"}`."""
|
||||||
return dict(
|
return dict(
|
||||||
frappe.get_all("Language", fields=["language_name", "name"], order_by="modified", as_list=True)
|
frappe.get_all("Language", fields=["language_name", "name"], order_by="modified", as_list=True)
|
||||||
)
|
)
|
||||||
|
|
@ -267,7 +267,7 @@ def clear_cache():
|
||||||
|
|
||||||
|
|
||||||
def get_messages_for_app(app, deduplicate=True):
|
def get_messages_for_app(app, deduplicate=True):
|
||||||
"""Returns all messages (list) for a specified `app`"""
|
"""Return all messages (list) for a specified `app`."""
|
||||||
messages = []
|
messages = []
|
||||||
modules = [frappe.unscrub(m) for m in frappe.local.app_modules[app]]
|
modules = [frappe.unscrub(m) for m in frappe.local.app_modules[app]]
|
||||||
|
|
||||||
|
|
@ -479,12 +479,12 @@ def get_messages_from_custom_fields(app_name):
|
||||||
|
|
||||||
|
|
||||||
def get_messages_from_page(name):
|
def get_messages_from_page(name):
|
||||||
"""Returns all translatable strings from a :class:`frappe.core.doctype.Page`"""
|
"""Return all translatable strings from a :class:`frappe.core.doctype.Page`."""
|
||||||
return _get_messages_from_page_or_report("Page", name)
|
return _get_messages_from_page_or_report("Page", name)
|
||||||
|
|
||||||
|
|
||||||
def get_messages_from_report(name):
|
def get_messages_from_report(name):
|
||||||
"""Returns all translatable strings from a :class:`frappe.core.doctype.Report`"""
|
"""Return all translatable strings from a :class:`frappe.core.doctype.Report`."""
|
||||||
report = frappe.get_doc("Report", name)
|
report = frappe.get_doc("Report", name)
|
||||||
messages = _get_messages_from_page_or_report(
|
messages = _get_messages_from_page_or_report(
|
||||||
"Report", name, frappe.db.get_value("DocType", report.ref_doctype, "module")
|
"Report", name, frappe.db.get_value("DocType", report.ref_doctype, "module")
|
||||||
|
|
@ -550,7 +550,7 @@ def get_server_messages(app):
|
||||||
|
|
||||||
|
|
||||||
def get_messages_from_include_files(app_name=None):
|
def get_messages_from_include_files(app_name=None):
|
||||||
"""Returns messages from js files included at time of boot like desk.min.js for desk and web"""
|
"""Return messages from js files included at time of boot like desk.min.js for desk and web."""
|
||||||
from frappe.utils.jinja_globals import bundled_asset
|
from frappe.utils.jinja_globals import bundled_asset
|
||||||
|
|
||||||
messages = []
|
messages = []
|
||||||
|
|
@ -584,7 +584,7 @@ def get_all_messages_from_js_files(app_name=None):
|
||||||
|
|
||||||
|
|
||||||
def get_messages_from_file(path: str) -> list[tuple[str, str, str | None, int]]:
|
def get_messages_from_file(path: str) -> list[tuple[str, str, str | None, int]]:
|
||||||
"""Returns a list of transatable strings from a code file
|
"""Return a list of transatable strings from a code file.
|
||||||
|
|
||||||
:param path: path of the code file
|
:param path: path of the code file
|
||||||
"""
|
"""
|
||||||
|
|
@ -913,7 +913,7 @@ def write_csv_file(path, app_messages, lang_dict):
|
||||||
|
|
||||||
|
|
||||||
def get_untranslated(lang, untranslated_file, get_all=False, app="_ALL_APPS"):
|
def get_untranslated(lang, untranslated_file, get_all=False, app="_ALL_APPS"):
|
||||||
"""Returns all untranslated strings for a language and writes in a file
|
"""Return all untranslated strings for a language and write in a file.
|
||||||
|
|
||||||
:param lang: Language code.
|
:param lang: Language code.
|
||||||
:param untranslated_file: Output file path.
|
:param untranslated_file: Output file path.
|
||||||
|
|
@ -1188,7 +1188,7 @@ def get_translator_url():
|
||||||
|
|
||||||
@frappe.whitelist(allow_guest=True)
|
@frappe.whitelist(allow_guest=True)
|
||||||
def get_all_languages(with_language_name: bool = False) -> list:
|
def get_all_languages(with_language_name: bool = False) -> list:
|
||||||
"""Returns all enabled language codes ar, ch etc"""
|
"""Return all enabled language codes ar, ch etc."""
|
||||||
|
|
||||||
def get_language_codes():
|
def get_language_codes():
|
||||||
return frappe.get_all("Language", filters={"enabled": 1}, pluck="name")
|
return frappe.get_all("Language", filters={"enabled": 1}, pluck="name")
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ def toggle_two_factor_auth(state, roles=None):
|
||||||
|
|
||||||
|
|
||||||
def two_factor_is_enabled(user=None):
|
def two_factor_is_enabled(user=None):
|
||||||
"""Returns True if 2FA is enabled."""
|
"""Return True if 2FA is enabled."""
|
||||||
enabled = cint(frappe.db.get_single_value("System Settings", "enable_two_factor_auth"))
|
enabled = cint(frappe.db.get_single_value("System Settings", "enable_two_factor_auth"))
|
||||||
if enabled:
|
if enabled:
|
||||||
bypass_two_factor_auth = cint(
|
bypass_two_factor_auth = cint(
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ def validate_phone_number_with_country_code(phone_number: str, fieldname: str) -
|
||||||
|
|
||||||
|
|
||||||
def validate_phone_number(phone_number, throw=False):
|
def validate_phone_number(phone_number, throw=False):
|
||||||
"""Returns True if valid phone number"""
|
"""Return True if valid phone number."""
|
||||||
if not phone_number:
|
if not phone_number:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
@ -139,9 +139,10 @@ def validate_phone_number(phone_number, throw=False):
|
||||||
|
|
||||||
|
|
||||||
def validate_name(name, throw=False):
|
def validate_name(name, throw=False):
|
||||||
"""Returns True if the name is valid
|
"""Return True if the name is valid
|
||||||
valid names may have unicode and ascii characters, dash, quotes, numbers
|
|
||||||
anything else is considered invalid
|
* valid names may have unicode and ascii characters, dash, quotes, numbers
|
||||||
|
* anything else is considered invalid
|
||||||
|
|
||||||
Note: "Name" here is name of a person, not the primary key in Frappe doctypes.
|
Note: "Name" here is name of a person, not the primary key in Frappe doctypes.
|
||||||
"""
|
"""
|
||||||
|
|
@ -219,14 +220,11 @@ def validate_url(
|
||||||
valid_schemes: str | Container[str] | None = None,
|
valid_schemes: str | Container[str] | None = None,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
Checks whether `txt` has a valid URL string
|
Return True if `txt` represents a valid URL.
|
||||||
|
|
||||||
Parameters:
|
Args:
|
||||||
throw (`bool`): throws a validationError if URL is not valid
|
throw: throws a validationError if URL is not valid
|
||||||
valid_schemes (`str` or `list`): if provided checks the given URL's scheme against this
|
valid_schemes: if provided checks the given URL's scheme against this
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: if `txt` represents a valid URL
|
|
||||||
"""
|
"""
|
||||||
url = urlparse(txt)
|
url = urlparse(txt)
|
||||||
is_valid = bool(url.netloc)
|
is_valid = bool(url.netloc)
|
||||||
|
|
@ -252,7 +250,7 @@ def random_string(length: int) -> str:
|
||||||
|
|
||||||
|
|
||||||
def has_gravatar(email: str) -> str:
|
def has_gravatar(email: str) -> str:
|
||||||
"""Returns gravatar url if user has set an avatar at gravatar.com"""
|
"""Return gravatar url if user has set an avatar at gravatar.com."""
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
if frappe.flags.in_import or frappe.flags.in_install or frappe.flags.in_test:
|
if frappe.flags.in_import or frappe.flags.in_install or frappe.flags.in_test:
|
||||||
|
|
@ -285,9 +283,7 @@ def get_gravatar(email: str) -> str:
|
||||||
|
|
||||||
|
|
||||||
def get_traceback(with_context=False) -> str:
|
def get_traceback(with_context=False) -> str:
|
||||||
"""
|
"""Return the traceback of the Exception."""
|
||||||
Returns the traceback of the Exception
|
|
||||||
"""
|
|
||||||
from traceback_with_variables import iter_exc_lines
|
from traceback_with_variables import iter_exc_lines
|
||||||
|
|
||||||
exc_type, exc_value, exc_tb = sys.exc_info()
|
exc_type, exc_value, exc_tb = sys.exc_info()
|
||||||
|
|
@ -350,9 +346,7 @@ def log(event, details):
|
||||||
|
|
||||||
|
|
||||||
def dict_to_str(args: dict[str, Any], sep: str = "&") -> str:
|
def dict_to_str(args: dict[str, Any], sep: str = "&") -> str:
|
||||||
"""
|
"""Convert a dictionary to URL."""
|
||||||
Converts a dictionary to URL
|
|
||||||
"""
|
|
||||||
return sep.join(f"{str(k)}=" + quote(str(args[k] or "")) for k in list(args))
|
return sep.join(f"{str(k)}=" + quote(str(args[k] or "")) for k in list(args))
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -383,9 +377,7 @@ def set_default(key, val):
|
||||||
|
|
||||||
|
|
||||||
def remove_blanks(d: dict) -> dict:
|
def remove_blanks(d: dict) -> dict:
|
||||||
"""
|
"""Return d with empty ('' or None) values stripped. Mutates inplace."""
|
||||||
Returns d with empty ('' or None) values stripped. Mutates inplace.
|
|
||||||
"""
|
|
||||||
for k, v in tuple(d.items()):
|
for k, v in tuple(d.items()):
|
||||||
if v == "" or v == None:
|
if v == "" or v == None:
|
||||||
del d[k]
|
del d[k]
|
||||||
|
|
@ -393,14 +385,12 @@ def remove_blanks(d: dict) -> dict:
|
||||||
|
|
||||||
|
|
||||||
def strip_html_tags(text):
|
def strip_html_tags(text):
|
||||||
"""Remove html tags from text"""
|
"""Remove html tags from the given `text`."""
|
||||||
return HTML_TAGS_PATTERN.sub("", text)
|
return HTML_TAGS_PATTERN.sub("", text)
|
||||||
|
|
||||||
|
|
||||||
def get_file_timestamp(fn):
|
def get_file_timestamp(fn):
|
||||||
"""
|
"""Return timestamp of the given file."""
|
||||||
Returns timestamp of the given file
|
|
||||||
"""
|
|
||||||
from frappe.utils import cint
|
from frappe.utils import cint
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -566,7 +556,7 @@ def touch_file(path):
|
||||||
|
|
||||||
|
|
||||||
def get_test_client(use_cookies=True) -> Client:
|
def get_test_client(use_cookies=True) -> Client:
|
||||||
"""Returns an test instance of the Frappe WSGI"""
|
"""Return an test instance of the Frappe WSGI."""
|
||||||
from frappe.app import application
|
from frappe.app import application
|
||||||
|
|
||||||
return Client(application, use_cookies=use_cookies)
|
return Client(application, use_cookies=use_cookies)
|
||||||
|
|
@ -590,7 +580,7 @@ def call_hook_method(hook, *args, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
def is_cli() -> bool:
|
def is_cli() -> bool:
|
||||||
"""Returns True if current instance is being run via a terminal"""
|
"""Return True if current instance is being run via a terminal."""
|
||||||
invoked_from_terminal = False
|
invoked_from_terminal = False
|
||||||
try:
|
try:
|
||||||
invoked_from_terminal = bool(os.get_terminal_size())
|
invoked_from_terminal = bool(os.get_terminal_size())
|
||||||
|
|
@ -835,11 +825,12 @@ def parse_json(val):
|
||||||
|
|
||||||
def get_db_count(*args):
|
def get_db_count(*args):
|
||||||
"""
|
"""
|
||||||
Pass a doctype or a series of doctypes to get the count of docs in them
|
Pass a doctype or a series of doctypes to get the count of docs in them.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
*args: Variable length argument list of doctype names whose doc count you need
|
*args: Variable length argument list of doctype names whose doc count you need
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
dict: A dict with the count values.
|
dict: A dict with the count values.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
@ -859,7 +850,7 @@ def call(fn, *args, **kwargs):
|
||||||
Parameters:
|
Parameters:
|
||||||
fn: frappe function to be called
|
fn: frappe function to be called
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
based on the function you call: output of the function you call
|
based on the function you call: output of the function you call
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
@ -912,7 +903,7 @@ def get_safe_filters(filters):
|
||||||
|
|
||||||
|
|
||||||
def create_batch(iterable: Iterable, size: int) -> Generator[Iterable, None, None]:
|
def create_batch(iterable: Iterable, size: int) -> Generator[Iterable, None, None]:
|
||||||
"""Convert an iterable to multiple batches of constant size of batch_size
|
"""Convert an iterable to multiple batches of constant size of batch_size.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
iterable (Iterable): Iterable object which is subscriptable
|
iterable (Iterable): Iterable object which is subscriptable
|
||||||
|
|
@ -992,12 +983,12 @@ def get_assets_json():
|
||||||
|
|
||||||
|
|
||||||
def get_bench_relative_path(file_path):
|
def get_bench_relative_path(file_path):
|
||||||
"""Fixes paths relative to the bench root directory if exists and returns the absolute path
|
"""Fix paths relative to the bench root directory if exists and return the absolute path.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
file_path (str, Path): Path of a file that exists on the file system
|
file_path (str, Path): Path of a file that exists on the file system
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
str: Absolute path of the file_path
|
str: Absolute path of the file_path
|
||||||
"""
|
"""
|
||||||
if not os.path.exists(file_path):
|
if not os.path.exists(file_path):
|
||||||
|
|
|
||||||
|
|
@ -394,7 +394,7 @@ def get_queue_list(queue_list=None, build_queue_name=False):
|
||||||
|
|
||||||
|
|
||||||
def get_workers(queue=None):
|
def get_workers(queue=None):
|
||||||
"""Returns a list of Worker objects tied to a queue object if queue is passed, else returns a list of all workers"""
|
"""Return a list of Worker objects tied to a queue object if queue is passed, else return a list of all workers."""
|
||||||
if queue:
|
if queue:
|
||||||
return Worker.all(queue=queue)
|
return Worker.all(queue=queue)
|
||||||
else:
|
else:
|
||||||
|
|
@ -402,7 +402,7 @@ def get_workers(queue=None):
|
||||||
|
|
||||||
|
|
||||||
def get_running_jobs_in_queue(queue):
|
def get_running_jobs_in_queue(queue):
|
||||||
"""Returns a list of Jobs objects that are tied to a queue object and are currently running"""
|
"""Return a list of Jobs objects that are tied to a queue object and are currently running."""
|
||||||
jobs = []
|
jobs = []
|
||||||
workers = get_workers(queue)
|
workers = get_workers(queue)
|
||||||
for worker in workers:
|
for worker in workers:
|
||||||
|
|
@ -413,7 +413,7 @@ def get_running_jobs_in_queue(queue):
|
||||||
|
|
||||||
|
|
||||||
def get_queue(qtype, is_async=True):
|
def get_queue(qtype, is_async=True):
|
||||||
"""Returns a Queue object tied to a redis connection"""
|
"""Return a Queue object tied to a redis connection."""
|
||||||
validate_queue(qtype)
|
validate_queue(qtype)
|
||||||
return Queue(generate_qname(qtype), connection=get_redis_conn(), is_async=is_async)
|
return Queue(generate_qname(qtype), connection=get_redis_conn(), is_async=is_async)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -475,11 +475,12 @@ download only after 24 hours.""".format(
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def fetch_latest_backups(partial=False):
|
def fetch_latest_backups(partial=False) -> dict:
|
||||||
"""Fetches paths of the latest backup taken in the last 30 days
|
"""Fetch paths of the latest backup taken in the last 30 days.
|
||||||
Only for: System Managers
|
|
||||||
|
|
||||||
Returns:
|
Note: Only for System Managers
|
||||||
|
|
||||||
|
Return:
|
||||||
dict: relative Backup Paths
|
dict: relative Backup Paths
|
||||||
"""
|
"""
|
||||||
frappe.only_for("System Manager")
|
frappe.only_for("System Manager")
|
||||||
|
|
@ -583,13 +584,8 @@ def delete_temp_backups(older_than=24):
|
||||||
os.remove(this_file_path)
|
os.remove(this_file_path)
|
||||||
|
|
||||||
|
|
||||||
def is_file_old(file_path, older_than=24):
|
def is_file_old(file_path, older_than=24) -> bool:
|
||||||
"""
|
"""Return True if file exists and is older than specified hours."""
|
||||||
Checks if file exists and is older than specified hours
|
|
||||||
Returns ->
|
|
||||||
True: file does not exist or file is old
|
|
||||||
False: file is new
|
|
||||||
"""
|
|
||||||
if os.path.isfile(file_path):
|
if os.path.isfile(file_path):
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ def get_versions():
|
||||||
|
|
||||||
|
|
||||||
def get_app_branch(app):
|
def get_app_branch(app):
|
||||||
"""Returns branch of an app"""
|
"""Return branch of an app."""
|
||||||
try:
|
try:
|
||||||
with open(os.devnull, "wb") as null_stream:
|
with open(os.devnull, "wb") as null_stream:
|
||||||
result = subprocess.check_output(
|
result = subprocess.check_output(
|
||||||
|
|
@ -198,15 +198,14 @@ def check_for_update():
|
||||||
add_message_to_redis(updates)
|
add_message_to_redis(updates)
|
||||||
|
|
||||||
|
|
||||||
def parse_latest_non_beta_release(response):
|
def parse_latest_non_beta_release(response: list) -> list | None:
|
||||||
"""
|
"""Parse the response JSON for all the releases and return the latest non prerelease.
|
||||||
Parses the response JSON for all the releases and returns the latest non prerelease
|
|
||||||
|
Args:
|
||||||
|
|
||||||
Parameters
|
|
||||||
response (list): response object returned by github
|
response (list): response object returned by github
|
||||||
|
|
||||||
Returns
|
Return a json object pertaining to the latest non-beta release
|
||||||
json : json object pertaining to the latest non-beta release
|
|
||||||
"""
|
"""
|
||||||
version_list = [
|
version_list = [
|
||||||
release.get("tag_name").strip("v") for release in response if not release.get("prerelease")
|
release.get("tag_name").strip("v") for release in response if not release.get("prerelease")
|
||||||
|
|
@ -218,14 +217,13 @@ def parse_latest_non_beta_release(response):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def check_release_on_github(app: str):
|
def check_release_on_github(app: str) -> tuple | None:
|
||||||
"""
|
"""Check the latest release for a given Frappe application hosted on Github.
|
||||||
Check the latest release for a given Frappe application hosted on Github.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
app (str): The name of the Frappe application.
|
app: The name of the Frappe application.
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
tuple(Version, str): The semantic version object of the latest release and the
|
tuple(Version, str): The semantic version object of the latest release and the
|
||||||
organization name, if the application exists, otherwise None.
|
organization name, if the application exists, otherwise None.
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ def get_start_of_week_index() -> int:
|
||||||
|
|
||||||
|
|
||||||
def is_invalid_date_string(date_string: str) -> bool:
|
def is_invalid_date_string(date_string: str) -> bool:
|
||||||
"""Returns True if the date string is invalid or None or empty."""
|
"""Return True if the date string is invalid or None or empty."""
|
||||||
# dateutil parser does not agree with dates like "0001-01-01" or "0000-00-00"
|
# dateutil parser does not agree with dates like "0001-01-01" or "0000-00-00"
|
||||||
return not isinstance(date_string, str) or (
|
return not isinstance(date_string, str) or (
|
||||||
(not date_string) or (date_string or "").startswith(("0001-01-01", "0000-00-00"))
|
(not date_string) or (date_string or "").startswith(("0001-01-01", "0000-00-00"))
|
||||||
|
|
@ -101,7 +101,7 @@ def getdate(
|
||||||
string_date: Optional["DateTimeLikeObject"] = None, parse_day_first: bool = False
|
string_date: Optional["DateTimeLikeObject"] = None, parse_day_first: bool = False
|
||||||
) -> datetime.date | None:
|
) -> datetime.date | None:
|
||||||
"""
|
"""
|
||||||
Converts string date (yyyy-mm-dd) to datetime.date object.
|
Convert string date (yyyy-mm-dd) to datetime.date object.
|
||||||
If no input is provided, current date is returned.
|
If no input is provided, current date is returned.
|
||||||
"""
|
"""
|
||||||
if not string_date:
|
if not string_date:
|
||||||
|
|
@ -126,7 +126,7 @@ def getdate(
|
||||||
def get_datetime(
|
def get_datetime(
|
||||||
datetime_str: Optional["DateTimeLikeObject"] = None,
|
datetime_str: Optional["DateTimeLikeObject"] = None,
|
||||||
) -> datetime.datetime | None:
|
) -> datetime.datetime | None:
|
||||||
"""Returns the below mentioned values based on the given `datetime_str`:
|
"""Return the below mentioned values based on the given `datetime_str`:
|
||||||
|
|
||||||
* If `datetime_str` is None, returns datetime object of current datetime
|
* If `datetime_str` is None, returns datetime object of current datetime
|
||||||
* If `datetime_str` is already a datetime object, returns the same
|
* If `datetime_str` is already a datetime object, returns the same
|
||||||
|
|
@ -159,8 +159,9 @@ def get_datetime(
|
||||||
|
|
||||||
|
|
||||||
def get_timedelta(time: str | None = None) -> datetime.timedelta | None:
|
def get_timedelta(time: str | None = None) -> datetime.timedelta | None:
|
||||||
"""Return `datetime.timedelta` object from string value of a
|
"""Return `datetime.timedelta` object from string value of a valid time format.
|
||||||
valid time format. Returns None if `time` is not a valid format
|
|
||||||
|
Return None if `time` is not a valid format.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
time (str): A valid time representation. This string is parsed
|
time (str): A valid time representation. This string is parsed
|
||||||
|
|
@ -168,7 +169,7 @@ def get_timedelta(time: str | None = None) -> datetime.timedelta | None:
|
||||||
'0:0:0', '17:21:00', '2012-01-19 17:21:00'. Checkout
|
'0:0:0', '17:21:00', '2012-01-19 17:21:00'. Checkout
|
||||||
https://dateutil.readthedocs.io/en/stable/parser.html#dateutil.parser.parse
|
https://dateutil.readthedocs.io/en/stable/parser.html#dateutil.parser.parse
|
||||||
|
|
||||||
Returns:
|
Return:
|
||||||
datetime.timedelta: Timedelta object equivalent of the passed `time` string
|
datetime.timedelta: Timedelta object equivalent of the passed `time` string
|
||||||
"""
|
"""
|
||||||
time = time or "0:0:0"
|
time = time or "0:0:0"
|
||||||
|
|
@ -188,7 +189,7 @@ def get_timedelta(time: str | None = None) -> datetime.timedelta | None:
|
||||||
|
|
||||||
|
|
||||||
def to_timedelta(time_str: str | datetime.time) -> datetime.timedelta:
|
def to_timedelta(time_str: str | datetime.time) -> datetime.timedelta:
|
||||||
"""Returns a `datetime.timedelta` object from the given string or `datetime.time` object.
|
"""Return a `datetime.timedelta` object from the given string or `datetime.time` object.
|
||||||
If the given argument is not a string or a `datetime.time` object, it is returned as is.
|
If the given argument is not a string or a `datetime.time` object, it is returned as is.
|
||||||
"""
|
"""
|
||||||
if isinstance(time_str, datetime.time):
|
if isinstance(time_str, datetime.time):
|
||||||
|
|
@ -295,32 +296,32 @@ def add_to_date(
|
||||||
|
|
||||||
|
|
||||||
def add_days(date: DateTimeLikeObject, days: NumericType) -> DateTimeLikeObject:
|
def add_days(date: DateTimeLikeObject, days: NumericType) -> DateTimeLikeObject:
|
||||||
"""Returns a new date after adding the given number of `days` to the given `date`."""
|
"""Return a new date after adding the given number of `days` to the given `date`."""
|
||||||
return add_to_date(date, days=days)
|
return add_to_date(date, days=days)
|
||||||
|
|
||||||
|
|
||||||
def add_months(date: DateTimeLikeObject, months: NumericType) -> DateTimeLikeObject:
|
def add_months(date: DateTimeLikeObject, months: NumericType) -> DateTimeLikeObject:
|
||||||
"""Returns a new date after adding the given number of `months` to the given `date`."""
|
"""Return a new date after adding the given number of `months` to the given `date`."""
|
||||||
return add_to_date(date, months=months)
|
return add_to_date(date, months=months)
|
||||||
|
|
||||||
|
|
||||||
def add_years(date: DateTimeLikeObject, years: NumericType) -> DateTimeLikeObject:
|
def add_years(date: DateTimeLikeObject, years: NumericType) -> DateTimeLikeObject:
|
||||||
"""Returns a new date after adding the given number of `years` to the given `date`."""
|
"""Return a new date after adding the given number of `years` to the given `date`."""
|
||||||
return add_to_date(date, years=years)
|
return add_to_date(date, years=years)
|
||||||
|
|
||||||
|
|
||||||
def date_diff(string_ed_date: DateTimeLikeObject, string_st_date: DateTimeLikeObject) -> int:
|
def date_diff(string_ed_date: DateTimeLikeObject, string_st_date: DateTimeLikeObject) -> int:
|
||||||
"""Returns the difference between given two dates in days."""
|
"""Return the difference between given two dates in days."""
|
||||||
return days_diff(string_ed_date, string_st_date)
|
return days_diff(string_ed_date, string_st_date)
|
||||||
|
|
||||||
|
|
||||||
def days_diff(string_ed_date: DateTimeLikeObject, string_st_date: DateTimeLikeObject) -> int:
|
def days_diff(string_ed_date: DateTimeLikeObject, string_st_date: DateTimeLikeObject) -> int:
|
||||||
"""Returns the difference between given two dates in days."""
|
"""Return the difference between given two dates in days."""
|
||||||
return (getdate(string_ed_date) - getdate(string_st_date)).days
|
return (getdate(string_ed_date) - getdate(string_st_date)).days
|
||||||
|
|
||||||
|
|
||||||
def month_diff(string_ed_date: DateTimeLikeObject, string_st_date: DateTimeLikeObject) -> int:
|
def month_diff(string_ed_date: DateTimeLikeObject, string_st_date: DateTimeLikeObject) -> int:
|
||||||
"""Returns the difference between given two dates in months."""
|
"""Return the difference between given two dates in months."""
|
||||||
ed_date = getdate(string_ed_date)
|
ed_date = getdate(string_ed_date)
|
||||||
st_date = getdate(string_st_date)
|
st_date = getdate(string_st_date)
|
||||||
return (ed_date.year - st_date.year) * 12 + ed_date.month - st_date.month + 1
|
return (ed_date.year - st_date.year) * 12 + ed_date.month - st_date.month + 1
|
||||||
|
|
@ -329,32 +330,32 @@ def month_diff(string_ed_date: DateTimeLikeObject, string_st_date: DateTimeLikeO
|
||||||
def time_diff(
|
def time_diff(
|
||||||
string_ed_date: DateTimeLikeObject, string_st_date: DateTimeLikeObject
|
string_ed_date: DateTimeLikeObject, string_st_date: DateTimeLikeObject
|
||||||
) -> datetime.timedelta:
|
) -> datetime.timedelta:
|
||||||
"""Returns the difference between given two dates as `datetime.timedelta` object."""
|
"""Return the difference between given two dates as `datetime.timedelta` object."""
|
||||||
return get_datetime(string_ed_date) - get_datetime(string_st_date)
|
return get_datetime(string_ed_date) - get_datetime(string_st_date)
|
||||||
|
|
||||||
|
|
||||||
def time_diff_in_seconds(
|
def time_diff_in_seconds(
|
||||||
string_ed_date: DateTimeLikeObject, string_st_date: DateTimeLikeObject
|
string_ed_date: DateTimeLikeObject, string_st_date: DateTimeLikeObject
|
||||||
) -> float:
|
) -> float:
|
||||||
"""Returns the difference between given two dates in seconds."""
|
"""Return the difference between given two dates in seconds."""
|
||||||
return time_diff(string_ed_date, string_st_date).total_seconds()
|
return time_diff(string_ed_date, string_st_date).total_seconds()
|
||||||
|
|
||||||
|
|
||||||
def time_diff_in_hours(
|
def time_diff_in_hours(
|
||||||
string_ed_date: DateTimeLikeObject, string_st_date: DateTimeLikeObject
|
string_ed_date: DateTimeLikeObject, string_st_date: DateTimeLikeObject
|
||||||
) -> float:
|
) -> float:
|
||||||
"""Returns the difference between given two dates in hours."""
|
"""Return the difference between given two dates in hours."""
|
||||||
return round(float(time_diff(string_ed_date, string_st_date).total_seconds()) / 3600, 6)
|
return round(float(time_diff(string_ed_date, string_st_date).total_seconds()) / 3600, 6)
|
||||||
|
|
||||||
|
|
||||||
def now_datetime() -> datetime.datetime:
|
def now_datetime() -> datetime.datetime:
|
||||||
"""Returns the current datetime in system timezone."""
|
"""Return the current datetime in system timezone."""
|
||||||
dt = convert_utc_to_system_timezone(datetime.datetime.now(pytz.UTC))
|
dt = convert_utc_to_system_timezone(datetime.datetime.now(pytz.UTC))
|
||||||
return dt.replace(tzinfo=None)
|
return dt.replace(tzinfo=None)
|
||||||
|
|
||||||
|
|
||||||
def get_timestamp(date: Optional["DateTimeLikeObject"] = None) -> float:
|
def get_timestamp(date: Optional["DateTimeLikeObject"] = None) -> float:
|
||||||
"""Returns the Unix timestamp (seconds since Epoch) for the given `date`.
|
"""Return the Unix timestamp (seconds since Epoch) for the given `date`.
|
||||||
If `date` is None, the current timestamp is returned.
|
If `date` is None, the current timestamp is returned.
|
||||||
"""
|
"""
|
||||||
return time.mktime(getdate(date).timetuple())
|
return time.mktime(getdate(date).timetuple())
|
||||||
|
|
@ -370,7 +371,7 @@ def _get_system_timezone():
|
||||||
|
|
||||||
|
|
||||||
def get_system_timezone() -> str:
|
def get_system_timezone() -> str:
|
||||||
"""Returns the system timezone."""
|
"""Return the system timezone."""
|
||||||
if frappe.local.flags.in_test:
|
if frappe.local.flags.in_test:
|
||||||
return _get_system_timezone()
|
return _get_system_timezone()
|
||||||
|
|
||||||
|
|
@ -389,19 +390,19 @@ def convert_utc_to_timezone(utc_timestamp: datetime.datetime, time_zone: str) ->
|
||||||
|
|
||||||
|
|
||||||
def get_datetime_in_timezone(time_zone: str) -> datetime.datetime:
|
def get_datetime_in_timezone(time_zone: str) -> datetime.datetime:
|
||||||
"""Returns the current datetime in the given timezone (e.g. 'Asia/Kolkata')."""
|
"""Return the current datetime in the given timezone (e.g. 'Asia/Kolkata')."""
|
||||||
utc_timestamp = datetime.datetime.now(pytz.UTC)
|
utc_timestamp = datetime.datetime.now(pytz.UTC)
|
||||||
return convert_utc_to_timezone(utc_timestamp, time_zone)
|
return convert_utc_to_timezone(utc_timestamp, time_zone)
|
||||||
|
|
||||||
|
|
||||||
def convert_utc_to_system_timezone(utc_timestamp: datetime.datetime) -> datetime.datetime:
|
def convert_utc_to_system_timezone(utc_timestamp: datetime.datetime) -> datetime.datetime:
|
||||||
"""Returns the given UTC `datetime` timestamp in system timezone."""
|
"""Return the given UTC `datetime` timestamp in system timezone."""
|
||||||
time_zone = get_system_timezone()
|
time_zone = get_system_timezone()
|
||||||
return convert_utc_to_timezone(utc_timestamp, time_zone)
|
return convert_utc_to_timezone(utc_timestamp, time_zone)
|
||||||
|
|
||||||
|
|
||||||
def now() -> str:
|
def now() -> str:
|
||||||
"""return current datetime as yyyy-mm-dd hh:mm:ss"""
|
"""Return current datetime as `yyyy-mm-dd hh:mm:ss`."""
|
||||||
if frappe.flags.current_date:
|
if frappe.flags.current_date:
|
||||||
return (
|
return (
|
||||||
getdate(frappe.flags.current_date).strftime(DATE_FORMAT)
|
getdate(frappe.flags.current_date).strftime(DATE_FORMAT)
|
||||||
|
|
@ -413,17 +414,17 @@ def now() -> str:
|
||||||
|
|
||||||
|
|
||||||
def nowdate() -> str:
|
def nowdate() -> str:
|
||||||
"""return current date as yyyy-mm-dd"""
|
"""Return current date as `yyyy-mm-dd`."""
|
||||||
return now_datetime().strftime(DATE_FORMAT)
|
return now_datetime().strftime(DATE_FORMAT)
|
||||||
|
|
||||||
|
|
||||||
def today() -> str:
|
def today() -> str:
|
||||||
"""Returns today's date in `yyyy-mm-dd` format."""
|
"""Return today's date in `yyyy-mm-dd` format."""
|
||||||
return nowdate()
|
return nowdate()
|
||||||
|
|
||||||
|
|
||||||
def get_abbr(string: str, max_len: int = 2) -> str:
|
def get_abbr(string: str, max_len: int = 2) -> str:
|
||||||
"""Returns the abbreviation of the given string.
|
"""Return the abbreviation of the given string.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
|
|
@ -431,7 +432,7 @@ def get_abbr(string: str, max_len: int = 2) -> str:
|
||||||
* "Jenny Jane Doe" => "JJ" (default, `max_len` = 2)
|
* "Jenny Jane Doe" => "JJ" (default, `max_len` = 2)
|
||||||
* "Jenny Jane Doe" => "JJD" (`max_len` = 3)
|
* "Jenny Jane Doe" => "JJD" (`max_len` = 3)
|
||||||
|
|
||||||
Returns "?" if the given string is empty.
|
Return "?" if the given string is empty.
|
||||||
"""
|
"""
|
||||||
abbr = ""
|
abbr = ""
|
||||||
for part in string.split(" "):
|
for part in string.split(" "):
|
||||||
|
|
@ -442,7 +443,7 @@ def get_abbr(string: str, max_len: int = 2) -> str:
|
||||||
|
|
||||||
|
|
||||||
def nowtime() -> str:
|
def nowtime() -> str:
|
||||||
"""Returns current time (system timezone) in `hh:mm:ss` format."""
|
"""Return current time (system timezone) in `hh:mm:ss` format."""
|
||||||
return now_datetime().strftime(TIME_FORMAT)
|
return now_datetime().strftime(TIME_FORMAT)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -460,9 +461,9 @@ def get_first_day(dt, d_years=0, d_months=0, as_str: Literal[True] = False) -> s
|
||||||
def get_first_day(
|
def get_first_day(
|
||||||
dt, d_years: int = 0, d_months: int = 0, as_str: bool = False
|
dt, d_years: int = 0, d_months: int = 0, as_str: bool = False
|
||||||
) -> str | datetime.date:
|
) -> str | datetime.date:
|
||||||
"""
|
"""Return the first day of the month for the date specified by date object.
|
||||||
Returns the first day of the month for the date specified by date object
|
|
||||||
Also adds `d_years` and `d_months` if specified
|
Also, add `d_years` and `d_months` if specified.
|
||||||
"""
|
"""
|
||||||
dt = getdate(dt)
|
dt = getdate(dt)
|
||||||
|
|
||||||
|
|
@ -492,7 +493,7 @@ def get_quarter_start(dt: DateTimeLikeObject | None = None, as_str: Literal[True
|
||||||
def get_quarter_start(
|
def get_quarter_start(
|
||||||
dt: DateTimeLikeObject | None = None, as_str: bool = False
|
dt: DateTimeLikeObject | None = None, as_str: bool = False
|
||||||
) -> str | datetime.date:
|
) -> str | datetime.date:
|
||||||
"""Returns the start date of the quarter for the given datetime like object (`dt`).
|
"""Return the start date of the quarter for the given datetime like object (`dt`).
|
||||||
|
|
||||||
If `dt` is None, the current quarter start date is returned.
|
If `dt` is None, the current quarter start date is returned.
|
||||||
"""
|
"""
|
||||||
|
|
@ -513,7 +514,7 @@ def get_first_day_of_week(dt: DateTimeLikeObject, as_str: Literal[True] = False)
|
||||||
|
|
||||||
|
|
||||||
def get_first_day_of_week(dt: DateTimeLikeObject, as_str=False) -> datetime.date | str:
|
def get_first_day_of_week(dt: DateTimeLikeObject, as_str=False) -> datetime.date | str:
|
||||||
"""Returns the first day of the week (as per System Settings or Sunday by default) for the given datetime like object (`dt`).
|
"""Return the first day of the week (as per System Settings or Sunday by default) for the given datetime like object (`dt`).
|
||||||
|
|
||||||
If `as_str` is True, the first day of the week is returned as a string in `yyyy-mm-dd` format.
|
If `as_str` is True, the first day of the week is returned as a string in `yyyy-mm-dd` format.
|
||||||
"""
|
"""
|
||||||
|
|
@ -548,7 +549,7 @@ def get_year_start(dt: DateTimeLikeObject, as_str: Literal[True] = False) -> str
|
||||||
|
|
||||||
|
|
||||||
def get_year_start(dt: DateTimeLikeObject, as_str=False) -> str | datetime.date:
|
def get_year_start(dt: DateTimeLikeObject, as_str=False) -> str | datetime.date:
|
||||||
"""Returns the start date of the year for the given date (`dt`)."""
|
"""Return the start date of the year for the given date (`dt`)."""
|
||||||
dt = getdate(dt)
|
dt = getdate(dt)
|
||||||
date = datetime.date(dt.year, 1, 1)
|
date = datetime.date(dt.year, 1, 1)
|
||||||
return date.strftime(DATE_FORMAT) if as_str else date
|
return date.strftime(DATE_FORMAT) if as_str else date
|
||||||
|
|
@ -565,7 +566,7 @@ def get_last_day_of_week(dt: DateTimeLikeObject, as_str: Literal[True] = False)
|
||||||
|
|
||||||
|
|
||||||
def get_last_day_of_week(dt: DateTimeLikeObject, as_str=False) -> datetime.date | str:
|
def get_last_day_of_week(dt: DateTimeLikeObject, as_str=False) -> datetime.date | str:
|
||||||
"""Returns the last day of the week (first day is taken from System Settings or Sunday by default) for the given datetime like object (`dt`).
|
"""Return the last day of the week (first day is taken from System Settings or Sunday by default) for the given datetime like object (`dt`).
|
||||||
|
|
||||||
If `as_str` is True, the last day of the week is returned as a string in `yyyy-mm-dd` format.
|
If `as_str` is True, the last day of the week is returned as a string in `yyyy-mm-dd` format.
|
||||||
"""
|
"""
|
||||||
|
|
@ -575,8 +576,8 @@ def get_last_day_of_week(dt: DateTimeLikeObject, as_str=False) -> datetime.date
|
||||||
|
|
||||||
|
|
||||||
def get_last_day(dt):
|
def get_last_day(dt):
|
||||||
"""
|
"""Return last day of the month using:
|
||||||
Returns last day of the month using:
|
|
||||||
`get_first_day(dt, 0, 1) + datetime.timedelta(-1)`
|
`get_first_day(dt, 0, 1) + datetime.timedelta(-1)`
|
||||||
"""
|
"""
|
||||||
return get_first_day(dt, 0, 1) + datetime.timedelta(-1)
|
return get_first_day(dt, 0, 1) + datetime.timedelta(-1)
|
||||||
|
|
@ -603,7 +604,7 @@ def get_quarter_ending(dt: DateTimeLikeObject | None = None, as_str: Literal[Tru
|
||||||
def get_quarter_ending(
|
def get_quarter_ending(
|
||||||
date: DateTimeLikeObject | None = None, as_str=False
|
date: DateTimeLikeObject | None = None, as_str=False
|
||||||
) -> str | datetime.date:
|
) -> str | datetime.date:
|
||||||
"""Returns the end date of the quarter for the given datetime like object (`date`).
|
"""Return the end date of the quarter for the given datetime like object (`date`).
|
||||||
|
|
||||||
If `date` is None, the current quarter end date is returned.
|
If `date` is None, the current quarter end date is returned.
|
||||||
If `as_str` is True, the end date of the quarter is returned as a string in `yyyy-mm-dd` format.
|
If `as_str` is True, the end date of the quarter is returned as a string in `yyyy-mm-dd` format.
|
||||||
|
|
@ -635,7 +636,7 @@ def get_year_ending(dt: DateTimeLikeObject | None = None, as_str: Literal[True]
|
||||||
|
|
||||||
|
|
||||||
def get_year_ending(date: DateTimeLikeObject | None = None, as_str=False) -> datetime.date | str:
|
def get_year_ending(date: DateTimeLikeObject | None = None, as_str=False) -> datetime.date | str:
|
||||||
"""Returns the end date of the year for the given datetime like object (`date`).
|
"""Return the end date of the year for the given datetime like object (`date`).
|
||||||
|
|
||||||
If `date` is None, the current year end date is returned.
|
If `date` is None, the current year end date is returned.
|
||||||
If `as_str` is True, the end date of the year is returned as a string in `yyyy-mm-dd` format.
|
If `as_str` is True, the end date of the year is returned as a string in `yyyy-mm-dd` format.
|
||||||
|
|
@ -649,7 +650,7 @@ def get_year_ending(date: DateTimeLikeObject | None = None, as_str=False) -> dat
|
||||||
def get_time(
|
def get_time(
|
||||||
time_str: str | datetime.datetime | datetime.time | datetime.timedelta,
|
time_str: str | datetime.datetime | datetime.time | datetime.timedelta,
|
||||||
) -> datetime.time:
|
) -> datetime.time:
|
||||||
"""Returns a `datetime.time` object for the given `time_str`.
|
"""Return a `datetime.time` object for the given `time_str`.
|
||||||
|
|
||||||
If the given argument is already a `datetime.time` object, it is returned as is."""
|
If the given argument is already a `datetime.time` object, it is returned as is."""
|
||||||
|
|
||||||
|
|
@ -668,21 +669,21 @@ def get_time(
|
||||||
|
|
||||||
|
|
||||||
def get_datetime_str(datetime_obj: DateTimeLikeObject) -> str:
|
def get_datetime_str(datetime_obj: DateTimeLikeObject) -> str:
|
||||||
"""Returns the given datetime like object (datetime.date, datetime.datetime, string) as a string in `yyyy-mm-dd hh:mm:ss` format."""
|
"""Return the given datetime like object (datetime.date, datetime.datetime, string) as a string in `yyyy-mm-dd hh:mm:ss` format."""
|
||||||
if isinstance(datetime_obj, str):
|
if isinstance(datetime_obj, str):
|
||||||
datetime_obj = get_datetime(datetime_obj)
|
datetime_obj = get_datetime(datetime_obj)
|
||||||
return datetime_obj.strftime(DATETIME_FORMAT)
|
return datetime_obj.strftime(DATETIME_FORMAT)
|
||||||
|
|
||||||
|
|
||||||
def get_date_str(date_obj: DateTimeLikeObject) -> str:
|
def get_date_str(date_obj: DateTimeLikeObject) -> str:
|
||||||
"""Returns the given datetime like object (datetime.date, datetime.datetime, string) as a string in `yyyy-mm-dd` format."""
|
"""Return the given datetime like object (datetime.date, datetime.datetime, string) as a string in `yyyy-mm-dd` format."""
|
||||||
if isinstance(date_obj, str):
|
if isinstance(date_obj, str):
|
||||||
date_obj = get_datetime(date_obj)
|
date_obj = get_datetime(date_obj)
|
||||||
return date_obj.strftime(DATE_FORMAT)
|
return date_obj.strftime(DATE_FORMAT)
|
||||||
|
|
||||||
|
|
||||||
def get_time_str(timedelta_obj: datetime.timedelta | str) -> str:
|
def get_time_str(timedelta_obj: datetime.timedelta | str) -> str:
|
||||||
"""Returns the given timedelta object as a string in `hh:mm:ss` format."""
|
"""Return the given timedelta object as a string in `hh:mm:ss` format."""
|
||||||
if isinstance(timedelta_obj, str):
|
if isinstance(timedelta_obj, str):
|
||||||
timedelta_obj = to_timedelta(timedelta_obj)
|
timedelta_obj = to_timedelta(timedelta_obj)
|
||||||
|
|
||||||
|
|
@ -713,7 +714,8 @@ def get_user_time_format() -> str:
|
||||||
def format_date(
|
def format_date(
|
||||||
string_date=None, format_string: str | None = None, parse_day_first: bool = False
|
string_date=None, format_string: str | None = None, parse_day_first: bool = False
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Converts the given string date to :data:`user_date_format`
|
"""Convert the given string date to :data:`user_date_format`.
|
||||||
|
|
||||||
User format specified in defaults
|
User format specified in defaults
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
@ -746,7 +748,8 @@ formatdate = format_date # For backwards compatibility
|
||||||
|
|
||||||
|
|
||||||
def format_time(time_string=None, format_string: str | None = None) -> str:
|
def format_time(time_string=None, format_string: str | None = None) -> str:
|
||||||
"""Converts the given string time to :data:`user_time_format`
|
"""Convert the given string time to :data:`user_time_format`.
|
||||||
|
|
||||||
User format specified in defaults
|
User format specified in defaults
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
@ -773,7 +776,7 @@ def format_time(time_string=None, format_string: str | None = None) -> str:
|
||||||
|
|
||||||
|
|
||||||
def format_datetime(datetime_string: DateTimeLikeObject, format_string: str | None = None) -> str:
|
def format_datetime(datetime_string: DateTimeLikeObject, format_string: str | None = None) -> str:
|
||||||
"""Converts the given string time to :data:`user_datetime_format`
|
"""Convert the given string time to :data:`user_datetime_format`
|
||||||
User format specified in defaults
|
User format specified in defaults
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
@ -801,9 +804,9 @@ def format_datetime(datetime_string: DateTimeLikeObject, format_string: str | No
|
||||||
|
|
||||||
|
|
||||||
def format_duration(seconds, hide_days=False):
|
def format_duration(seconds, hide_days=False):
|
||||||
"""Converts the given duration value in float(seconds) to duration format
|
"""Convert the given duration value in float(seconds) to duration format.
|
||||||
|
|
||||||
example: converts 12885 to '3h 34m 45s' where 12885 = seconds in float
|
example: convert 12885 to '3h 34m 45s' where 12885 = seconds in float
|
||||||
"""
|
"""
|
||||||
|
|
||||||
seconds = cint(seconds)
|
seconds = cint(seconds)
|
||||||
|
|
@ -837,9 +840,9 @@ def format_duration(seconds, hide_days=False):
|
||||||
|
|
||||||
|
|
||||||
def duration_to_seconds(duration):
|
def duration_to_seconds(duration):
|
||||||
"""Converts the given duration formatted value to duration value in seconds
|
"""Convert the given duration formatted value to duration value in seconds.
|
||||||
|
|
||||||
example: converts '3h 34m 45s' to 12885 (value in seconds)
|
example: convert '3h 34m 45s' to 12885 (value in seconds)
|
||||||
"""
|
"""
|
||||||
validate_duration_format(duration)
|
validate_duration_format(duration)
|
||||||
value = 0
|
value = 0
|
||||||
|
|
@ -876,15 +879,15 @@ def validate_duration_format(duration):
|
||||||
|
|
||||||
|
|
||||||
def get_weekdays() -> list[str]:
|
def get_weekdays() -> list[str]:
|
||||||
"""Returns a list of weekday names.
|
"""Return a list of weekday names.
|
||||||
|
|
||||||
Return value: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
|
Return value: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
|
||||||
"""
|
"""
|
||||||
return ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
|
return ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
|
||||||
|
|
||||||
|
|
||||||
def get_weekday(datetime: DateTimeLikeObject | None = None) -> str:
|
def get_weekday(datetime: DateTimeLikeObject | None = None) -> str:
|
||||||
"""Returns the weekday name (e.g. 'Sunday') for the given datetime like object (datetime.date, datetime.datetime, string).
|
"""Return the weekday name (e.g. 'Sunday') for the given datetime like object (datetime.date, datetime.datetime, string).
|
||||||
|
|
||||||
If `datetime` argument is not provided, the current weekday name is returned.
|
If `datetime` argument is not provided, the current weekday name is returned.
|
||||||
"""
|
"""
|
||||||
|
|
@ -901,7 +904,7 @@ def get_weekday(datetime: DateTimeLikeObject | None = None) -> str:
|
||||||
def get_timespan_date_range(
|
def get_timespan_date_range(
|
||||||
timespan: TimespanOptions,
|
timespan: TimespanOptions,
|
||||||
) -> tuple[datetime.datetime, datetime.datetime] | None:
|
) -> tuple[datetime.datetime, datetime.datetime] | None:
|
||||||
"""Returns the date range (start_date, end_date) tuple for the given timespan."""
|
"""Return the date range (start_date, end_date) tuple for the given timespan."""
|
||||||
today = getdate()
|
today = getdate()
|
||||||
|
|
||||||
match timespan:
|
match timespan:
|
||||||
|
|
@ -974,8 +977,8 @@ def get_timespan_date_range(
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
def global_date_format(date, format="long"):
|
def global_date_format(date: DateTimeLikeObject, format="long") -> str:
|
||||||
"""returns localized date in the form of January 1, 2012"""
|
"""Return localized date in the form of 'January 1, 2012'."""
|
||||||
import babel.dates
|
import babel.dates
|
||||||
|
|
||||||
date = getdate(date)
|
date = getdate(date)
|
||||||
|
|
@ -985,7 +988,7 @@ def global_date_format(date, format="long"):
|
||||||
|
|
||||||
|
|
||||||
def has_common(l1: typing.Hashable, l2: typing.Hashable) -> bool:
|
def has_common(l1: typing.Hashable, l2: typing.Hashable) -> bool:
|
||||||
"""Returns truthy value if there are common elements in lists l1 and l2"""
|
"""Return truthy value if there are common elements in lists l1 and l2."""
|
||||||
return set(l1) & set(l2)
|
return set(l1) & set(l2)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1089,13 +1092,13 @@ def flt(s: NumericType | str, precision: int | None = None) -> float:
|
||||||
def flt(
|
def flt(
|
||||||
s: NumericType | str, precision: int | None = None, rounding_method: str | None = None
|
s: NumericType | str, precision: int | None = None, rounding_method: str | None = None
|
||||||
) -> float:
|
) -> float:
|
||||||
"""Convert to float (ignoring commas in string)
|
"""Convert to float (ignoring commas in string).
|
||||||
|
|
||||||
:param s: Number in string or other numeric format.
|
:param s: Number in string or other numeric format.
|
||||||
:param precision: optional argument to specify precision for rounding.
|
:param precision: optional argument to specify precision for rounding.
|
||||||
:returns: Converted number in python float type.
|
:returns: Converted number in python float type.
|
||||||
|
|
||||||
Returns 0 if input can not be converted to float.
|
Return 0 if input can not be converted to float.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
|
|
@ -1124,12 +1127,12 @@ def flt(
|
||||||
|
|
||||||
|
|
||||||
def cint(s: NumericType | str, default: int = 0) -> int:
|
def cint(s: NumericType | str, default: int = 0) -> int:
|
||||||
"""Convert to integer
|
"""Convert to integer.
|
||||||
|
|
||||||
:param s: Number in string or other numeric format.
|
:param s: Number in string or other numeric format.
|
||||||
:returns: Converted number in python integer type.
|
:returns: Converted number in python integer type.
|
||||||
|
|
||||||
Returns default if input can not be converted to integer.
|
Return default if input cannot be converted to integer.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
>>> cint("100")
|
>>> cint("100")
|
||||||
|
|
@ -1144,21 +1147,8 @@ def cint(s: NumericType | str, default: int = 0) -> int:
|
||||||
return default
|
return default
|
||||||
|
|
||||||
|
|
||||||
def floor(s):
|
def floor(s: NumericType | str) -> int:
|
||||||
"""
|
"""Return a number representing the largest integer less than or equal to the specified number."""
|
||||||
A number representing the largest integer less than or equal to the specified number
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
s : int or str or Decimal object
|
|
||||||
The mathematical value to be floored
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
int
|
|
||||||
number representing the largest integer less than or equal to the specified number
|
|
||||||
|
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
num = cint(math.floor(flt(s)))
|
num = cint(math.floor(flt(s)))
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|
@ -1166,21 +1156,8 @@ def floor(s):
|
||||||
return num
|
return num
|
||||||
|
|
||||||
|
|
||||||
def ceil(s):
|
def ceil(s: NumericType | str) -> int:
|
||||||
"""
|
"""Return the smallest integer greater than or equal to the given number."""
|
||||||
The smallest integer greater than or equal to the given number
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
s : int or str or Decimal object
|
|
||||||
The mathematical value to be ceiled
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
int
|
|
||||||
smallest integer greater than or equal to the given number
|
|
||||||
|
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
num = cint(math.ceil(flt(s)))
|
num = cint(math.ceil(flt(s)))
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|
@ -1189,12 +1166,13 @@ def ceil(s):
|
||||||
|
|
||||||
|
|
||||||
def cstr(s, encoding="utf-8") -> str:
|
def cstr(s, encoding="utf-8") -> str:
|
||||||
"""Converts the given argument to string."""
|
"""Convert the given argument to string."""
|
||||||
return frappe.as_unicode(s, encoding)
|
return frappe.as_unicode(s, encoding)
|
||||||
|
|
||||||
|
|
||||||
def sbool(x: str) -> bool | Any:
|
def sbool(x: str) -> bool | Any:
|
||||||
"""Converts str object to Boolean if possible.
|
"""Convert str object to Boolean if possible.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
"true" becomes True
|
"true" becomes True
|
||||||
"1" becomes True
|
"1" becomes True
|
||||||
|
|
@ -1203,8 +1181,7 @@ def sbool(x: str) -> bool | Any:
|
||||||
Args:
|
Args:
|
||||||
x (str): String to be converted to Bool
|
x (str): String to be converted to Bool
|
||||||
|
|
||||||
Returns:
|
Return Boolean or x.
|
||||||
object: Returns Boolean or x
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
val = x.lower()
|
val = x.lower()
|
||||||
|
|
@ -1361,7 +1338,7 @@ def encode(obj, encoding="utf-8"):
|
||||||
|
|
||||||
|
|
||||||
def parse_val(v):
|
def parse_val(v):
|
||||||
"""Converts to simple datatypes from SQL query results"""
|
"""Convert to simple datatypes from SQL query results."""
|
||||||
if isinstance(v, (datetime.date, datetime.datetime)):
|
if isinstance(v, (datetime.date, datetime.datetime)):
|
||||||
v = str(v)
|
v = str(v)
|
||||||
elif isinstance(v, datetime.timedelta):
|
elif isinstance(v, datetime.timedelta):
|
||||||
|
|
@ -1377,9 +1354,7 @@ def fmt_money(
|
||||||
currency: str | None = None,
|
currency: str | None = None,
|
||||||
format: str | None = None,
|
format: str | None = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""Convert to string with commas for thousands, millions etc."""
|
||||||
Convert to string with commas for thousands, millions etc
|
|
||||||
"""
|
|
||||||
number_format = format or frappe.db.get_default("number_format") or "#,###.##"
|
number_format = format or frappe.db.get_default("number_format") or "#,###.##"
|
||||||
if precision is None:
|
if precision is None:
|
||||||
precision = cint(frappe.db.get_default("currency_precision")) or None
|
precision = cint(frappe.db.get_default("currency_precision")) or None
|
||||||
|
|
@ -1485,9 +1460,7 @@ def money_in_words(
|
||||||
main_currency: str | None = None,
|
main_currency: str | None = None,
|
||||||
fraction_currency: str | None = None,
|
fraction_currency: str | None = None,
|
||||||
):
|
):
|
||||||
"""
|
"""Return string in words with currency and fraction currency."""
|
||||||
Returns string in words with currency and fraction currency.
|
|
||||||
"""
|
|
||||||
from frappe.utils import get_defaults
|
from frappe.utils import get_defaults
|
||||||
|
|
||||||
_ = frappe._
|
_ = frappe._
|
||||||
|
|
@ -1557,9 +1530,7 @@ def money_in_words(
|
||||||
# convert number to words
|
# convert number to words
|
||||||
#
|
#
|
||||||
def in_words(integer: int, in_million=True) -> str:
|
def in_words(integer: int, in_million=True) -> str:
|
||||||
"""
|
"""Return string in words for the given integer."""
|
||||||
Returns string in words for the given integer.
|
|
||||||
"""
|
|
||||||
from num2words import num2words
|
from num2words import num2words
|
||||||
|
|
||||||
locale = "en_IN" if not in_million else frappe.local.lang
|
locale = "en_IN" if not in_million else frappe.local.lang
|
||||||
|
|
@ -1574,14 +1545,14 @@ def in_words(integer: int, in_million=True) -> str:
|
||||||
|
|
||||||
|
|
||||||
def is_html(text: str) -> bool:
|
def is_html(text: str) -> bool:
|
||||||
"""Returns True if the given `text` contains any HTML tags."""
|
"""Return True if the given `text` contains any HTML tags."""
|
||||||
if not isinstance(text, str):
|
if not isinstance(text, str):
|
||||||
return False
|
return False
|
||||||
return HTML_TAG_PATTERN.search(text)
|
return HTML_TAG_PATTERN.search(text)
|
||||||
|
|
||||||
|
|
||||||
def is_image(filepath: str) -> bool:
|
def is_image(filepath: str) -> bool:
|
||||||
"""Returns True if the given `filepath` points to an image file."""
|
"""Return True if the given `filepath` points to an image file."""
|
||||||
from mimetypes import guess_type
|
from mimetypes import guess_type
|
||||||
|
|
||||||
# filepath can be https://example.com/bed.jpg?v=129
|
# filepath can be https://example.com/bed.jpg?v=129
|
||||||
|
|
@ -1699,7 +1670,7 @@ def pretty_date(iso_datetime: datetime.datetime | str) -> str:
|
||||||
|
|
||||||
|
|
||||||
def comma_or(some_list: list | tuple, add_quotes=True) -> str:
|
def comma_or(some_list: list | tuple, add_quotes=True) -> str:
|
||||||
"""Returns the given list or tuple as a comma separated string with the last item joined by 'or'.
|
"""Return the given list or tuple as a comma separated string with the last item joined by 'or'.
|
||||||
e.g. ['a', 'b', 'c'] -> 'a, b or c'
|
e.g. ['a', 'b', 'c'] -> 'a, b or c'
|
||||||
|
|
||||||
If `add_quotes` is True, each item in the list will be wrapped in single quotes.
|
If `add_quotes` is True, each item in the list will be wrapped in single quotes.
|
||||||
|
|
@ -1709,7 +1680,7 @@ def comma_or(some_list: list | tuple, add_quotes=True) -> str:
|
||||||
|
|
||||||
|
|
||||||
def comma_and(some_list: list | tuple, add_quotes=True) -> str:
|
def comma_and(some_list: list | tuple, add_quotes=True) -> str:
|
||||||
"""Returns the given list or tuple as a comma separated string with the last item joined by 'and'.
|
"""Return the given list or tuple as a comma separated string with the last item joined by 'and'.
|
||||||
e.g. ['a', 'b', 'c'] -> 'a, b and c'
|
e.g. ['a', 'b', 'c'] -> 'a, b and c'
|
||||||
|
|
||||||
If `add_quotes` is True, each item in the list will be wrapped in single quotes.
|
If `add_quotes` is True, each item in the list will be wrapped in single quotes.
|
||||||
|
|
@ -1719,7 +1690,7 @@ def comma_and(some_list: list | tuple, add_quotes=True) -> str:
|
||||||
|
|
||||||
|
|
||||||
def comma_sep(some_list: list | tuple, pattern: str, add_quotes=True) -> str:
|
def comma_sep(some_list: list | tuple, pattern: str, add_quotes=True) -> str:
|
||||||
"""Returns the given list or tuple as a comma separated string, with the last item joined by the given string format pattern.
|
"""Return the given list or tuple as a comma separated string, with the last item joined by the given string format pattern.
|
||||||
|
|
||||||
If `add_quotes` is True, each item in the list will be wrapped in single quotes.
|
If `add_quotes` is True, each item in the list will be wrapped in single quotes.
|
||||||
|
|
||||||
|
|
@ -1740,7 +1711,7 @@ def comma_sep(some_list: list | tuple, pattern: str, add_quotes=True) -> str:
|
||||||
|
|
||||||
|
|
||||||
def new_line_sep(some_list: list | tuple) -> str:
|
def new_line_sep(some_list: list | tuple) -> str:
|
||||||
"""Returns the given list or tuple as a new line separated string.
|
"""Return the given list or tuple as a new line separated string.
|
||||||
|
|
||||||
e.g. ['', 'Paid', 'Unpaid'] -> '\n Paid\n Unpaid'
|
e.g. ['', 'Paid', 'Unpaid'] -> '\n Paid\n Unpaid'
|
||||||
"""
|
"""
|
||||||
|
|
@ -1828,7 +1799,7 @@ def get_host_name_from_request() -> str:
|
||||||
|
|
||||||
|
|
||||||
def url_contains_port(url: str) -> bool:
|
def url_contains_port(url: str) -> bool:
|
||||||
"""Returns True if the given url contains a port number.
|
"""Return True if the given url contains a port number.
|
||||||
|
|
||||||
e.g. 'http://localhost:8000' -> True, 'http://localhost' -> False
|
e.g. 'http://localhost:8000' -> True, 'http://localhost' -> False
|
||||||
"""
|
"""
|
||||||
|
|
@ -1877,7 +1848,7 @@ def get_link_to_report(
|
||||||
|
|
||||||
|
|
||||||
def get_absolute_url(doctype: str, name: str) -> str:
|
def get_absolute_url(doctype: str, name: str) -> str:
|
||||||
"""Returns the absolute route for the form view of the given document in the desk.
|
"""Return the absolute route for the form view of the given document in the desk.
|
||||||
|
|
||||||
e.g. when doctype="Sales Invoice" and name="INV-00001", returns '/app/sales-invoice/INV-00001'
|
e.g. when doctype="Sales Invoice" and name="INV-00001", returns '/app/sales-invoice/INV-00001'
|
||||||
"""
|
"""
|
||||||
|
|
@ -1889,7 +1860,7 @@ def get_url_to_form(doctype: str, name: str) -> str:
|
||||||
|
|
||||||
|
|
||||||
def get_url_to_list(doctype: str) -> str:
|
def get_url_to_list(doctype: str) -> str:
|
||||||
"""Returns the absolute URL for the list view of the given document in the desk.
|
"""Return the absolute URL for the list view of the given document in the desk.
|
||||||
|
|
||||||
e.g. when doctype="Sales Invoice" and your site URL is "https://frappe.io",
|
e.g. when doctype="Sales Invoice" and your site URL is "https://frappe.io",
|
||||||
returns 'https://frappe.io/app/sales-invoice'
|
returns 'https://frappe.io/app/sales-invoice'
|
||||||
|
|
@ -1946,7 +1917,7 @@ operator_map = {
|
||||||
|
|
||||||
|
|
||||||
def evaluate_filters(doc, filters: dict | list | tuple):
|
def evaluate_filters(doc, filters: dict | list | tuple):
|
||||||
"""Returns true if doc matches filters"""
|
"""Return True if doc matches filters."""
|
||||||
if isinstance(filters, dict):
|
if isinstance(filters, dict):
|
||||||
for key, value in filters.items():
|
for key, value in filters.items():
|
||||||
f = get_filter(None, {key: value})
|
f = get_filter(None, {key: value})
|
||||||
|
|
@ -1973,14 +1944,14 @@ def compare(val1: Any, condition: str, val2: Any, fieldtype: str | None = None):
|
||||||
|
|
||||||
|
|
||||||
def get_filter(doctype: str, f: dict | list | tuple, filters_config=None) -> "frappe._dict":
|
def get_filter(doctype: str, f: dict | list | tuple, filters_config=None) -> "frappe._dict":
|
||||||
"""Returns a _dict like
|
"""Return a `_dict` like:
|
||||||
|
|
||||||
{
|
{
|
||||||
"doctype":
|
"doctype": ...
|
||||||
"fieldname":
|
"fieldname": ...
|
||||||
"operator":
|
"operator": ...
|
||||||
"value":
|
"value": ...
|
||||||
"fieldtype":
|
"fieldtype": ...
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
from frappe.database.utils import NestedSetHierarchy
|
from frappe.database.utils import NestedSetHierarchy
|
||||||
|
|
@ -2181,7 +2152,7 @@ def get_string_between(start: str, string: str, end: str) -> str:
|
||||||
|
|
||||||
|
|
||||||
def to_markdown(html: str) -> str:
|
def to_markdown(html: str) -> str:
|
||||||
"""Converts the given HTML to markdown and returns it."""
|
"""Convert the given HTML to markdown and returns it."""
|
||||||
from html.parser import HTMLParser
|
from html.parser import HTMLParser
|
||||||
|
|
||||||
from frappe.core.utils import html2text
|
from frappe.core.utils import html2text
|
||||||
|
|
@ -2193,7 +2164,7 @@ def to_markdown(html: str) -> str:
|
||||||
|
|
||||||
|
|
||||||
def md_to_html(markdown_text: str) -> Optional["UnicodeWithAttrs"]:
|
def md_to_html(markdown_text: str) -> Optional["UnicodeWithAttrs"]:
|
||||||
"""Converts the given markdown text to HTML and returns it."""
|
"""Convert the given markdown text to HTML and returns it."""
|
||||||
from markdown2 import MarkdownError
|
from markdown2 import MarkdownError
|
||||||
from markdown2 import markdown as _markdown
|
from markdown2 import markdown as _markdown
|
||||||
|
|
||||||
|
|
@ -2213,12 +2184,12 @@ def md_to_html(markdown_text: str) -> Optional["UnicodeWithAttrs"]:
|
||||||
|
|
||||||
|
|
||||||
def markdown(markdown_text: str) -> Optional["UnicodeWithAttrs"]:
|
def markdown(markdown_text: str) -> Optional["UnicodeWithAttrs"]:
|
||||||
"""Converts the given markdown text to HTML and returns it."""
|
"""Convert the given markdown text to HTML and returns it."""
|
||||||
return md_to_html(markdown_text)
|
return md_to_html(markdown_text)
|
||||||
|
|
||||||
|
|
||||||
def is_subset(list_a: list, list_b: list) -> bool:
|
def is_subset(list_a: list, list_b: list) -> bool:
|
||||||
"""Returns whether list_a is a subset of list_b"""
|
"""Return whether list_a is a subset of list_b."""
|
||||||
return len(list(set(list_a) & set(list_b))) == len(list_a)
|
return len(list(set(list_a) & set(list_b))) == len(list_a)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2231,7 +2202,7 @@ def generate_hash(*args, **kwargs) -> str:
|
||||||
|
|
||||||
|
|
||||||
def dict_with_keys(dict, keys):
|
def dict_with_keys(dict, keys):
|
||||||
"""Returns a new dict with a subset of keys"""
|
"""Return a new dict with a subset of keys."""
|
||||||
out = {}
|
out = {}
|
||||||
for key in dict:
|
for key in dict:
|
||||||
if key in keys:
|
if key in keys:
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ def create_lock(name):
|
||||||
|
|
||||||
|
|
||||||
def lock_exists(name):
|
def lock_exists(name):
|
||||||
"""Returns True if lock of the given name exists"""
|
"""Return True if lock of the given name exists."""
|
||||||
return os.path.exists(get_lock_path(name))
|
return os.path.exists(get_lock_path(name))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ def upload():
|
||||||
|
|
||||||
|
|
||||||
def get_file_doc(dt=None, dn=None, folder=None, is_private=None, df=None):
|
def get_file_doc(dt=None, dn=None, folder=None, is_private=None, df=None):
|
||||||
"""returns File object (Document) from given parameters or form_dict"""
|
"""Return File object (Document) from given parameters or `form_dict`."""
|
||||||
r = frappe.form_dict
|
r = frappe.form_dict
|
||||||
|
|
||||||
if dt is None:
|
if dt is None:
|
||||||
|
|
@ -328,7 +328,7 @@ def delete_file(path):
|
||||||
|
|
||||||
|
|
||||||
def get_file(fname):
|
def get_file(fname):
|
||||||
"""Returns [`file_name`, `content`] for given file name `fname`"""
|
"""Return [`file_name`, `content`] for given file name `fname`."""
|
||||||
file_path = get_file_path(fname)
|
file_path = get_file_path(fname)
|
||||||
|
|
||||||
# read the file
|
# read the file
|
||||||
|
|
@ -345,7 +345,7 @@ def get_file(fname):
|
||||||
|
|
||||||
|
|
||||||
def get_file_path(file_name):
|
def get_file_path(file_name):
|
||||||
"""Returns file path from given file name"""
|
"""Return file path from given file name."""
|
||||||
if "../" in file_name:
|
if "../" in file_name:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,7 @@ class Identicon:
|
||||||
self.hash = self.digest(str_)
|
self.hash = self.digest(str_)
|
||||||
|
|
||||||
def digest(self, str_):
|
def digest(self, str_):
|
||||||
"""
|
"""Return a md5 numeric hash."""
|
||||||
Returns a md5 numeric hash
|
|
||||||
"""
|
|
||||||
return int(md5(str_.encode("utf-8"), usedforsecurity=False).hexdigest(), 16)
|
return int(md5(str_.encode("utf-8"), usedforsecurity=False).hexdigest(), 16)
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
|
|
|
||||||
|
|
@ -20,14 +20,13 @@ def resize_images(path, maxdim=700):
|
||||||
print(f"resized {os.path.join(basepath, fname)}")
|
print(f"resized {os.path.join(basepath, fname)}")
|
||||||
|
|
||||||
|
|
||||||
def strip_exif_data(content, content_type):
|
def strip_exif_data(content, content_type) -> bytes:
|
||||||
"""Strips EXIF from image files which support it.
|
"""Strip EXIF from image files which support it.
|
||||||
|
|
||||||
Works by creating a new Image object which ignores exif by
|
Works by creating a new Image object which ignores exif by
|
||||||
default and then extracts the binary data back into content.
|
default and then extracts the binary data back into content.
|
||||||
|
|
||||||
Returns:
|
Return Stripped image content.
|
||||||
Bytes: Stripped image content
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
original_image = Image.open(io.BytesIO(content))
|
original_image = Image.open(io.BytesIO(content))
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ def set_filters(jenv):
|
||||||
|
|
||||||
|
|
||||||
def get_jinja_hooks():
|
def get_jinja_hooks():
|
||||||
"""Returns a tuple of (methods, filters) each containing a dict of method name and method definition pair."""
|
"""Return a tuple of (methods, filters) each containing a dict of method name and method definition pair."""
|
||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
if not getattr(frappe.local, "site", None):
|
if not getattr(frappe.local, "site", None):
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ def get_logger(
|
||||||
file_count=20,
|
file_count=20,
|
||||||
stream_only=stream_logging,
|
stream_only=stream_logging,
|
||||||
) -> "logging.Logger":
|
) -> "logging.Logger":
|
||||||
"""Application Logger for your given module
|
"""Return Application Logger for your given module.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
module (str, optional): Name of your logger and consequently your log file. Defaults to None.
|
module (str, optional): Name of your logger and consequently your log file. Defaults to None.
|
||||||
|
|
@ -33,8 +33,7 @@ def get_logger(
|
||||||
file_count (int, optional): Max count of log files to be retained via Log Rotation. Defaults to 20.
|
file_count (int, optional): Max count of log files to be retained via Log Rotation. Defaults to 20.
|
||||||
stream_only (bool, optional): Whether to stream logs only to stderr (True) or use log files (False). Defaults to False.
|
stream_only (bool, optional): Whether to stream logs only to stderr (True) or use log files (False). Defaults to False.
|
||||||
|
|
||||||
Returns:
|
Return a Python logger object with Site and Bench level logging capabilities.
|
||||||
<class 'logging.Logger'>: Returns a Python logger object with Site and Bench level logging capabilities.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if allow_site is True:
|
if allow_site is True:
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,9 @@ from frappe.www.printview import validate_print_permission
|
||||||
def download_multi_pdf(
|
def download_multi_pdf(
|
||||||
doctype, name, format=None, no_letterhead=False, letterhead=None, options=None
|
doctype, name, format=None, no_letterhead=False, letterhead=None, options=None
|
||||||
):
|
):
|
||||||
"""
|
"""Return a PDF compiled by concatenating multiple documents.
|
||||||
Concatenate multiple docs as PDF .
|
|
||||||
|
|
||||||
Returns a PDF compiled by concatenating multiple documents. The documents
|
The documents can be from a single DocType or multiple DocTypes.
|
||||||
can be from a single DocType or multiple DocTypes
|
|
||||||
|
|
||||||
Note: The design may seem a little weird, but it exists exists to
|
Note: The design may seem a little weird, but it exists exists to
|
||||||
ensure backward compatibility. The correct way to use this function is to
|
ensure backward compatibility. The correct way to use this function is to
|
||||||
|
|
@ -43,9 +41,6 @@ def download_multi_pdf(
|
||||||
format:
|
format:
|
||||||
Print Format to be used
|
Print Format to be used
|
||||||
|
|
||||||
Returns:
|
|
||||||
PDF: A PDF generated by the concatenation of the mentioned input docs
|
|
||||||
|
|
||||||
OLD FUNCTIONALITY - soon to be deprecated
|
OLD FUNCTIONALITY - soon to be deprecated
|
||||||
=========================================
|
=========================================
|
||||||
Parameters:
|
Parameters:
|
||||||
|
|
|
||||||
|
|
@ -72,8 +72,8 @@ class RedisWrapper(redis.Redis):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_value(self, key, generator=None, user=None, expires=False, shared=False):
|
def get_value(self, key, generator=None, user=None, expires=False, shared=False):
|
||||||
"""Returns cache value. If not found and generator function is
|
"""Return cache value. If not found and generator function is
|
||||||
given, it will call the generator.
|
given, call the generator.
|
||||||
|
|
||||||
:param key: Cache key.
|
:param key: Cache key.
|
||||||
:param generator: Function to be called to generate a value if `None` is returned.
|
:param generator: Function to be called to generate a value if `None` is returned.
|
||||||
|
|
@ -266,23 +266,23 @@ class RedisWrapper(redis.Redis):
|
||||||
super().sadd(self.make_key(name), *values)
|
super().sadd(self.make_key(name), *values)
|
||||||
|
|
||||||
def srem(self, name, *values):
|
def srem(self, name, *values):
|
||||||
"""Remove a specific member/list of members from the set"""
|
"""Remove a specific member/list of members from the set."""
|
||||||
super().srem(self.make_key(name), *values)
|
super().srem(self.make_key(name), *values)
|
||||||
|
|
||||||
def sismember(self, name, value):
|
def sismember(self, name, value):
|
||||||
"""Returns True or False based on if a given value is present in the set"""
|
"""Return True or False based on if a given value is present in the set."""
|
||||||
return super().sismember(self.make_key(name), value)
|
return super().sismember(self.make_key(name), value)
|
||||||
|
|
||||||
def spop(self, name):
|
def spop(self, name):
|
||||||
"""Removes and returns a random member from the set"""
|
"""Remove and returns a random member from the set."""
|
||||||
return super().spop(self.make_key(name))
|
return super().spop(self.make_key(name))
|
||||||
|
|
||||||
def srandmember(self, name, count=None):
|
def srandmember(self, name, count=None):
|
||||||
"""Returns a random member from the set"""
|
"""Return a random member from the set."""
|
||||||
return super().srandmember(self.make_key(name))
|
return super().srandmember(self.make_key(name))
|
||||||
|
|
||||||
def smembers(self, name):
|
def smembers(self, name):
|
||||||
"""Return all members of the set"""
|
"""Return all members of the set."""
|
||||||
return super().smembers(self.make_key(name))
|
return super().smembers(self.make_key(name))
|
||||||
|
|
||||||
def ft(self, index_name="idx"):
|
def ft(self, index_name="idx"):
|
||||||
|
|
|
||||||
|
|
@ -141,8 +141,8 @@ def disable_scheduler():
|
||||||
|
|
||||||
|
|
||||||
def schedule_jobs_based_on_activity(check_time=None):
|
def schedule_jobs_based_on_activity(check_time=None):
|
||||||
"""Returns True for active sites defined by Activity Log
|
"""Return True for active sites defined by Activity Log.
|
||||||
Returns True for inactive sites once in 24 hours"""
|
Also return True for inactive sites once in 24 hours."""
|
||||||
if is_dormant(check_time=check_time):
|
if is_dormant(check_time=check_time):
|
||||||
# ensure last job is one day old
|
# ensure last job is one day old
|
||||||
last_job_timestamp = _get_last_modified_timestamp("Scheduled Job Log")
|
last_job_timestamp = _get_last_modified_timestamp("Scheduled Job Log")
|
||||||
|
|
|
||||||
|
|
@ -285,7 +285,7 @@ def get_fullname_and_avatar(user: str) -> _dict:
|
||||||
|
|
||||||
|
|
||||||
def get_system_managers(only_name: bool = False) -> list[str]:
|
def get_system_managers(only_name: bool = False) -> list[str]:
|
||||||
"""returns all system manager's user details"""
|
"""Return all system manager's user details."""
|
||||||
HasRole = DocType("Has Role")
|
HasRole = DocType("Has Role")
|
||||||
User = DocType("User")
|
User = DocType("User")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -103,12 +103,7 @@ class PrintFormatGenerator:
|
||||||
return header_html, footer_html
|
return header_html, footer_html
|
||||||
|
|
||||||
def render_pdf(self):
|
def render_pdf(self):
|
||||||
"""
|
"""Return a bytes sequence of the rendered PDF."""
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
pdf: a bytes sequence
|
|
||||||
The rendered PDF.
|
|
||||||
"""
|
|
||||||
HTML, CSS = import_weasyprint()
|
HTML, CSS = import_weasyprint()
|
||||||
|
|
||||||
self._make_header_footer()
|
self._make_header_footer()
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ class PersonalDataDownloadRequest(Document):
|
||||||
|
|
||||||
|
|
||||||
def get_user_data(user):
|
def get_user_data(user):
|
||||||
"""returns user data not linked to User doctype"""
|
"""Return user data not linked to `User` doctype."""
|
||||||
hooks = frappe.get_hooks("user_data_fields")
|
hooks = frappe.get_hooks("user_data_fields")
|
||||||
data = {}
|
data = {}
|
||||||
for hook in hooks:
|
for hook in hooks:
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ class WebForm(WebsiteGenerator):
|
||||||
frappe.throw(_("Following fields are missing:") + "<br>" + "<br>".join(missing))
|
frappe.throw(_("Following fields are missing:") + "<br>" + "<br>".join(missing))
|
||||||
|
|
||||||
def reset_field_parent(self):
|
def reset_field_parent(self):
|
||||||
"""Convert link fields to select with names as options"""
|
"""Convert link fields to select with names as options."""
|
||||||
for df in self.web_form_fields:
|
for df in self.web_form_fields:
|
||||||
df.parent = self.doc_type
|
df.parent = self.doc_type
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -235,7 +235,7 @@ def check_publish_status():
|
||||||
|
|
||||||
|
|
||||||
def get_web_blocks_html(blocks):
|
def get_web_blocks_html(blocks):
|
||||||
"""Converts a list of blocks into Raw HTML and extracts out their scripts for deduplication"""
|
"""Convert a list of blocks into Raw HTML and extract out their scripts for deduplication."""
|
||||||
|
|
||||||
out = frappe._dict(html="", scripts={}, styles={})
|
out = frappe._dict(html="", scripts={}, styles={})
|
||||||
extracted_scripts = {}
|
extracted_scripts = {}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ def authorize_access(reauthorize=False, code=None):
|
||||||
|
|
||||||
|
|
||||||
def get_google_indexing_object():
|
def get_google_indexing_object():
|
||||||
"""Returns an object of Google Indexing object."""
|
"""Return an object of Google Indexing object."""
|
||||||
account = frappe.get_doc("Website Settings")
|
account = frappe.get_doc("Website Settings")
|
||||||
oauth_obj = GoogleOAuth("indexing")
|
oauth_obj = GoogleOAuth("indexing")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ class PathResolver:
|
||||||
self.http_status_code = http_status_code
|
self.http_status_code = http_status_code
|
||||||
|
|
||||||
def resolve(self):
|
def resolve(self):
|
||||||
"""Returns endpoint and a renderer instance that can render the endpoint"""
|
"""Return endpoint and a renderer instance that can render the endpoint."""
|
||||||
request = frappe._dict()
|
request = frappe._dict()
|
||||||
if hasattr(frappe.local, "request"):
|
if hasattr(frappe.local, "request"):
|
||||||
request = frappe.local.request or request
|
request = frappe.local.request or request
|
||||||
|
|
|
||||||
|
|
@ -254,8 +254,8 @@ def setup_source(page_info):
|
||||||
|
|
||||||
|
|
||||||
def get_base_template(path=None):
|
def get_base_template(path=None):
|
||||||
"""
|
"""Return the `base_template` for given `path`.
|
||||||
Returns the `base_template` for given `path`.
|
|
||||||
The default `base_template` for any web route is `templates/web.html` defined in `hooks.py`.
|
The default `base_template` for any web route is `templates/web.html` defined in `hooks.py`.
|
||||||
This can be overridden for certain routes in `custom_app/hooks.py` based on regex pattern.
|
This can be overridden for certain routes in `custom_app/hooks.py` based on regex pattern.
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -251,7 +251,7 @@ def get_next_link(route, url_prefix=None, app=None):
|
||||||
|
|
||||||
|
|
||||||
def get_full_index(route=None, app=None):
|
def get_full_index(route=None, app=None):
|
||||||
"""Returns full index of the website for www upto the n-th level"""
|
"""Return full index of the website for www upto the n-th level."""
|
||||||
from frappe.website.router import get_pages
|
from frappe.website.router import get_pages
|
||||||
|
|
||||||
if not frappe.local.flags.children_map:
|
if not frappe.local.flags.children_map:
|
||||||
|
|
@ -305,7 +305,7 @@ def get_full_index(route=None, app=None):
|
||||||
|
|
||||||
|
|
||||||
def extract_title(source, path):
|
def extract_title(source, path):
|
||||||
"""Returns title from `<!-- title -->` or <h1> or path"""
|
"""Return title from `<!-- title -->` or <h1> or path."""
|
||||||
title = extract_comment_tag(source, "title")
|
title = extract_comment_tag(source, "title")
|
||||||
|
|
||||||
if not title and "<h1>" in source:
|
if not title and "<h1>" in source:
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,7 @@ class WebsiteGenerator(Document):
|
||||||
self.route = self.route.strip("/.")[:139]
|
self.route = self.route.strip("/.")[:139]
|
||||||
|
|
||||||
def make_route(self):
|
def make_route(self):
|
||||||
"""Returns the default route. If `route` is specified in DocType it will be
|
"""Return the default route. If `route` is specified in DocType it will be route/title."""
|
||||||
route/title"""
|
|
||||||
from_title = self.scrubbed_title()
|
from_title = self.scrubbed_title()
|
||||||
if self.meta.route:
|
if self.meta.route:
|
||||||
return self.meta.route + "/" + from_title
|
return self.meta.route + "/" + from_title
|
||||||
|
|
|
||||||
|
|
@ -496,9 +496,7 @@ def get_common_email_args(doc):
|
||||||
|
|
||||||
|
|
||||||
def get_email_template(doc):
|
def get_email_template(doc):
|
||||||
"""Returns next_action_email_template
|
"""Return next_action_email_template for workflow state (if available) based on doc current workflow state."""
|
||||||
for workflow state (if available) based on doc current workflow state
|
|
||||||
"""
|
|
||||||
workflow_name = get_workflow_name(doc.get("doctype"))
|
workflow_name = get_workflow_name(doc.get("doctype"))
|
||||||
doc_state = get_doc_workflow_state(doc)
|
doc_state = get_doc_workflow_state(doc)
|
||||||
template_name = frappe.db.get_value(
|
template_name = frappe.db.get_value(
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,9 @@ no_cache = 1
|
||||||
|
|
||||||
|
|
||||||
def get_context(context, **dict_params):
|
def get_context(context, **dict_params):
|
||||||
"""Returns context for a list standard list page.
|
"""Return context for a list standard list page.
|
||||||
Will also update `get_list_context` from the doctype module file"""
|
|
||||||
|
Also update `get_list_context` from the doctype module file."""
|
||||||
frappe.local.form_dict.update(dict_params)
|
frappe.local.form_dict.update(dict_params)
|
||||||
doctype = frappe.local.form_dict.doctype
|
doctype = frappe.local.form_dict.doctype
|
||||||
context.parents = [{"route": "me", "title": _("My Account")}]
|
context.parents = [{"route": "me", "title": _("My Account")}]
|
||||||
|
|
@ -27,7 +28,7 @@ def get_context(context, **dict_params):
|
||||||
|
|
||||||
@frappe.whitelist(allow_guest=True)
|
@frappe.whitelist(allow_guest=True)
|
||||||
def get(doctype, txt=None, limit_start=0, limit=20, pathname=None, **kwargs):
|
def get(doctype, txt=None, limit_start=0, limit=20, pathname=None, **kwargs):
|
||||||
"""Returns processed HTML page for a standard listing."""
|
"""Return processed HTML page for a standard listing."""
|
||||||
limit_start = cint(limit_start)
|
limit_start = cint(limit_start)
|
||||||
raw_result = get_list_data(doctype, txt, limit_start, limit=limit + 1, **kwargs)
|
raw_result = get_list_data(doctype, txt, limit_start, limit=limit + 1, **kwargs)
|
||||||
show_more = len(raw_result) > limit
|
show_more = len(raw_result) > limit
|
||||||
|
|
@ -77,7 +78,7 @@ def get(doctype, txt=None, limit_start=0, limit=20, pathname=None, **kwargs):
|
||||||
def get_list_data(
|
def get_list_data(
|
||||||
doctype, txt=None, limit_start=0, fields=None, cmd=None, limit=20, web_form_name=None, **kwargs
|
doctype, txt=None, limit_start=0, fields=None, cmd=None, limit=20, web_form_name=None, **kwargs
|
||||||
):
|
):
|
||||||
"""Returns processed HTML page for a standard listing."""
|
"""Return processed HTML page for a standard listing."""
|
||||||
limit_start = cint(limit_start)
|
limit_start = cint(limit_start)
|
||||||
|
|
||||||
if frappe.is_table(doctype):
|
if frappe.is_table(doctype):
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue