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:
parent
b418dba7ae
commit
de9ac89748
|
@ -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")
|
||||
>>>
|
||||
[
|
||||
{
|
||||
|
|
|
@ -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))})
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
|
|
|
@ -19,4 +19,5 @@ class AssignmentRuleDay(Document):
|
|||
parentfield: DF.Data
|
||||
parenttype: DF.Data
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -19,4 +19,5 @@ class AssignmentRuleUser(Document):
|
|||
parenttype: DF.Data
|
||||
user: DF.Link
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -19,4 +19,5 @@ class AutoRepeatDay(Document):
|
|||
parentfield: DF.Data
|
||||
parenttype: DF.Data
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -20,6 +20,7 @@ class Milestone(Document):
|
|||
track_field: DF.Data
|
||||
value: DF.Data
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)"""
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -20,4 +20,5 @@ class ContactEmail(Document):
|
|||
parentfield: DF.Data
|
||||
parenttype: DF.Data
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -21,4 +21,5 @@ class ContactPhone(Document):
|
|||
parenttype: DF.Data
|
||||
phone: DF.Data
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -15,4 +15,5 @@ class Gender(Document):
|
|||
|
||||
gender: DF.Data | None
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -15,4 +15,5 @@ class Salutation(Document):
|
|||
|
||||
salutation: DF.Data | None
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -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", [])
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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(
|
||||
{
|
||||
|
|
|
@ -20,4 +20,5 @@ class AmendedDocumentNamingSettings(Document):
|
|||
parentfield: DF.Data
|
||||
parenttype: DF.Data
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -18,4 +18,5 @@ class BlockModule(Document):
|
|||
parentfield: DF.Data
|
||||
parenttype: DF.Data
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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}
|
||||
)
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -21,6 +21,7 @@ class CommunicationLink(Document):
|
|||
parentfield: DF.Data
|
||||
parenttype: DF.Data
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -17,4 +17,5 @@ class DataExport(Document):
|
|||
file_type: DF.Literal["Excel", "CSV"]
|
||||
reference_doctype: DF.Link
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -22,4 +22,5 @@ class DataImportLog(Document):
|
|||
row_indexes: DF.Code | None
|
||||
success: DF.Check
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -20,6 +20,7 @@ class DefaultValue(Document):
|
|||
parentfield: DF.Data
|
||||
parenttype: DF.Data
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ class DeletedDocument(Document):
|
|||
new_name: DF.ReadOnly | None
|
||||
restored: DF.Check
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -33,4 +33,5 @@ class DocPerm(Document):
|
|||
submit: DF.Check
|
||||
write: DF.Check
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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"]
|
||||
)
|
||||
|
|
|
@ -24,4 +24,5 @@ class DocTypeAction(Document):
|
|||
parentfield: DF.Data
|
||||
parenttype: DF.Data
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -26,4 +26,5 @@ class DocTypeLink(Document):
|
|||
parenttype: DF.Data
|
||||
table_fieldname: DF.Data | None
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -23,4 +23,5 @@ class DocTypeState(Document):
|
|||
parenttype: DF.Data
|
||||
title: DF.Data
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -21,4 +21,5 @@ class DocumentNamingRuleCondition(Document):
|
|||
parenttype: DF.Data
|
||||
value: DF.Data
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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"])
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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))
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -21,6 +21,7 @@ class DynamicLink(Document):
|
|||
parentfield: DF.Data
|
||||
parenttype: DF.Data
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -18,4 +18,5 @@ class HasDomain(Document):
|
|||
parentfield: DF.Data
|
||||
parenttype: DF.Data
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -21,4 +21,5 @@ class InstalledApplication(Document):
|
|||
parentfield: DF.Data
|
||||
parenttype: DF.Data
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -19,4 +19,5 @@ class LogSettingUser(Document):
|
|||
parenttype: DF.Data
|
||||
user: DF.Link
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -20,4 +20,5 @@ class LogsToClear(Document):
|
|||
parenttype: DF.Data
|
||||
ref_doctype: DF.Link
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -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."""
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -24,4 +24,5 @@ class NavbarItem(Document):
|
|||
parenttype: DF.Data
|
||||
route: DF.Data | None
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -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"))
|
||||
|
|
|
@ -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(" ", "-")
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ class PatchLog(Document):
|
|||
skipped: DF.Check
|
||||
traceback: DF.Code | None
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -37,4 +37,5 @@ class ReportColumn(Document):
|
|||
parenttype: DF.Data
|
||||
width: DF.Int
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -38,4 +38,5 @@ class ReportFilter(Document):
|
|||
parenttype: DF.Data
|
||||
wildcard_filter: DF.Check
|
||||
# end: auto-generated types
|
||||
|
||||
pass
|
||||
|
|
|
@ -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"])
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue
Block a user