2
0
mirror of https://github.com/frappe/frappe.git synced 2024-06-13 11:12:24 +00:00

style: re-format with ruff

This commit is contained in:
Ankush Menat 2024-02-05 18:32:56 +05:30
parent b418dba7ae
commit de9ac89748
464 changed files with 1032 additions and 1861 deletions

View File

@ -307,9 +307,7 @@ def init(site: str, sites_path: str = ".", new_site: bool = False, force=False)
local.initialised = True
def connect(
site: str | None = None, db_name: str | None = None, set_admin_as_user: bool = True
) -> None:
def connect(site: str | None = None, db_name: str | None = None, set_admin_as_user: bool = True) -> None:
"""Connect to site database instance.
:param site: (Deprecated) If site is given, calls `frappe.init`.
@ -432,9 +430,7 @@ def get_site_config(sites_path: str | None = None, site_path: str | None = None)
)
# Set the user as database name if not set in config
config["db_user"] = (
os.environ.get("FRAPPE_DB_USER") or config.get("db_user") or config.get("db_name")
)
config["db_user"] = os.environ.get("FRAPPE_DB_USER") or config.get("db_user") or config.get("db_name")
# Allow externally extending the config with hooks
if extra_config := config.get("extra_config"):
@ -920,9 +916,7 @@ def is_whitelisted(method):
is_guest = session["user"] == "Guest"
if method not in whitelisted or is_guest and method not in guest_methods:
summary = _("You are not permitted to access this resource.")
detail = _("Function {0} is not whitelisted.").format(
bold(f"{method.__module__}.{method.__name__}")
)
detail = _("Function {0} is not whitelisted.").format(bold(f"{method.__module__}.{method.__name__}"))
msg = f"<details><summary>{summary}</summary>{detail}</details>"
throw(msg, PermissionError, title="Method Not Allowed")
@ -937,7 +931,6 @@ def is_whitelisted(method):
def read_only():
def innfn(fn):
def wrapper_fn(*args, **kwargs):
# frappe.read_only could be called from nested functions, in such cases don't swap the
# connection again.
switched_connection = False
@ -1109,9 +1102,7 @@ def has_permission(
)
if throw and not out:
document_label = (
f"{_(doctype)} {doc if isinstance(doc, str) else doc.name}" if doc else _(doctype)
)
document_label = f"{_(doctype)} {doc if isinstance(doc, str) else doc.name}" if doc else _(doctype)
frappe.flags.error_message = _("No permission for {0}").format(document_label)
raise frappe.PermissionError
@ -1286,9 +1277,7 @@ def clear_document_cache(doctype: str, name: str | None = None) -> None:
delattr(local, "website_settings")
def get_cached_value(
doctype: str, name: str, fieldname: str = "name", as_dict: bool = False
) -> Any:
def get_cached_value(doctype: str, name: str, fieldname: str = "name", as_dict: bool = False) -> Any:
try:
doc = get_cached_doc(doctype, name)
except DoesNotExistError:
@ -1654,9 +1643,7 @@ def _load_app_hooks(app_name: str | None = None):
return hooks
def get_hooks(
hook: str = None, default: Any | None = "_KEEP_DEFAULT_LIST", app_name: str = None
) -> _dict:
def get_hooks(hook: str = None, default: Any | None = "_KEEP_DEFAULT_LIST", app_name: str = None) -> _dict:
"""Get hooks via `app/hooks.py`
:param hook: Name of the hook. Will gather all hooks for this name and return as a list.
@ -1757,11 +1744,7 @@ def read_file(path, raise_not_found=False):
def get_attr(method_string: str) -> Any:
"""Get python method object from its name."""
app_name = method_string.split(".", 1)[0]
if (
not local.flags.in_uninstall
and not local.flags.in_install
and app_name not in get_installed_apps()
):
if not local.flags.in_uninstall and not local.flags.in_install and app_name not in get_installed_apps():
throw(_("App {0} is not installed").format(app_name), AppNotInstalledError)
modulename = ".".join(method_string.split(".")[:-1])
@ -1783,7 +1766,8 @@ def get_newargs(fn: Callable, kwargs: dict[str, Any]) -> dict[str, Any]:
"""Remove any kwargs that are not supported by the function.
Example:
>>> def fn(a=1, b=2): pass
>>> def fn(a=1, b=2):
... pass
>>> get_newargs(fn, {"a": 2, "c": 1})
{"a": 2}
@ -2346,9 +2330,7 @@ loggers = {}
log_level = None
def logger(
module=None, with_more_info=False, allow_site=True, filter=None, max_size=100_000, file_count=20
):
def logger(module=None, with_more_info=False, allow_site=True, filter=None, max_size=100_000, file_count=20):
"""Return a python logger that uses StreamHandler."""
from frappe.utils.logger import get_logger
@ -2363,9 +2345,7 @@ def logger(
def get_desk_link(doctype, name):
html = (
'<a href="/app/Form/{doctype}/{name}" style="font-weight: bold;">{doctype_local} {name}</a>'
)
html = '<a href="/app/Form/{doctype}/{name}" style="font-weight: bold;">{doctype_local} {name}</a>'
return html.format(doctype=doctype, name=name, doctype_local=_(doctype))
@ -2418,7 +2398,7 @@ def get_version(doctype, name, limit=None, head=False, raise_err=True):
Note: Applicable only if DocType has changes tracked.
Example
>>> frappe.get_version('User', 'foobar@gmail.com')
>>> frappe.get_version("User", "foobar@gmail.com")
>>>
[
{

View File

@ -272,9 +272,7 @@ def set_cors_headers(response):
# only required for preflight requests
if request.method == "OPTIONS":
cors_headers["Access-Control-Allow-Methods"] = request.headers.get(
"Access-Control-Request-Method"
)
cors_headers["Access-Control-Allow-Methods"] = request.headers.get("Access-Control-Request-Method")
if allowed_headers := request.headers.get("Access-Control-Request-Headers"):
cors_headers["Access-Control-Allow-Headers"] = allowed_headers
@ -513,9 +511,7 @@ def serve(
def application_with_statics():
global application, _sites_path
application = SharedDataMiddleware(
application, {"/assets": str(os.path.join(_sites_path, "assets"))}
)
application = SharedDataMiddleware(application, {"/assets": str(os.path.join(_sites_path, "assets"))})
application = StaticDataMiddleware(application, {"/files": str(os.path.abspath(_sites_path))})

View File

@ -61,9 +61,7 @@ class HTTPRequest:
def set_request_ip(self):
if frappe.get_request_header("X-Forwarded-For"):
frappe.local.request_ip = (
frappe.get_request_header("X-Forwarded-For").split(",", 1)[0]
).strip()
frappe.local.request_ip = (frappe.get_request_header("X-Forwarded-For").split(",", 1)[0]).strip()
elif frappe.get_request_header("REMOTE_ADDR"):
frappe.local.request_ip = frappe.get_request_header("REMOTE_ADDR")
@ -107,9 +105,7 @@ class LoginManager:
self.full_name = None
self.user_type = None
if (
frappe.local.form_dict.get("cmd") == "login" or frappe.local.request.path == "/api/method/login"
):
if frappe.local.form_dict.get("cmd") == "login" or frappe.local.request.path == "/api/method/login":
if self.login() is False:
return
self.resume = False
@ -138,9 +134,7 @@ class LoginManager:
self.authenticate(user=user, pwd=pwd)
if self.force_user_to_reset_password():
doc = frappe.get_doc("User", self.user)
frappe.local.response["redirect_to"] = doc.reset_password(
send_email=False, password_expired=True
)
frappe.local.response["redirect_to"] = doc.reset_password(send_email=False, password_expired=True)
frappe.local.response["message"] = "Password Reset"
return False
@ -413,9 +407,7 @@ def get_logged_user():
def clear_cookies():
if hasattr(frappe.local, "session"):
frappe.session.sid = ""
frappe.local.cookie_manager.delete_cookie(
["full_name", "user_id", "sid", "user_image", "system_user"]
)
frappe.local.cookie_manager.delete_cookie(["full_name", "user_id", "sid", "user_image", "system_user"])
def validate_ip_address(user):
@ -613,9 +605,7 @@ def validate_oauth(authorization_header):
req = frappe.request
parsed_url = urlparse(req.url)
access_token = {"access_token": token}
uri = (
parsed_url.scheme + "://" + parsed_url.netloc + parsed_url.path + "?" + urlencode(access_token)
)
uri = parsed_url.scheme + "://" + parsed_url.netloc + parsed_url.path + "?" + urlencode(access_token)
http_method = req.method
headers = req.headers
body = req.get_data()

View File

@ -39,6 +39,7 @@ class AssignmentRule(Document):
unassign_condition: DF.Code | None
users: DF.TableMultiSelect[AssignmentRuleUser]
# end: auto-generated types
def validate(self):
self.validate_document_types()
self.validate_assignment_days()
@ -50,9 +51,7 @@ class AssignmentRule(Document):
def validate_document_types(self):
if self.document_type == "ToDo":
frappe.throw(
_("Assignment Rule is not allowed on {0} document type").format(frappe.bold("ToDo"))
)
frappe.throw(_("Assignment Rule is not allowed on {0} document type").format(frappe.bold("ToDo")))
def validate_assignment_days(self):
assignment_days = self.get_assignment_days()
@ -357,9 +356,7 @@ def update_due_date(doc, state=None):
rule_doc = frappe.get_cached_doc("Assignment Rule", rule.get("name"))
due_date_field = rule_doc.due_date_based_on
field_updated = (
doc.meta.has_field(due_date_field)
and doc.has_value_changed(due_date_field)
and rule.get("name")
doc.meta.has_field(due_date_field) and doc.has_value_changed(due_date_field) and rule.get("name")
)
if field_updated:

View File

@ -138,7 +138,9 @@ class TestAutoAssign(FrappeTestCase):
# check if auto assigned to doc owner, test1@example.com
self.assertEqual(
frappe.db.get_value(
"ToDo", dict(reference_type=TEST_DOCTYPE, reference_name=note.name, status="Open"), "owner"
"ToDo",
dict(reference_type=TEST_DOCTYPE, reference_name=note.name, status="Open"),
"owner",
),
test_user,
)

View File

@ -19,4 +19,5 @@ class AssignmentRuleDay(Document):
parentfield: DF.Data
parenttype: DF.Data
# end: auto-generated types
pass

View File

@ -19,4 +19,5 @@ class AssignmentRuleUser(Document):
parenttype: DF.Data
user: DF.Link
# end: auto-generated types
pass

View File

@ -70,6 +70,7 @@ class AutoRepeat(Document):
submit_on_creation: DF.Check
template: DF.Link | None
# end: auto-generated types
def validate(self):
self.update_status()
self.validate_reference_doctype()

View File

@ -53,9 +53,7 @@ class TestAutoRepeat(FrappeTestCase):
todo = frappe.get_doc(doc.reference_doctype, doc.reference_document)
self.assertEqual(todo.auto_repeat, doc.name)
new_todo = frappe.db.get_value(
"ToDo", {"auto_repeat": doc.name, "name": ("!=", todo.name)}, "name"
)
new_todo = frappe.db.get_value("ToDo", {"auto_repeat": doc.name, "name": ("!=", todo.name)}, "name")
new_todo = frappe.get_doc("ToDo", new_todo)
@ -81,9 +79,7 @@ class TestAutoRepeat(FrappeTestCase):
todo = frappe.get_doc(doc.reference_doctype, doc.reference_document)
self.assertEqual(todo.auto_repeat, doc.name)
new_todo = frappe.db.get_value(
"ToDo", {"auto_repeat": doc.name, "name": ("!=", todo.name)}, "name"
)
new_todo = frappe.db.get_value("ToDo", {"auto_repeat": doc.name, "name": ("!=", todo.name)}, "name")
new_todo = frappe.get_doc("ToDo", new_todo)
@ -128,7 +124,9 @@ class TestAutoRepeat(FrappeTestCase):
# test without end_date
todo = frappe.get_doc(
dict(
doctype="ToDo", description="test recurring todo without end_date", assigned_by="Administrator"
doctype="ToDo",
description="test recurring todo without end_date",
assigned_by="Administrator",
)
).insert()
self.monthly_auto_repeat("ToDo", todo.name, start_date)
@ -183,13 +181,9 @@ class TestAutoRepeat(FrappeTestCase):
create_repeated_entries(data)
frappe.db.commit()
new_todo = frappe.db.get_value(
"ToDo", {"auto_repeat": doc.name, "name": ("!=", todo.name)}, "name"
)
new_todo = frappe.db.get_value("ToDo", {"auto_repeat": doc.name, "name": ("!=", todo.name)}, "name")
email_queue = frappe.db.exists(
"Email Queue", dict(reference_doctype="ToDo", reference_name=new_todo)
)
email_queue = frappe.db.exists("Email Queue", dict(reference_doctype="ToDo", reference_name=new_todo))
self.assertTrue(email_queue)
def test_next_schedule_date(self):
@ -208,9 +202,7 @@ class TestAutoRepeat(FrappeTestCase):
self.assertTrue(doc.next_schedule_date >= current_date)
todo = frappe.get_doc(
dict(
doctype="ToDo", description="test next schedule date for daily", assigned_by="Administrator"
)
dict(doctype="ToDo", description="test next schedule date for daily", assigned_by="Administrator")
).insert()
doc = make_auto_repeat(
frequency="Daily", reference_document=todo.name, start_date=add_days(today(), -2)

View File

@ -19,4 +19,5 @@ class AutoRepeatDay(Document):
parentfield: DF.Data
parenttype: DF.Data
# end: auto-generated types
pass

View File

@ -20,6 +20,7 @@ class Milestone(Document):
track_field: DF.Data
value: DF.Data
# end: auto-generated types
pass

View File

@ -20,6 +20,7 @@ class MilestoneTracker(Document):
document_type: DF.Link
track_field: DF.Literal
# end: auto-generated types
def on_update(self):
frappe.cache_manager.clear_doctype_map("Milestone Tracker", self.document_type)

View File

@ -24,6 +24,7 @@ class Reminder(Document):
reminder_doctype: DF.Link | None
user: DF.Link
# end: auto-generated types
@staticmethod
def clear_old_logs(days=30):
from frappe.query_builder import Interval

View File

@ -10,7 +10,6 @@ from frappe.utils import add_to_date, now_datetime
class TestReminder(FrappeTestCase):
def test_reminder(self):
description = "TEST_REMINDER"
create_new_reminder(

View File

@ -176,9 +176,7 @@ def get_user_pages_or_reports(parent, cache=False):
frappe.qb.from_(customRole)
.from_(hasRole)
.from_(parentTable)
.select(
customRole[parent.lower()].as_("name"), customRole.modified, customRole.ref_doctype, *columns
)
.select(customRole[parent.lower()].as_("name"), customRole.modified, customRole.ref_doctype, *columns)
.where(
(hasRole.parent == customRole.name)
& (parentTable.name == customRole[parent.lower()])
@ -201,9 +199,7 @@ def get_user_pages_or_reports(parent, cache=False):
.from_(parentTable)
.select(parentTable.name.as_("name"), parentTable.modified, *columns)
.where(
(hasRole.role.isin(roles))
& (hasRole.parent == parentTable.name)
& (parentTable.name.notin(subq))
(hasRole.role.isin(roles)) & (hasRole.parent == parentTable.name) & (parentTable.name.notin(subq))
)
.distinct()
)
@ -225,7 +221,6 @@ def get_user_pages_or_reports(parent, cache=False):
# pages with no role are allowed
if parent == "Page":
pages_with_no_roles = (
frappe.qb.from_(parentTable)
.select(parentTable.name, parentTable.modified, *columns)

View File

@ -378,9 +378,7 @@ def make_asset_dirs(hard_link=False):
symlinks = generate_assets_map()
for source, target in symlinks.items():
start_message = unstrip(
f"{'Copying assets from' if hard_link else 'Linking'} {source} to {target}"
)
start_message = unstrip(f"{'Copying assets from' if hard_link else 'Linking'} {source} to {target}")
fail_message = unstrip(f"Cannot {'copy' if hard_link else 'link'} {source} to {target}")
# Used '\r' instead of '\x1b[1K\r' to print entire lines in smaller terminal sizes

View File

@ -197,9 +197,7 @@ def build_table_count_cache():
table_rows = frappe.qb.Field("table_rows").as_("count")
information_schema = frappe.qb.Schema("information_schema")
data = (frappe.qb.from_(information_schema.tables).select(table_name, table_rows)).run(
as_dict=True
)
data = (frappe.qb.from_(information_schema.tables).select(table_name, table_rows)).run(as_dict=True)
counts = {d.get("name").replace("tab", "", 1): d.get("count", None) for d in data}
frappe.cache.set_value("information_schema:counts", counts)

View File

@ -35,9 +35,7 @@ def compile_translations(context, app: str | None = None, locale: str = None, fo
_compile_translations(app, locale, force=force)
@click.command(
"migrate-csv-to-po", help="Translation: migrate from CSV files (old) to PO files (new)"
)
@click.command("migrate-csv-to-po", help="Translation: migrate from CSV files (old) to PO files (new)")
@click.option("--app", help="Only migrate for this app. eg: frappe")
@click.option("--locale", help="Compile translations only for this locale. eg: de")
@pass_context

View File

@ -13,9 +13,7 @@ from frappe.utils.redis_queue import RedisQueue
default=False,
help="Set new Redis admin(default user) password",
)
@click.option(
"--use-rq-auth", is_flag=True, default=False, help="Enable Redis authentication for sites"
)
@click.option("--use-rq-auth", is_flag=True, default=False, help="Enable Redis authentication for sites")
def create_rq_users(set_admin_password=False, use_rq_auth=False):
"""Create Redis Queue users and add to acl and app configs.
@ -46,9 +44,7 @@ def create_rq_users(set_admin_password=False, use_rq_auth=False):
validate=False,
site_config_path=common_site_config_path,
)
update_site_config(
"use_rq_auth", use_rq_auth, validate=False, site_config_path=common_site_config_path
)
update_site_config("use_rq_auth", use_rq_auth, validate=False, site_config_path=common_site_config_path)
click.secho(
"* ACL and site configs are updated with new user credentials. "
@ -65,8 +61,7 @@ def create_rq_users(set_admin_password=False, use_rq_auth=False):
)
click.secho(f"`export {env_key}={user_credentials['default'][1]}`")
click.secho(
"NOTE: Please save the admin password as you "
"can not access redis server without the password",
"NOTE: Please save the admin password as you " "can not access redis server without the password",
fg="yellow",
)

View File

@ -74,9 +74,7 @@ def disable_scheduler(context):
@click.command("scheduler")
@click.option("--site", help="site name")
@click.argument("state", type=click.Choice(["pause", "resume", "disable", "enable", "status"]))
@click.option(
"--format", "-f", default="text", type=click.Choice(["json", "text"]), help="Output format"
)
@click.option("--format", "-f", default="text", type=click.Choice(["json", "text"]), help="Output format")
@click.option("--verbose", "-v", is_flag=True, help="Verbose output")
@pass_context
def scheduler(context, state: str, format: str, verbose: bool = False, site: str | None = None):
@ -128,9 +126,7 @@ def set_maintenance_mode(context, state, site=None):
frappe.destroy()
@click.command(
"doctor"
) # Passing context always gets a site and if there is no use site it breaks
@click.command("doctor") # Passing context always gets a site and if there is no use site it breaks
@click.option("--site", help="site name")
@pass_context
def doctor(context, site=None):
@ -199,9 +195,7 @@ def start_scheduler():
type=click.Choice(["round_robin", "random"]),
help="Dequeuing strategy to use",
)
def start_worker(
queue, quiet=False, rq_username=None, rq_password=None, burst=False, strategy=None
):
def start_worker(queue, quiet=False, rq_username=None, rq_password=None, burst=False, strategy=None):
"""Start a background worker"""
from frappe.utils.background_jobs import start_worker

View File

@ -29,9 +29,7 @@ from frappe.exceptions import SiteNotSpecifiedError
"--mariadb-root-username",
help='Root username for MariaDB or PostgreSQL, Default is "root"',
)
@click.option(
"--db-root-password", "--mariadb-root-password", help="Root password for MariaDB or PostgreSQL"
)
@click.option("--db-root-password", "--mariadb-root-password", help="Root password for MariaDB or PostgreSQL")
@click.option(
"--no-mariadb-socket",
is_flag=True,
@ -40,14 +38,10 @@ from frappe.exceptions import SiteNotSpecifiedError
)
@click.option("--admin-password", help="Administrator password for new site", default=None)
@click.option("--verbose", is_flag=True, default=False, help="Verbose")
@click.option(
"--force", help="Force restore if site/database already exists", is_flag=True, default=False
)
@click.option("--force", help="Force restore if site/database already exists", is_flag=True, default=False)
@click.option("--source-sql", "--source_sql", help="Initiate database with a SQL file")
@click.option("--install-app", multiple=True, help="Install app after installation")
@click.option(
"--set-default", is_flag=True, default=False, help="Set the new site as default site"
)
@click.option("--set-default", is_flag=True, default=False, help="Set the new site as default site")
@click.option(
"--setup-db/--no-setup-db",
default=True,
@ -108,15 +102,11 @@ def new_site(
"--mariadb-root-username",
help='Root username for MariaDB or PostgreSQL, Default is "root"',
)
@click.option(
"--db-root-password", "--mariadb-root-password", help="Root password for MariaDB or PostgreSQL"
)
@click.option("--db-root-password", "--mariadb-root-password", help="Root password for MariaDB or PostgreSQL")
@click.option("--db-name", help="Database name for site in case it is a new one")
@click.option("--admin-password", help="Administrator password for new site")
@click.option("--install-app", multiple=True, help="Install app after installation")
@click.option(
"--with-public-files", help="Restores the public files of the site, given path to its tar file"
)
@click.option("--with-public-files", help="Restores the public files of the site, given path to its tar file")
@click.option(
"--with-private-files",
help="Restores the private files of the site, given path to its tar file",
@ -299,8 +289,7 @@ def restore_backup(
# Check if the backup is of an older version of frappe and the user hasn't specified force
if is_downgrade(sql_file_path, verbose=True) and not force:
warn_message = (
"This is not recommended and may lead to unexpected behaviour. "
"Do you want to continue anyway?"
"This is not recommended and may lead to unexpected behaviour. " "Do you want to continue anyway?"
)
click.confirm(warn_message, abort=True)
@ -391,14 +380,10 @@ def partial_restore(context, sql_file_path, verbose, encryption_key=None):
"--mariadb-root-username",
help='Root username for MariaDB or PostgreSQL, Default is "root"',
)
@click.option(
"--db-root-password", "--mariadb-root-password", help="Root password for MariaDB or PostgreSQL"
)
@click.option("--db-root-password", "--mariadb-root-password", help="Root password for MariaDB or PostgreSQL")
@click.option("--yes", is_flag=True, default=False, help="Pass --yes to skip confirmation")
@pass_context
def reinstall(
context, admin_password=None, db_root_username=None, db_root_password=None, yes=False
):
def reinstall(context, admin_password=None, db_root_username=None, db_root_password=None, yes=False):
"Reinstall site ie. wipe all data and start over"
site = get_site(context)
_reinstall(site, admin_password, db_root_username, db_root_password, yes, verbose=context.verbose)
@ -860,9 +845,7 @@ def use(site, sites_path="."):
type=str,
help="Specify the DocTypes to not backup seperated by commas",
)
@click.option(
"--backup-path", default=None, help="Set path for saving all the files in this operation"
)
@click.option("--backup-path", default=None, help="Set path for saving all the files in this operation")
@click.option("--backup-path-db", default=None, help="Set path for saving database file")
@click.option("--backup-path-files", default=None, help="Set path for saving public file")
@click.option("--backup-path-private-files", default=None, help="Set path for saving private file")
@ -875,9 +858,7 @@ def use(site, sites_path="."):
)
@click.option("--verbose", default=False, is_flag=True, help="Add verbosity")
@click.option("--compress", default=False, is_flag=True, help="Compress private and public files")
@click.option(
"--old-backup-metadata", default=False, is_flag=True, help="Use older backup metadata"
)
@click.option("--old-backup-metadata", default=False, is_flag=True, help="Use older backup metadata")
@pass_context
def backup(
context,
@ -977,9 +958,7 @@ def remove_from_installed_apps(context, app):
is_flag=True,
default=False,
)
@click.option(
"--dry-run", help="List all doctypes that will be deleted", is_flag=True, default=False
)
@click.option("--dry-run", help="List all doctypes that will be deleted", is_flag=True, default=False)
@click.option("--no-backup", help="Do not backup the site", is_flag=True, default=False)
@click.option("--force", help="Force remove app from site", is_flag=True, default=False)
@pass_context
@ -1016,9 +995,7 @@ def uninstall(context, app, dry_run, yes, no_backup, force):
)
@click.option("--archived-sites-path")
@click.option("--no-backup", is_flag=True, default=False)
@click.option(
"--force", help="Force drop-site even if an error is encountered", is_flag=True, default=False
)
@click.option("--force", help="Force drop-site even if an error is encountered", is_flag=True, default=False)
def drop_site(
site,
db_root_username="root",
@ -1105,9 +1082,7 @@ def move(dest_dir, site):
@click.command("set-password")
@click.argument("user")
@click.argument("password", required=False)
@click.option(
"--logout-all-sessions", help="Log out from all sessions", is_flag=True, default=False
)
@click.option("--logout-all-sessions", help="Log out from all sessions", is_flag=True, default=False)
@pass_context
def set_password(context, user, password=None, logout_all_sessions=False):
"Set password for a user on a site"
@ -1120,9 +1095,7 @@ def set_password(context, user, password=None, logout_all_sessions=False):
@click.command("set-admin-password")
@click.argument("admin-password", required=False)
@click.option(
"--logout-all-sessions", help="Log out from all sessions", is_flag=True, default=False
)
@click.option("--logout-all-sessions", help="Log out from all sessions", is_flag=True, default=False)
@pass_context
def set_admin_password(context, admin_password=None, logout_all_sessions=False):
"Set Administrator password for a site"
@ -1279,9 +1252,7 @@ def stop_recording(context):
@click.command("ngrok")
@click.option(
"--bind-tls", is_flag=True, default=False, help="Returns a reference to the https tunnel."
)
@click.option("--bind-tls", is_flag=True, default=False, help="Returns a reference to the https tunnel.")
@click.option(
"--use-default-authtoken",
is_flag=True,
@ -1389,9 +1360,7 @@ def clear_log_table(context, doctype, days, no_backup):
@click.command("trim-database")
@click.option("--dry-run", is_flag=True, default=False, help="Show what would be deleted")
@click.option(
"--format", "-f", default="text", type=click.Choice(["json", "text"]), help="Output format"
)
@click.option("--format", "-f", default="text", type=click.Choice(["json", "text"]), help="Output format")
@click.option("--no-backup", is_flag=True, default=False, help="Do not backup the site")
@click.option(
"--yes",
@ -1501,9 +1470,7 @@ def get_standard_tables():
@click.command("trim-tables")
@click.option("--dry-run", is_flag=True, default=False, help="Show what would be deleted")
@click.option(
"--format", "-f", default="table", type=click.Choice(["json", "table"]), help="Output format"
)
@click.option("--format", "-f", default="table", type=click.Choice(["json", "table"]), help="Output format")
@click.option("--no-backup", is_flag=True, default=False, help="Do not backup the site")
@pass_context
def trim_tables(context, dry_run, format, no_backup):

View File

@ -39,13 +39,9 @@ def new_language(context, lang_code, app):
frappe.translate.write_translations_file(app, lang_code)
print(
"File created at ./apps/{app}/{app}/translations/{lang_code}.csv".format(
app=app, lang_code=lang_code
)
)
print(
"You will need to add the language in frappe/geo/languages.json, if you haven't done it already."
"File created at ./apps/{app}/{app}/translations/{lang_code}.csv".format(app=app, lang_code=lang_code)
)
print("You will need to add the language in frappe/geo/languages.json, if you haven't done it already.")
@click.command("get-untranslated")

View File

@ -437,14 +437,10 @@ def import_doc(context, path, force=False):
default="Insert",
help="Insert New Records or Update Existing Records",
)
@click.option(
"--submit-after-import", default=False, is_flag=True, help="Submit document after importing it"
)
@click.option("--submit-after-import", default=False, is_flag=True, help="Submit document after importing it")
@click.option("--mute-emails", default=True, is_flag=True, help="Mute emails during import")
@pass_context
def data_import(
context, file_path, doctype, import_type=None, submit_after_import=False, mute_emails=True
):
def data_import(context, file_path, doctype, import_type=None, submit_after_import=False, mute_emails=True):
"Import documents in bulk from CSV or XLSX using data import"
from frappe.core.doctype.data_import.data_import import import_file
@ -570,9 +566,7 @@ frappe.connect()
frappe.local.lang = frappe.db.get_default('lang')
frappe.db.connect()
```
""".format(
site=site, sites_path=sites_path
)
""".format(site=site, sites_path=sites_path)
)
os.execv(
f"{bin_path}/jupyter",
@ -630,9 +624,7 @@ def console(context, autoreload=False):
terminal()
@click.command(
"transform-database", help="Change tables' internal settings changing engine and row formats"
)
@click.command("transform-database", help="Change tables' internal settings changing engine and row formats")
@click.option(
"--table",
required=True,
@ -731,9 +723,7 @@ def transform_database(context, table, engine, row_format, failfast):
@click.option("--profile", is_flag=True, default=False)
@click.option("--coverage", is_flag=True, default=False)
@click.option("--skip-test-records", is_flag=True, default=False, help="Don't create test records")
@click.option(
"--skip-before-tests", is_flag=True, default=False, help="Don't run before tests hook"
)
@click.option("--skip-before-tests", is_flag=True, default=False, help="Don't run before tests hook")
@click.option("--junit-xml-output", help="Destination file path for junit xml report")
@click.option(
"--failfast", is_flag=True, default=False, help="Stop the test run on the first error or failure"
@ -983,7 +973,9 @@ def request(context, args=None, path=None):
frappe.connect()
if args:
if "?" in args:
frappe.local.form_dict = frappe._dict([a.split("=") for a in args.split("?")[-1].split("&")])
frappe.local.form_dict = frappe._dict(
[a.split("=") for a in args.split("?")[-1].split("&")]
)
else:
frappe.local.form_dict = frappe._dict()
@ -1007,9 +999,7 @@ def request(context, args=None, path=None):
@click.command("make-app")
@click.argument("destination")
@click.argument("app_name")
@click.option(
"--no-git", is_flag=True, default=False, help="Do not initialize git repository for the app"
)
@click.option("--no-git", is_flag=True, default=False, help="Do not initialize git repository for the app")
def make_app(destination, app_name, no_git=False):
"Creates a boilerplate app"
from frappe.utils.boilerplate import make_boilerplate
@ -1030,9 +1020,7 @@ def create_patch():
@click.command("set-config")
@click.argument("key")
@click.argument("value")
@click.option(
"-g", "--global", "global_", is_flag=True, default=False, help="Set value in bench config"
)
@click.option("-g", "--global", "global_", is_flag=True, default=False, help="Set value in bench config")
@click.option("-p", "--parse", is_flag=True, default=False, help="Evaluate as Python Object")
@pass_context
def set_config(context, key, value, global_=False, parse=False):
@ -1109,9 +1097,7 @@ def get_version(output):
@click.command("rebuild-global-search")
@click.option(
"--static-pages", is_flag=True, default=False, help="Rebuild global search for static pages"
)
@click.option("--static-pages", is_flag=True, default=False, help="Rebuild global search for static pages")
@pass_context
def rebuild_global_search(context, static_pages=False):
"""Setup help table in the current site (called after migrate)"""

View File

@ -30,9 +30,7 @@ def get_modules_from_all_apps():
def get_modules_from_app(app):
return frappe.get_all(
"Module Def", filters={"app_name": app}, fields=["module_name", "app_name as app"]
)
return frappe.get_all("Module Def", filters={"app_name": app}, fields=["module_name", "app_name as app"])
def get_all_empty_tables_by_module():

View File

@ -52,6 +52,7 @@ class Address(Document):
pincode: DF.Data | None
state: DF.Data | None
# end: auto-generated types
def __setup__(self):
self.flags.linked = False
@ -140,9 +141,7 @@ def get_preferred_address(doctype, name, preferred_key="is_primary_address"):
@frappe.whitelist()
def get_default_address(
doctype: str, name: str | None, sort_key: str = "is_primary_address"
) -> str | None:
def get_default_address(doctype: str, name: str | None, sort_key: str = "is_primary_address") -> str | None:
"""Return default Address name for the given doctype, name."""
if sort_key not in ["is_shipping_address", "is_primary_address"]:
return None

View File

@ -20,6 +20,7 @@ class AddressTemplate(Document):
is_default: DF.Check
template: DF.Code | None
# end: auto-generated types
def validate(self):
validate_template(self.template)

View File

@ -25,9 +25,7 @@ class TestAddressTemplate(FrappeTestCase):
self.assertEqual(frappe.db.get_value("Address Template", "Brazil", "is_default"), 1)
def test_delete_address_template(self):
india = frappe.get_doc(
{"doctype": "Address Template", "country": "India", "is_default": 0}
).insert()
india = frappe.get_doc({"doctype": "Address Template", "country": "India", "is_default": 0}).insert()
brazil = frappe.get_doc(
{"doctype": "Address Template", "country": "Brazil", "is_default": 1}

View File

@ -47,6 +47,7 @@ class Contact(Document):
unsubscribed: DF.Check
user: DF.Link | None
# end: auto-generated types
def autoname(self):
self.name = self._get_full_name()
@ -248,10 +249,7 @@ def contact_query(doctype, txt, searchfield, start, page_len, filters):
from frappe.desk.reportview import get_match_cond
doctype = "Contact"
if (
not frappe.get_meta(doctype).get_field(searchfield)
and searchfield not in frappe.db.DEFAULT_COLUMNS
):
if not frappe.get_meta(doctype).get_field(searchfield) and searchfield not in frappe.db.DEFAULT_COLUMNS:
return []
link_doctype = filters.pop("link_doctype")
@ -272,9 +270,7 @@ def contact_query(doctype, txt, searchfield, start, page_len, filters):
order by
if(locate(%(_txt)s, `tabContact`.full_name), locate(%(_txt)s, `tabContact`.company_name), 99999),
`tabContact`.idx desc, `tabContact`.full_name
limit %(start)s, %(page_len)s """.format(
mcond=get_match_cond(doctype), key=searchfield
),
limit %(start)s, %(page_len)s """.format(mcond=get_match_cond(doctype), key=searchfield),
{
"txt": "%" + txt + "%",
"_txt": txt.replace("%", ""),
@ -291,8 +287,7 @@ def address_query(links):
import json
links = [
{"link_doctype": d.get("link_doctype"), "link_name": d.get("link_name")}
for d in json.loads(links)
{"link_doctype": d.get("link_doctype"), "link_name": d.get("link_name")} for d in json.loads(links)
]
result = []
@ -335,9 +330,7 @@ def get_contact_with_phone_number(number):
def get_contact_name(email_id):
contact = frappe.get_all(
"Contact Email", filters={"email_id": email_id}, fields=["parent"], limit=1
)
contact = frappe.get_all("Contact Email", filters={"email_id": email_id}, fields=["parent"], limit=1)
return contact[0].parent if contact else None

View File

@ -20,4 +20,5 @@ class ContactEmail(Document):
parentfield: DF.Data
parenttype: DF.Data
# end: auto-generated types
pass

View File

@ -21,4 +21,5 @@ class ContactPhone(Document):
parenttype: DF.Data
phone: DF.Data
# end: auto-generated types
pass

View File

@ -15,4 +15,5 @@ class Gender(Document):
gender: DF.Data | None
# end: auto-generated types
pass

View File

@ -15,4 +15,5 @@ class Salutation(Document):
salutation: DF.Data | None
# end: auto-generated types
pass

View File

@ -76,12 +76,8 @@ def get_reference_addresses_and_contact(reference_doctype, reference_name):
for d in reference_list:
reference_details.setdefault(d, frappe._dict())
reference_details = get_reference_details(
reference_doctype, "Address", reference_list, reference_details
)
reference_details = get_reference_details(
reference_doctype, "Contact", reference_list, reference_details
)
reference_details = get_reference_details(reference_doctype, "Address", reference_list, reference_details)
reference_details = get_reference_details(reference_doctype, "Contact", reference_list, reference_details)
for reference_name, details in reference_details.items():
addresses = details.get("address", [])

View File

@ -27,6 +27,7 @@ class AccessLog(Document):
timestamp: DF.Datetime | None
user: DF.Link | None
# end: auto-generated types
@staticmethod
def clear_old_logs(days=30):
from frappe.query_builder import Interval

View File

@ -34,6 +34,7 @@ class ActivityLog(Document):
timeline_name: DF.DynamicLink | None
user: DF.Link | None
# end: auto-generated types
def before_insert(self):
self.full_name = get_fullname(self.user)
self.date = now()

View File

@ -9,7 +9,6 @@ from frappe.tests.utils import FrappeTestCase
class TestActivityLog(FrappeTestCase):
def test_activity_log(self):
# test user login log
frappe.local.form_dict = frappe._dict(
{

View File

@ -20,4 +20,5 @@ class AmendedDocumentNamingSettings(Document):
parentfield: DF.Data
parenttype: DF.Data
# end: auto-generated types
pass

View File

@ -24,6 +24,7 @@ class AuditTrail(Document):
end_date: DF.Date | None
start_date: DF.Date | None
# end: auto-generated types
pass
def validate(self):

View File

@ -18,4 +18,5 @@ class BlockModule(Document):
parentfield: DF.Data
parenttype: DF.Data
# end: auto-generated types
pass

View File

@ -52,6 +52,7 @@ class Comment(Document):
seen: DF.Check
subject: DF.Text | None
# end: auto-generated types
def after_insert(self):
notify_mentions(self.reference_doctype, self.reference_name, self.content)
self.notify_change("add")

View File

@ -57,9 +57,7 @@ class TestComment(FrappeTestCase):
frappe.db.delete("Comment", {"reference_doctype": "Blog Post"})
add_comment_args.update(
comment="pleez vizits my site http://mysite.com", comment_by="bad commentor"
)
add_comment_args.update(comment="pleez vizits my site http://mysite.com", comment_by="bad commentor")
add_comment(**add_comment_args)
self.assertEqual(

View File

@ -119,6 +119,7 @@ class Communication(Document, CommunicationEmailMixin):
unread_notification_sent: DF.Check
user: DF.Link | None
# end: auto-generated types
"""Communication represents an external communication like Email."""
no_feed_on_delete = True
@ -133,7 +134,6 @@ class Communication(Document, CommunicationEmailMixin):
and self.uid
and self.uid != -1
):
email_flag_queue = frappe.db.get_value(
"Email Flag Queue", {"communication": self.name, "is_completed": 0}
)

View File

@ -239,9 +239,7 @@ class CommunicationEmailMixin:
if not emails:
return []
return frappe.get_all(
"User", pluck="email", filters={"email": ["in", emails], "thread_notify": 0}
)
return frappe.get_all("User", pluck="email", filters={"email": ["in", emails], "thread_notify": 0})
@staticmethod
def filter_disabled_users(emails):
@ -259,7 +257,6 @@ class CommunicationEmailMixin:
print_letterhead=None,
is_inbound_mail_communcation=None,
) -> dict:
outgoing_email_account = self.get_outgoing_email_account()
if not outgoing_email_account:
return {}
@ -270,9 +267,7 @@ class CommunicationEmailMixin:
cc = self.get_mail_cc_with_displayname(
is_inbound_mail_communcation=is_inbound_mail_communcation, include_sender=send_me_a_copy
)
bcc = self.get_mail_bcc_with_displayname(
is_inbound_mail_communcation=is_inbound_mail_communcation
)
bcc = self.get_mail_bcc_with_displayname(is_inbound_mail_communcation=is_inbound_mail_communcation)
if not (recipients or cc):
return {}

View File

@ -21,6 +21,7 @@ class CommunicationLink(Document):
parentfield: DF.Data
parenttype: DF.Data
# end: auto-generated types
pass

View File

@ -32,5 +32,6 @@ class CustomDocPerm(Document):
submit: DF.Check
write: DF.Check
# end: auto-generated types
def on_update(self):
frappe.clear_cache(doctype=self.parent)

View File

@ -20,6 +20,7 @@ class CustomRole(Document):
report: DF.Link | None
roles: DF.Table[HasRole]
# end: auto-generated types
def validate(self):
if self.report and not self.ref_doctype:
self.ref_doctype = frappe.db.get_value("Report", self.report, "ref_doctype")

View File

@ -17,4 +17,5 @@ class DataExport(Document):
file_type: DF.Literal["Excel", "CSV"]
reference_doctype: DF.Link
# end: auto-generated types
pass

View File

@ -183,9 +183,7 @@ class DataExporter:
self.writer.writerow([_("Notes:")])
self.writer.writerow([_("Please do not change the template headings.")])
self.writer.writerow([_("First data column must be blank.")])
self.writer.writerow(
[_('If you are uploading new records, leave the "name" (ID) column blank.')]
)
self.writer.writerow([_('If you are uploading new records, leave the "name" (ID) column blank.')])
self.writer.writerow(
[_('If you are uploading new records, "Naming Series" becomes mandatory, if present.')]
)
@ -252,7 +250,9 @@ class DataExporter:
"label": "Parent",
"fieldtype": "Data",
"reqd": 1,
"info": _("Parent is the name of the document to which the data will get added to."),
"info": _(
"Parent is the name of the document to which the data will get added to."
),
}
),
True,

View File

@ -154,9 +154,7 @@ def start_import(data_import):
@frappe.whitelist()
def download_template(
doctype, export_fields=None, export_records=None, export_filters=None, file_type="CSV"
):
def download_template(doctype, export_fields=None, export_records=None, export_filters=None, file_type="CSV"):
"""
Download template from Exporter
:param doctype: Document Type

View File

@ -50,9 +50,7 @@ class Exporter:
self.add_data()
def get_all_exportable_fields(self):
child_table_fields = [
df.fieldname for df in self.meta.fields if df.fieldtype in table_fieldtypes
]
child_table_fields = [df.fieldname for df in self.meta.fields if df.fieldtype in table_fieldtypes]
meta = frappe.get_meta(self.doctype)
exportable_fields = frappe._dict({})
@ -206,9 +204,7 @@ class Exporter:
if is_parent:
label = _(df.label or df.fieldname)
else:
label = (
f"{_(df.label or df.fieldname)} ({_(df.child_table_df.label or df.child_table_df.fieldname)})"
)
label = f"{_(df.label or df.fieldname)} ({_(df.child_table_df.label or df.child_table_df.fieldname)})"
if label in header:
# this label is already in the header,

View File

@ -103,10 +103,7 @@ class Importer:
log_index = 0
# Do not remove rows in case of retry after an error or pending data import
if (
self.data_import.status == "Partial Success"
and len(import_log) >= self.data_import.payload_count
):
if self.data_import.status == "Partial Success" and len(import_log) >= self.data_import.payload_count:
# remove previous failures from import log only in case of retry after partial success
import_log = [log for log in import_log if log.get("success")]
@ -622,7 +619,9 @@ class Row:
if len_row != len_columns:
less_than_columns = len_row < len_columns
message = (
"Row has less values than columns" if less_than_columns else "Row has more values than columns"
"Row has less values than columns"
if less_than_columns
else "Row has more values than columns"
)
self.warnings.append(
{
@ -989,9 +988,7 @@ class Column:
if self.df.fieldtype == "Link":
# find all values that dont exist
values = list({cstr(v) for v in self.column_values if v})
exists = [
cstr(d.name) for d in frappe.get_all(self.df.options, filters={"name": ("in", values)})
]
exists = [cstr(d.name) for d in frappe.get_all(self.df.options, filters={"name": ("in", values)})]
not_exists = list(set(values) - set(exists))
if not_exists:
missing_values = ", ".join(not_exists)
@ -1236,9 +1233,7 @@ def get_item_at_index(_list, i, default=None):
def get_user_format(date_format):
return (
date_format.replace("%Y", "yyyy").replace("%y", "yy").replace("%m", "mm").replace("%d", "dd")
)
return date_format.replace("%Y", "yyyy").replace("%y", "yy").replace("%m", "mm").replace("%d", "dd")
def df_as_json(df):

View File

@ -22,4 +22,5 @@ class DataImportLog(Document):
row_indexes: DF.Code | None
success: DF.Check
# end: auto-generated types
pass

View File

@ -20,6 +20,7 @@ class DefaultValue(Document):
parentfield: DF.Data
parenttype: DF.Data
# end: auto-generated types
pass

View File

@ -25,6 +25,7 @@ class DeletedDocument(Document):
new_name: DF.ReadOnly | None
restored: DF.Check
# end: auto-generated types
pass
@staticmethod

View File

@ -33,4 +33,5 @@ class DocPerm(Document):
submit: DF.Check
write: DF.Check
# end: auto-generated types
pass

View File

@ -28,6 +28,7 @@ class DocShare(Document):
user: DF.Link | None
write: DF.Check
# end: auto-generated types
no_feed_on_delete = True
def validate(self):
@ -58,13 +59,10 @@ class DocShare(Document):
if not self.flags.ignore_share_permission and not frappe.has_permission(
self.share_doctype, "share", self.get_doc()
):
frappe.throw(_('You need to have "Share" permission'), frappe.PermissionError)
def check_is_submittable(self):
if self.submit and not cint(
frappe.db.get_value("DocType", self.share_doctype, "is_submittable")
):
if self.submit and not cint(frappe.db.get_value("DocType", self.share_doctype, "is_submittable")):
frappe.throw(
_("Cannot share {0} with submit permission as the doctype {1} is not submittable").format(
frappe.bold(self.share_name), frappe.bold(self.share_doctype)

View File

@ -136,9 +136,7 @@ class TestDocShare(FrappeTestCase):
doctype = "Test DocShare with Submit"
create_submittable_doctype(doctype, submit_perms=0)
submittable_doc = frappe.get_doc(
dict(doctype=doctype, test="test docshare with submit")
).insert()
submittable_doc = frappe.get_doc(dict(doctype=doctype, test="test docshare with submit")).insert()
frappe.set_user(self.user)
self.assertFalse(frappe.has_permission(doctype, "submit", user=self.user))
@ -147,15 +145,11 @@ class TestDocShare(FrappeTestCase):
frappe.share.add(doctype, submittable_doc.name, self.user, submit=1)
frappe.set_user(self.user)
self.assertTrue(
frappe.has_permission(doctype, "submit", doc=submittable_doc.name, user=self.user)
)
self.assertTrue(frappe.has_permission(doctype, "submit", doc=submittable_doc.name, user=self.user))
# test cascade
self.assertTrue(frappe.has_permission(doctype, "read", doc=submittable_doc.name, user=self.user))
self.assertTrue(
frappe.has_permission(doctype, "write", doc=submittable_doc.name, user=self.user)
)
self.assertTrue(frappe.has_permission(doctype, "write", doc=submittable_doc.name, user=self.user))
frappe.share.remove(doctype, submittable_doc.name, self.user)

View File

@ -133,7 +133,6 @@ class DocType(Document):
is_virtual: DF.Check
issingle: DF.Check
istable: DF.Check
link_filters: DF.JSON
links: DF.Table[DocTypeLink]
make_attachments_public: DF.Check
max_attachments: DF.Int
@ -313,7 +312,9 @@ class DocType(Document):
continue
frappe.msgprint(
_("{0} should be indexed because it's referred in dashboard connections").format(_(d.label)),
_("{0} should be indexed because it's referred in dashboard connections").format(
_(d.label)
),
alert=True,
indicator="orange",
)
@ -330,9 +331,7 @@ class DocType(Document):
)
if self.is_virtual and self.custom:
frappe.throw(
_("Not allowed to create custom Virtual DocType."), CannotCreateStandardDoctypeError
)
frappe.throw(_("Not allowed to create custom Virtual DocType."), CannotCreateStandardDoctypeError)
if frappe.conf.get("developer_mode"):
self.owner = "Administrator"
@ -485,10 +484,14 @@ class DocType(Document):
elif d.fieldtype in ("Section Break", "Column Break", "Tab Break"):
d.fieldname = d.fieldtype.lower().replace(" ", "_") + "_" + str(random_string(4))
else:
frappe.throw(_("Row #{}: Fieldname is required").format(d.idx), title="Missing Fieldname")
frappe.throw(
_("Row #{}: Fieldname is required").format(d.idx), title="Missing Fieldname"
)
else:
if d.fieldname in restricted:
frappe.throw(_("Fieldname {0} is restricted").format(d.fieldname), InvalidFieldNameError)
frappe.throw(
_("Fieldname {0} is restricted").format(d.fieldname), InvalidFieldNameError
)
d.fieldname = ILLEGAL_FIELDNAME_PATTERN.sub("", d.fieldname)
# fieldnames should be lowercase
@ -886,9 +889,7 @@ class DocType(Document):
if self.allow_auto_repeat:
if not frappe.db.exists(
"Custom Field", {"fieldname": "auto_repeat", "dt": self.name}
) and not frappe.db.exists(
"DocField", {"fieldname": "auto_repeat", "parent": self.name}
):
) and not frappe.db.exists("DocField", {"fieldname": "auto_repeat", "parent": self.name}):
insert_after = self.fields[len(self.fields) - 1].fieldname
df = dict(
fieldname="auto_repeat",
@ -997,7 +998,8 @@ class DocType(Document):
if len(name) > max_length:
# length(tab + <Doctype Name>) should be equal to 64 characters hence doctype should be 61 characters
frappe.throw(
_("Doctype name is limited to {0} characters ({1})").format(max_length, name), frappe.NameError
_("Doctype name is limited to {0} characters ({1})").format(max_length, name),
frappe.NameError,
)
# a DocType name should not start or end with an empty space
@ -1056,7 +1058,6 @@ def validate_series(dt, autoname=None, name=None):
and (not autoname.startswith("naming_series:"))
and (not autoname.startswith("format:"))
):
prefix = autoname.split(".", 1)[0]
doctype = frappe.qb.DocType("DocType")
used_in = (
@ -1095,7 +1096,6 @@ def validate_autoincrement_autoname(dt: Union[DocType, "CustomizeForm"]) -> bool
and autoname_before_save != "autoincrement"
or (not is_autoname_autoincrement and autoname_before_save == "autoincrement")
):
if dt.doctype == "Customize Form":
frappe.throw(_("Cannot change to/from autoincrement autoname in Customize Form"))
@ -1333,7 +1333,9 @@ def validate_fields(meta):
)
elif d.default not in d.options.split("\n"):
frappe.throw(
_("Default value for {0} must be in the list of options.").format(frappe.bold(d.fieldname))
_("Default value for {0} must be in the list of options.").format(
frappe.bold(d.fieldname)
)
)
def check_precision(d):
@ -1546,9 +1548,7 @@ def validate_fields(meta):
if docfield.get("is_virtual"):
return
if docfield.fieldtype == "Data" and not (
docfield.oldfieldtype and docfield.oldfieldtype != "Data"
):
if docfield.fieldtype == "Data" and not (docfield.oldfieldtype and docfield.oldfieldtype != "Data"):
if docfield.options and (docfield.options not in data_field_options):
df_str = frappe.bold(_(docfield.label))
text_str = (
@ -1688,9 +1688,7 @@ def validate_permissions(doctype, for_remove=False, alert=False):
return _("For {0} at level {1} in {2} in row {3}").format(d.role, d.permlevel, d.parent, d.idx)
def check_atleast_one_set(d):
if (
not d.select and not d.read and not d.write and not d.submit and not d.cancel and not d.create
):
if not d.select and not d.read and not d.write and not d.submit and not d.cancel and not d.create:
frappe.throw(_("{0}: No basic permissions set").format(get_txt(d)))
def check_double(d):
@ -1720,7 +1718,9 @@ def validate_permissions(doctype, for_remove=False, alert=False):
if not has_zero_perm:
frappe.throw(
_("{0}: Permission at level 0 must be set before higher levels are set").format(get_txt(d))
_("{0}: Permission at level 0 must be set before higher levels are set").format(
get_txt(d)
)
)
for invalid in ("create", "submit", "cancel", "amend"):
@ -1765,9 +1765,9 @@ def validate_permissions(doctype, for_remove=False, alert=False):
if doctype.custom:
if d.role in AUTOMATIC_ROLES:
frappe.throw(
_("Row # {0}: Non administrator user can not set the role {1} to the custom doctype").format(
d.idx, frappe.bold(_(d.role))
),
_(
"Row # {0}: Non administrator user can not set the role {1} to the custom doctype"
).format(d.idx, frappe.bold(_(d.role))),
title=_("Permissions Error"),
)
@ -1775,9 +1775,9 @@ def validate_permissions(doctype, for_remove=False, alert=False):
if d.role in roles:
frappe.throw(
_("Row # {0}: Non administrator user can not set the role {1} to the custom doctype").format(
d.idx, frappe.bold(_(d.role))
),
_(
"Row # {0}: Non administrator user can not set the role {1} to the custom doctype"
).format(d.idx, frappe.bold(_(d.role))),
title=_("Permissions Error"),
)
@ -1840,9 +1840,7 @@ def check_fieldname_conflicts(docfield):
doc = frappe.get_doc({"doctype": docfield.dt})
available_objects = [x for x in dir(doc) if isinstance(x, str)]
property_list = [x for x in available_objects if is_a_property(getattr(type(doc), x, None))]
method_list = [
x for x in available_objects if x not in property_list and callable(getattr(doc, x))
]
method_list = [x for x in available_objects if x not in property_list and callable(getattr(doc, x))]
msg = _("Fieldname {0} conflicting with meta object").format(docfield.fieldname)
if docfield.fieldname in method_list + property_list:

View File

@ -220,9 +220,7 @@ class TestDocType(FrappeTestCase):
self.assertListEqual(
[f["fieldname"] for f in test_doctype_json["fields"]], test_doctype_json["field_order"]
)
self.assertListEqual(
[f["fieldname"] for f in test_doctype_json["fields"]], initial_fields_order
)
self.assertListEqual([f["fieldname"] for f in test_doctype_json["fields"]], initial_fields_order)
self.assertListEqual(test_doctype_json["field_order"], initial_fields_order)
# remove field_order to test reload_doc/sync/migrate is backwards compatible without field_order
@ -246,9 +244,7 @@ class TestDocType(FrappeTestCase):
self.assertListEqual(
[f["fieldname"] for f in test_doctype_json["fields"]], test_doctype_json["field_order"]
)
self.assertListEqual(
[f["fieldname"] for f in test_doctype_json["fields"]], initial_fields_order
)
self.assertListEqual([f["fieldname"] for f in test_doctype_json["fields"]], initial_fields_order)
self.assertListEqual(test_doctype_json["field_order"], initial_fields_order)
# reorder fields: swap row 1 and 3
@ -259,9 +255,7 @@ class TestDocType(FrappeTestCase):
# assert that reordering fields only affects `field_order` rather than `fields` attr
test_doctype.save()
test_doctype_json = frappe.get_file_json(path)
self.assertListEqual(
[f["fieldname"] for f in test_doctype_json["fields"]], initial_fields_order
)
self.assertListEqual([f["fieldname"] for f in test_doctype_json["fields"]], initial_fields_order)
self.assertListEqual(
test_doctype_json["field_order"], ["field_3", "field_2", "field_1", "field_4"]
)

View File

@ -24,4 +24,5 @@ class DocTypeAction(Document):
parentfield: DF.Data
parenttype: DF.Data
# end: auto-generated types
pass

View File

@ -26,4 +26,5 @@ class DocTypeLink(Document):
parenttype: DF.Data
table_fieldname: DF.Data | None
# end: auto-generated types
pass

View File

@ -23,4 +23,5 @@ class DocTypeState(Document):
parenttype: DF.Data
title: DF.Data
# end: auto-generated types
pass

View File

@ -28,6 +28,7 @@ class DocumentNamingRule(Document):
prefix_digits: DF.Int
priority: DF.Int
# end: auto-generated types
def validate(self):
self.validate_fields_in_conditions()

View File

@ -21,4 +21,5 @@ class DocumentNamingRuleCondition(Document):
parenttype: DF.Data
value: DF.Data
# end: auto-generated types
pass

View File

@ -36,16 +36,15 @@ class DocumentNamingSettings(Document):
try_naming_series: DF.Data | None
user_must_always_select: DF.Check
# end: auto-generated types
@frappe.whitelist()
def get_transactions_and_prefixes(self):
transactions = self._get_transactions()
prefixes = self._get_prefixes(transactions)
return {"transactions": transactions, "prefixes": prefixes}
def _get_transactions(self) -> list[str]:
readable_doctypes = set(get_doctypes_with_read())
standard = frappe.get_all("DocField", {"fieldname": "naming_series"}, "parent", pluck="parent")
@ -218,9 +217,7 @@ class DocumentNamingSettings(Document):
previous_value = naming_series.get_current_value()
naming_series.update_counter(self.current_value)
self.create_version_log_for_change(
naming_series.get_prefix(), previous_value, self.current_value
)
self.create_version_log_for_change(naming_series.get_prefix(), previous_value, self.current_value)
frappe.msgprint(
_("Series counter for {} updated to {} successfully").format(self.prefix, self.current_value),

View File

@ -54,7 +54,6 @@ class TestNamingSeries(FrappeTestCase):
serieses = self.dns.preview_series().split("\n")
def test_get_transactions(self):
naming_info = self.dns.get_transactions_and_prefixes()
self.assertIn(self.ns_doctype, naming_info["transactions"])

View File

@ -21,6 +21,7 @@ class DocumentShareKey(Document):
reference_docname: DF.DynamicLink | None
reference_doctype: DF.Link | None
# end: auto-generated types
def before_insert(self):
self.key = frappe.generate_hash(length=randrange(25, 35))
if not self.expires_on and not self.flags.no_expiry:

View File

@ -18,6 +18,7 @@ class Domain(Document):
domain: DF.Data
# end: auto-generated types
"""Domain documents are created automatically when DocTypes
with "Restricted" domains are imported during
installation or migration"""
@ -123,9 +124,7 @@ class Domain(Document):
# enable
frappe.db.sql(
"""update `tabPortal Menu Item` set enabled=1
where route in ({})""".format(
", ".join(f'"{d}"' for d in self.data.allow_sidebar_items)
)
where route in ({})""".format(", ".join(f'"{d}"' for d in self.data.allow_sidebar_items))
)
if self.data.remove_sidebar_items:
@ -135,7 +134,5 @@ class Domain(Document):
# enable
frappe.db.sql(
"""update `tabPortal Menu Item` set enabled=0
where route in ({})""".format(
", ".join(f'"{d}"' for d in self.data.remove_sidebar_items)
)
where route in ({})""".format(", ".join(f'"{d}"' for d in self.data.remove_sidebar_items))
)

View File

@ -17,6 +17,7 @@ class DomainSettings(Document):
active_domains: DF.Table[HasDomain]
# end: auto-generated types
def set_active_domains(self, domains):
active_domains = [d.domain for d in self.active_domains]
added = False

View File

@ -21,6 +21,7 @@ class DynamicLink(Document):
parentfield: DF.Data
parenttype: DF.Data
# end: auto-generated types
pass

View File

@ -23,6 +23,7 @@ class ErrorLog(Document):
seen: DF.Check
trace_id: DF.Data | None
# end: auto-generated types
def onload(self):
if not self.seen and not frappe.flags.read_only:
self.db_set("seen", 1, update_modified=0)

View File

@ -61,6 +61,7 @@ class File(Document):
uploaded_to_dropbox: DF.Check
uploaded_to_google_drive: DF.Check
# end: auto-generated types
no_feed_on_delete = True
def __init__(self, *args, **kwargs):
@ -369,9 +370,7 @@ class File(Document):
return
if self.file_type not in allowed_extensions.splitlines():
frappe.throw(
_("File type of {0} is not allowed").format(self.file_type), exc=FileTypeNotAllowed
)
frappe.throw(_("File type of {0} is not allowed").format(self.file_type), exc=FileTypeNotAllowed)
def validate_duplicate_entry(self):
if not self.flags.ignore_duplicate_entry_error and not self.is_folder:
@ -710,9 +709,7 @@ class File(Document):
def create_attachment_record(self):
icon = ' <i class="fa fa-lock text-warning"></i>' if self.is_private else ""
file_url = (
quote(frappe.safe_encode(self.file_url), safe="/:") if self.file_url else self.file_name
)
file_url = quote(frappe.safe_encode(self.file_url), safe="/:") if self.file_url else self.file_name
file_name = self.file_name or self.file_url
self.add_comment_in_reference_doc(

View File

@ -222,9 +222,7 @@ class TestSameContent(FrappeTestCase):
doctype, docname = make_test_doc()
from frappe.custom.doctype.property_setter.property_setter import make_property_setter
limit_property = make_property_setter(
"ToDo", None, "max_attachments", 1, "int", for_doctype=True
)
limit_property = make_property_setter("ToDo", None, "max_attachments", 1, "int", for_doctype=True)
file1 = frappe.get_doc(
{
"doctype": "File",
@ -451,9 +449,7 @@ class TestFile(FrappeTestCase):
test_file.file_url = None
test_file.file_name = "/usr/bin/man"
self.assertRaisesRegex(
ValidationError, "There is some problem with the file url", test_file.validate
)
self.assertRaisesRegex(ValidationError, "There is some problem with the file url", test_file.validate)
test_file.file_url = None
test_file.file_name = "_file"
@ -670,9 +666,7 @@ class TestAttachmentsAccess(FrappeTestCase):
frappe.set_user("test4@example.com")
user_files = [file.file_name for file in get_files_in_folder("Home")["files"]]
user_attachments_files = [
file.file_name for file in get_files_in_folder("Home/Attachments")["files"]
]
user_attachments_files = [file.file_name for file in get_files_in_folder("Home/Attachments")["files"]]
self.assertIn("test_sm_standalone.txt", system_manager_files)
self.assertNotIn("test_sm_standalone.txt", user_files)

View File

@ -18,4 +18,5 @@ class HasDomain(Document):
parentfield: DF.Data
parenttype: DF.Data
# end: auto-generated types
pass

View File

@ -19,6 +19,7 @@ class HasRole(Document):
parenttype: DF.Data
role: DF.Link | None
# end: auto-generated types
def before_insert(self):
if frappe.db.exists("Has Role", {"parent": self.parent, "role": self.role}):
frappe.throw(frappe._("User '{0}' already has the role '{1}'").format(self.parent, self.role))

View File

@ -21,4 +21,5 @@ class InstalledApplication(Document):
parentfield: DF.Data
parenttype: DF.Data
# end: auto-generated types
pass

View File

@ -24,6 +24,7 @@ class InstalledApplications(Document):
installed_applications: DF.Table[InstalledApplication]
# end: auto-generated types
def update_versions(self):
self.delete_key("installed_applications")
for app in frappe.utils.get_installed_apps_info():

View File

@ -24,6 +24,7 @@ class Language(Document):
language_code: DF.Data
language_name: DF.Data
# end: auto-generated types
def validate(self):
validate_with_regex(self.language_code, "Language Code")

View File

@ -19,4 +19,5 @@ class LogSettingUser(Document):
parenttype: DF.Data
user: DF.Link
# end: auto-generated types
pass

View File

@ -41,6 +41,7 @@ class LogSettings(Document):
logs_to_clear: DF.Table[LogsToClear]
# end: auto-generated types
def validate(self):
self.remove_unsupported_doctypes()
self._deduplicate_entries()
@ -78,9 +79,7 @@ class LogSettings(Document):
added_logtypes.add(logtype)
if added_logtypes:
frappe.msgprint(
_("Added default log doctypes: {}").format(",".join(added_logtypes)), alert=True
)
frappe.msgprint(_("Added default log doctypes: {}").format(",".join(added_logtypes)), alert=True)
def clear_logs(self):
"""
@ -133,7 +132,6 @@ def has_unseen_error_log():
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_log_doctypes(doctype, txt, searchfield, start, page_len, filters):
filters = filters or {}
filters.extend(

View File

@ -20,4 +20,5 @@ class LogsToClear(Document):
parenttype: DF.Data
ref_doctype: DF.Link
# end: auto-generated types
pass

View File

@ -25,6 +25,7 @@ class ModuleDef(Document):
package: DF.Link | None
restrict_to_domain: DF.Link | None
# end: auto-generated types
def on_update(self):
"""If in `developer_mode`, create folder for module and
add in `modules.txt` of app if missing."""

View File

@ -17,6 +17,7 @@ class ModuleProfile(Document):
block_modules: DF.Table[BlockModule]
module_profile_name: DF.Data
# end: auto-generated types
def onload(self):
from frappe.config import get_modules_from_all_apps

View File

@ -24,4 +24,5 @@ class NavbarItem(Document):
parenttype: DF.Data
route: DF.Data | None
# end: auto-generated types
pass

View File

@ -21,6 +21,7 @@ class NavbarSettings(Document):
logo_width: DF.Int
settings_dropdown: DF.Table[NavbarItem]
# end: auto-generated types
def validate(self):
self.validate_standard_navbar_items()
@ -36,9 +37,7 @@ class NavbarSettings(Document):
if item.is_standard
]
after_save_items = [
item for item in self.help_dropdown + self.settings_dropdown if item.is_standard
]
after_save_items = [item for item in self.help_dropdown + self.settings_dropdown if item.is_standard]
if not frappe.flags.in_patch and (len(before_save_items) > len(after_save_items)):
frappe.throw(_("Please hide the standard navbar items instead of deleting them"))

View File

@ -29,6 +29,7 @@ class Package(Document):
package_name: DF.Data
readme: DF.MarkdownEditor | None
# end: auto-generated types
def validate(self):
if not self.package_name:
self.package_name = self.name.lower().replace(" ", "-")

View File

@ -26,7 +26,11 @@ class TestPackage(FrappeTestCase):
self.assertTrue(
os.path.exists(
frappe.get_site_path(
"packages", "test-package", "test_module_for_package", "doctype", "test_doctype_for_package"
"packages",
"test-package",
"test_module_for_package",
"doctype",
"test_doctype_for_package",
)
)
)
@ -49,9 +53,7 @@ class TestPackage(FrappeTestCase):
def make_test_package():
if not frappe.db.exists("Package", "Test Package"):
frappe.get_doc(
dict(
doctype="Package", name="Test Package", package_name="test-package", readme="# Test Package"
)
dict(doctype="Package", name="Test Package", package_name="test-package", readme="# Test Package")
).insert()

View File

@ -27,6 +27,7 @@ class PackageImport(Document):
force: DF.Check
log: DF.Code | None
# end: auto-generated types
def validate(self):
if self.activate:
self.import_package()

View File

@ -27,6 +27,7 @@ class PackageRelease(Document):
publish: DF.Check
release_notes: DF.MarkdownEditor | None
# end: auto-generated types
def set_version(self):
# set the next patch release by default
doctype = frappe.qb.DocType("Package Release")

View File

@ -33,6 +33,7 @@ class Page(Document):
system_page: DF.Check
title: DF.Data | None
# end: auto-generated types
def autoname(self):
"""
Creates a url friendly name for this page.
@ -121,9 +122,7 @@ class Page(Document):
"""Return True if `Has Role` is not set or the user is allowed."""
from frappe.utils import has_common
allowed = [
d.role for d in frappe.get_all("Has Role", fields=["role"], filters={"parent": self.name})
]
allowed = [d.role for d in frappe.get_all("Has Role", fields=["role"], filters={"parent": self.name})]
custom_roles = get_custom_allowed_roles("page", self.name)
allowed.extend(custom_roles)
@ -170,7 +169,9 @@ class Page(Document):
try:
out = frappe.get_attr(
"{app}.{module}.page.{page}.{page}.get_context".format(
app=frappe.local.module_app[scrub(self.module)], module=scrub(self.module), page=page_name
app=frappe.local.module_app[scrub(self.module)],
module=scrub(self.module),
page=page_name,
)
)(context)

View File

@ -20,6 +20,7 @@ class PatchLog(Document):
skipped: DF.Check
traceback: DF.Code | None
# end: auto-generated types
pass

View File

@ -38,6 +38,7 @@ class PreparedReport(Document):
report_name: DF.Data
status: DF.Literal["Error", "Queued", "Completed", "Started"]
# end: auto-generated types
@property
def queued_by(self):
return self.owner
@ -217,9 +218,7 @@ def delete_prepared_reports(reports):
def create_json_gz_file(data, dt, dn):
# Storing data in CSV file causes information loss
# Reports like P&L Statement were completely unsuable because of this
json_filename = "{}.json.gz".format(
frappe.utils.data.format_datetime(frappe.utils.now(), "Y-m-d-H:M")
)
json_filename = "{}.json.gz".format(frappe.utils.data.format_datetime(frappe.utils.now(), "Y-m-d-H:M"))
encoded_content = frappe.safe_encode(frappe.as_json(data))
compressed_content = gzip.compress(encoded_content)

View File

@ -23,9 +23,10 @@ class RecorderQuery(Document):
parent: DF.Data
parentfield: DF.Data
parenttype: DF.Data
query: DF.Data
query: DF.Data | None
stack: DF.Text | None
# end: auto-generated types
pass
def db_insert(self, *args, **kwargs):

View File

@ -55,7 +55,8 @@ class Report(Document):
if not self.is_standard:
self.is_standard = "No"
if (
frappe.session.user == "Administrator" and getattr(frappe.local.conf, "developer_mode", 0) == 1
frappe.session.user == "Administrator"
and getattr(frappe.local.conf, "developer_mode", 0) == 1
):
self.is_standard = "Yes"
@ -108,9 +109,7 @@ class Report(Document):
"""Return True if `Has Role` is not set or the user is allowed."""
from frappe.utils import has_common
allowed = [
d.role for d in frappe.get_all("Has Role", fields=["role"], filters={"parent": self.name})
]
allowed = [d.role for d in frappe.get_all("Has Role", fields=["role"], filters={"parent": self.name})]
custom_roles = get_custom_allowed_roles("report", self.name)
@ -132,9 +131,7 @@ class Report(Document):
return
if self.is_standard == "Yes" and frappe.conf.developer_mode:
export_to_files(
record_list=[["Report", self.name]], record_module=self.module, create_init=True
)
export_to_files(record_list=[["Report", self.name]], record_module=self.module, create_init=True)
self.create_report_py()
@ -339,7 +336,7 @@ class Report(Document):
def build_standard_report_columns(self, columns, group_by_args):
_columns = []
for (fieldname, doctype) in columns:
for fieldname, doctype in columns:
meta = frappe.get_meta(doctype)
if meta.get_field(fieldname):

View File

@ -156,9 +156,7 @@ class TestReport(FrappeTestCase):
)
result = response.get("result")
columns = response.get("columns")
self.assertListEqual(
["name", "email", "user_type"], [column.get("fieldname") for column in columns]
)
self.assertListEqual(["name", "email", "user_type"], [column.get("fieldname") for column in columns])
admin_dict = frappe.core.utils.find(result, lambda d: d["name"] == "Administrator")
self.assertDictEqual(
{"name": "Administrator", "user_type": "System User", "email": "admin@example.com"}, admin_dict
@ -226,9 +224,7 @@ class TestReport(FrappeTestCase):
def test_format_method(self):
if frappe.db.exists("Report", "User Activity Report Without Sort"):
frappe.delete_doc("Report", "User Activity Report Without Sort")
with open(
os.path.join(os.path.dirname(__file__), "user_activity_report_without_sort.json")
) as f:
with open(os.path.join(os.path.dirname(__file__), "user_activity_report_without_sort.json")) as f:
frappe.get_doc(json.loads(f.read())).insert()
report = frappe.get_doc("Report", "User Activity Report Without Sort")

View File

@ -37,4 +37,5 @@ class ReportColumn(Document):
parenttype: DF.Data
width: DF.Int
# end: auto-generated types
pass

View File

@ -38,4 +38,5 @@ class ReportFilter(Document):
parenttype: DF.Data
wildcard_filter: DF.Check
# end: auto-generated types
pass

View File

@ -43,6 +43,7 @@ class Role(Document):
two_factor_auth: DF.Check
view_switcher: DF.Check
# end: auto-generated types
def before_rename(self, old, new, merge=False):
if old in STANDARD_ROLES:
frappe.throw(frappe._("Standard roles cannot be renamed"))
@ -125,9 +126,7 @@ def get_user_info(users, field="email"):
def get_users(role):
return [
d.parent
for d in frappe.get_all(
"Has Role", filters={"role": role, "parenttype": "User"}, fields=["parent"]
)
for d in frappe.get_all("Has Role", filters={"role": role, "parenttype": "User"}, fields=["parent"])
]

View File

@ -46,7 +46,6 @@ class TestUser(FrappeTestCase):
self.assertTrue(user.user_type == "Website User")
def test_get_users_by_role(self):
role = "System Manager"
sys_managers = get_info_based_on_role(role, field="name")

View File

@ -24,6 +24,7 @@ class RolePermissionforPageandReport(Document):
roles: DF.Table[HasRole]
set_role_for: DF.Literal["", "Page", "Report"]
# end: auto-generated types
@frappe.whitelist()
def set_report_page_data(self):
self.set_custom_roles()

Some files were not shown because too many files have changed in this diff Show More