docs: consistent doc strings

This commit is contained in:
Hussain Nagaria 2023-12-18 18:27:39 +05:30
parent aefe634ff7
commit 8d2137c265
102 changed files with 487 additions and 594 deletions

View file

@ -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.

View file

@ -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)

View file

@ -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

View file

@ -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)
) )

View file

@ -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)"""

View file

@ -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:

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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(),

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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):

View file

@ -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 = [

View file

@ -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 = [

View file

@ -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):

View file

@ -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

View file

@ -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'

View file

@ -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

View file

@ -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

View file

@ -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():

View file

@ -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)

View file

@ -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):

View file

@ -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:

View file

@ -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`
""" """

View file

@ -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)

View file

@ -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(",")

View file

@ -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 []

View file

@ -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):

View file

@ -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:

View file

@ -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

View file

@ -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]

View file

@ -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

View file

@ -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,

View file

@ -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):

View file

@ -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 {}

View file

@ -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(
{ {

View file

@ -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)

View file

@ -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)

View file

@ -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"]

View file

@ -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

View file

@ -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):

View file

@ -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

View file

@ -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:

View file

@ -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")

View file

@ -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")

View file

@ -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(

View file

@ -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,

View file

@ -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:

View file

@ -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"])

View file

@ -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)

View file

@ -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

View file

@ -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):

View file

@ -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:

View file

@ -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(

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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.

View file

@ -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:

View file

@ -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"]

View file

@ -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:

View file

@ -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:

View file

@ -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

View file

@ -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}

View file

@ -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):

View file

@ -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()

View file

@ -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

View file

@ -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 (

View file

@ -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

View file

@ -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")

View file

@ -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(

View file

@ -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):

View file

@ -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)

View file

@ -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

View file

@ -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.
""" """

View file

@ -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:

View file

@ -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))

View file

@ -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

View file

@ -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):

View file

@ -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))

View file

@ -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):

View file

@ -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:

View file

@ -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:

View file

@ -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"):

View file

@ -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")

View file

@ -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")

View file

@ -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()

View file

@ -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:

View file

@ -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

View file

@ -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 = {}

View file

@ -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")

View file

@ -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

View file

@ -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.
""" """

View file

@ -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 `&lt;!-- title --&gt;` or &lt;h1&gt; or path""" """Return title from `&lt;!-- title --&gt;` or &lt;h1&gt; 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:

View file

@ -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

View file

@ -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(

View file

@ -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