Merge branch 'develop' into flaky-ui-test-3
This commit is contained in:
commit
ff6f4c93c3
11 changed files with 115 additions and 68 deletions
|
|
@ -354,11 +354,11 @@ def cache() -> "RedisWrapper":
|
|||
return redis_server
|
||||
|
||||
|
||||
def get_traceback():
|
||||
def get_traceback(with_context=False):
|
||||
"""Returns error traceback."""
|
||||
from frappe.utils import get_traceback
|
||||
|
||||
return get_traceback()
|
||||
return get_traceback(with_context=with_context)
|
||||
|
||||
|
||||
def errprint(msg):
|
||||
|
|
@ -1210,18 +1210,35 @@ def reload_doc(module, dt=None, dn=None, force=False, reset_permissions=False):
|
|||
|
||||
|
||||
@whitelist()
|
||||
def rename_doc(*args, **kwargs):
|
||||
def rename_doc(
|
||||
doctype: str,
|
||||
old: str,
|
||||
new: str,
|
||||
force: bool = False,
|
||||
merge: bool = False,
|
||||
*,
|
||||
ignore_if_exists: bool = False,
|
||||
show_alert: bool = True,
|
||||
rebuild_search: bool = True,
|
||||
) -> str:
|
||||
"""
|
||||
Renames a doc(dt, old) to doc(dt, new) and updates all linked fields of type "Link"
|
||||
|
||||
Calls `frappe.model.rename_doc.rename_doc`
|
||||
"""
|
||||
kwargs.pop("ignore_permissions", None)
|
||||
kwargs.pop("cmd", None)
|
||||
|
||||
from frappe.model.rename_doc import rename_doc
|
||||
|
||||
return rename_doc(*args, **kwargs)
|
||||
return rename_doc(
|
||||
doctype=doctype,
|
||||
old=old,
|
||||
new=new,
|
||||
force=force,
|
||||
merge=merge,
|
||||
ignore_if_exists=ignore_if_exists,
|
||||
show_alert=show_alert,
|
||||
rebuild_search=rebuild_search,
|
||||
)
|
||||
|
||||
|
||||
def get_module(modulename):
|
||||
|
|
@ -2069,7 +2086,6 @@ def logger(
|
|||
|
||||
def log_error(title=None, message=None, reference_doctype=None, reference_name=None):
|
||||
"""Log error to Error Log"""
|
||||
|
||||
# Parameter ALERT:
|
||||
# the title and message may be swapped
|
||||
# the better API for this is log_error(title, message), and used in many cases this way
|
||||
|
|
@ -2082,20 +2098,15 @@ def log_error(title=None, message=None, reference_doctype=None, reference_name=N
|
|||
else:
|
||||
traceback = message
|
||||
|
||||
if not traceback:
|
||||
traceback = get_traceback()
|
||||
|
||||
if not title:
|
||||
title = "Error"
|
||||
title = title or "Error"
|
||||
traceback = as_unicode(traceback or get_traceback(with_context=True))
|
||||
|
||||
return get_doc(
|
||||
dict(
|
||||
doctype="Error Log",
|
||||
error=as_unicode(traceback),
|
||||
method=title,
|
||||
reference_doctype=reference_doctype,
|
||||
reference_name=reference_name,
|
||||
)
|
||||
doctype="Error Log",
|
||||
error=traceback,
|
||||
method=title,
|
||||
reference_doctype=reference_doctype,
|
||||
reference_name=reference_name,
|
||||
).insert(ignore_permissions=True)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -68,6 +68,8 @@
|
|||
"prepared_report_section",
|
||||
"enable_prepared_report_auto_deletion",
|
||||
"prepared_report_expiry_period",
|
||||
"column_break_64",
|
||||
"max_auto_email_report_per_user",
|
||||
"system_updates_section",
|
||||
"disable_system_update_notification"
|
||||
],
|
||||
|
|
@ -445,7 +447,7 @@
|
|||
"collapsible": 1,
|
||||
"fieldname": "prepared_report_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Prepared Report"
|
||||
"label": "Reports"
|
||||
},
|
||||
{
|
||||
"default": "Frappe",
|
||||
|
|
@ -485,12 +487,22 @@
|
|||
"fieldtype": "Select",
|
||||
"label": "First Day of the Week",
|
||||
"options": "Sunday\nMonday\nTuesday\nWednesday\nThursday\nFriday\nSaturday"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_64",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"default": "20",
|
||||
"fieldname": "max_auto_email_report_per_user",
|
||||
"fieldtype": "Int",
|
||||
"label": "Max auto email report per user"
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-cog",
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2022-01-04 11:28:34.881192",
|
||||
"modified": "2022-04-21 09:11:35.218721",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "System Settings",
|
||||
|
|
|
|||
|
|
@ -1066,7 +1066,7 @@ class Database(object):
|
|||
now_datetime() - relativedelta(minutes=minutes),
|
||||
)[0][0]
|
||||
|
||||
def get_db_table_columns(self, table):
|
||||
def get_db_table_columns(self, table) -> List[str]:
|
||||
"""Returns list of column names from given table."""
|
||||
columns = frappe.cache().hget("table_columns", table)
|
||||
if columns is None:
|
||||
|
|
@ -1146,18 +1146,13 @@ class Database(object):
|
|||
return frappe.db.is_missing_column(e)
|
||||
|
||||
def get_descendants(self, doctype, name):
|
||||
"""Return descendants of the current record"""
|
||||
node_location_indexes = self.get_value(doctype, name, ("lft", "rgt"))
|
||||
if node_location_indexes:
|
||||
lft, rgt = node_location_indexes
|
||||
return self.sql_list(
|
||||
"""select name from `tab{doctype}`
|
||||
where lft > {lft} and rgt < {rgt}""".format(
|
||||
doctype=doctype, lft=lft, rgt=rgt
|
||||
)
|
||||
)
|
||||
else:
|
||||
# when document does not exist
|
||||
"""Return descendants of the group node in tree"""
|
||||
from frappe.utils.nestedset import get_descendants_of
|
||||
|
||||
try:
|
||||
return get_descendants_of(doctype, name, ignore_permissions=True)
|
||||
except Exception:
|
||||
# Can only happen if document doesn't exists - kept for backward compatibility
|
||||
return []
|
||||
|
||||
def is_missing_table_or_column(self, e):
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ from frappe.model.document import Document
|
|||
from frappe.model.naming import append_number_if_name_exists
|
||||
from frappe.utils import (
|
||||
add_to_date,
|
||||
cint,
|
||||
format_time,
|
||||
get_link_to_form,
|
||||
get_url_to_report,
|
||||
|
|
@ -51,14 +52,18 @@ class AutoEmailReport(Document):
|
|||
self.email_to = "\n".join(valid)
|
||||
|
||||
def validate_report_count(self):
|
||||
"""check that there are only 3 enabled reports per user"""
|
||||
count = frappe.db.sql(
|
||||
"select count(*) from `tabAuto Email Report` where user=%s and enabled=1", self.user
|
||||
)[0][0]
|
||||
max_reports_per_user = frappe.local.conf.max_reports_per_user or 3
|
||||
count = frappe.db.count("Auto Email Report", {"user": self.user, "enabled": 1})
|
||||
|
||||
max_reports_per_user = (
|
||||
cint(frappe.local.conf.max_reports_per_user) # kept for backward compatibilty
|
||||
or cint(frappe.db.get_single_value("System Settings", "max_auto_email_report_per_user"))
|
||||
or 20
|
||||
)
|
||||
|
||||
if count > max_reports_per_user + (-1 if self.flags.in_insert else 0):
|
||||
frappe.throw(_("Only {0} emailed reports are allowed per user").format(max_reports_per_user))
|
||||
msg = _("Only {0} emailed reports are allowed per user.").format(max_reports_per_user)
|
||||
msg += " " + _("To allow more reports update limit in System Settings.")
|
||||
frappe.throw(msg, title=_("Report limit reached"))
|
||||
|
||||
def validate_report_format(self):
|
||||
"""check if user has select correct report format"""
|
||||
|
|
|
|||
|
|
@ -226,7 +226,6 @@ scheduler_events = {
|
|||
"frappe.sessions.clear_expired_sessions",
|
||||
"frappe.email.doctype.notification.notification.trigger_daily_alerts",
|
||||
"frappe.utils.scheduler.restrict_scheduler_events_if_dormant",
|
||||
"frappe.email.doctype.auto_email_report.auto_email_report.send_daily",
|
||||
"frappe.website.doctype.personal_data_deletion_request.personal_data_deletion_request.remove_unverified_record",
|
||||
"frappe.desk.form.document_follow.send_daily_updates",
|
||||
"frappe.social.doctype.energy_point_settings.energy_point_settings.allocate_review_points",
|
||||
|
|
@ -241,6 +240,7 @@ scheduler_events = {
|
|||
"frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backups_daily",
|
||||
"frappe.utils.change_log.check_for_update",
|
||||
"frappe.integrations.doctype.s3_backup_settings.s3_backup_settings.take_backups_daily",
|
||||
"frappe.email.doctype.auto_email_report.auto_email_report.send_daily",
|
||||
"frappe.integrations.doctype.google_drive.google_drive.daily_backup",
|
||||
],
|
||||
"weekly_long": [
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
# License: MIT. See LICENSE
|
||||
import datetime
|
||||
import json
|
||||
from typing import Dict, List
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
|
|
@ -252,7 +253,7 @@ class BaseDocument(object):
|
|||
|
||||
def get_valid_dict(
|
||||
self, sanitize=True, convert_dates_to_str=False, ignore_nulls=False, ignore_virtual=False
|
||||
):
|
||||
) -> Dict:
|
||||
d = frappe._dict()
|
||||
for fieldname in self.meta.get_valid_columns():
|
||||
d[fieldname] = self.get(fieldname)
|
||||
|
|
@ -329,7 +330,7 @@ class BaseDocument(object):
|
|||
if key not in self.__dict__:
|
||||
self.__dict__[key] = None
|
||||
|
||||
def get_valid_columns(self):
|
||||
def get_valid_columns(self) -> List[str]:
|
||||
if self.doctype not in frappe.local.valid_columns:
|
||||
if self.doctype in DOCTYPES_FOR_DOCTYPE:
|
||||
from frappe.model.meta import get_table_columns
|
||||
|
|
@ -342,7 +343,7 @@ class BaseDocument(object):
|
|||
|
||||
return frappe.local.valid_columns[self.doctype]
|
||||
|
||||
def is_new(self):
|
||||
def is_new(self) -> bool:
|
||||
return self.get("__islocal")
|
||||
|
||||
@property
|
||||
|
|
@ -359,7 +360,7 @@ class BaseDocument(object):
|
|||
no_default_fields=False,
|
||||
convert_dates_to_str=False,
|
||||
no_child_table_fields=False,
|
||||
):
|
||||
) -> Dict:
|
||||
doc = self.get_valid_dict(convert_dates_to_str=convert_dates_to_str)
|
||||
doc["doctype"] = self.doctype
|
||||
|
||||
|
|
|
|||
|
|
@ -289,19 +289,23 @@ export default class GridRow {
|
|||
var me = this;
|
||||
if(this.doc && !this.grid.df.in_place_edit) {
|
||||
// remove row
|
||||
if(!this.open_form_button) {
|
||||
this.open_form_button = $(`
|
||||
<div class="btn-open-row">
|
||||
<a>${frappe.utils.icon('edit', 'xs')}</a>
|
||||
<div class="hidden-xs edit-grid-row">${ __("Edit") }</div>
|
||||
</div>
|
||||
`)
|
||||
.appendTo($('<div class="col col-xs-1"></div>').appendTo(this.row))
|
||||
.on('click', function() {
|
||||
me.toggle_view(); return false;
|
||||
});
|
||||
if (!this.open_form_button) {
|
||||
this.open_form_button = $('<div class="col col-xs-1"></div>').appendTo(this.row);
|
||||
|
||||
if(this.is_too_small()) {
|
||||
if (!this.configure_columns) {
|
||||
this.open_form_button = $(`
|
||||
<div class="btn-open-row">
|
||||
<a>${frappe.utils.icon('edit', 'xs')}</a>
|
||||
<div class="hidden-xs edit-grid-row">${ __("Edit") }</div>
|
||||
</div>
|
||||
`)
|
||||
.appendTo(this.open_form_button)
|
||||
.on('click', function() {
|
||||
me.toggle_view(); return false;
|
||||
});
|
||||
}
|
||||
|
||||
if (this.is_too_small()) {
|
||||
// narrow
|
||||
this.open_form_button.css({'margin-right': '-2px'});
|
||||
}
|
||||
|
|
@ -310,7 +314,9 @@ export default class GridRow {
|
|||
}
|
||||
|
||||
add_column_configure_button() {
|
||||
if (this.configure_columns) {
|
||||
if (this.grid.df.in_place_edit && !this.frm) return;
|
||||
|
||||
if (this.configure_columns && this.frm) {
|
||||
this.configure_columns_button = $(`
|
||||
<div class="col grid-static-col col-xs-1 d-flex justify-content-center" style="cursor: pointer;">
|
||||
<a>${frappe.utils.icon('setting-gear', 'sm', '', 'filter: opacity(0.5)')}</a>
|
||||
|
|
@ -320,6 +326,10 @@ export default class GridRow {
|
|||
.on('click', () => {
|
||||
this.configure_dialog_for_columns_selector();
|
||||
});
|
||||
} else if (this.configure_columns && !this.frm) {
|
||||
this.configure_columns_button = $(`
|
||||
<div class="col grid-static-col col-xs-1"></div>
|
||||
`).appendTo(this.row);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -343,11 +343,10 @@ textarea.form-control {
|
|||
.duration-picker {
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
|
||||
border-radius: var(--border-radius);
|
||||
box-shadow: var(--shadow-sm);
|
||||
background: var(--popover-bg);
|
||||
|
||||
width: max-content;
|
||||
&:after,
|
||||
&:before {
|
||||
border: solid transparent;
|
||||
|
|
@ -466,4 +465,4 @@ button.data-pill {
|
|||
top: 0;
|
||||
right: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ from typing import Generator, Iterable
|
|||
from urllib.parse import quote, urlparse
|
||||
|
||||
from redis.exceptions import ConnectionError
|
||||
from traceback_with_variables import iter_exc_lines
|
||||
from werkzeug.test import Client
|
||||
|
||||
import frappe
|
||||
|
|
@ -255,7 +256,7 @@ def get_gravatar(email):
|
|||
return gravatar_url
|
||||
|
||||
|
||||
def get_traceback() -> str:
|
||||
def get_traceback(with_context=False) -> str:
|
||||
"""
|
||||
Returns the traceback of the Exception
|
||||
"""
|
||||
|
|
@ -264,14 +265,19 @@ def get_traceback() -> str:
|
|||
if not any([exc_type, exc_value, exc_tb]):
|
||||
return ""
|
||||
|
||||
trace_list = traceback.format_exception(exc_type, exc_value, exc_tb)
|
||||
bench_path = get_bench_path() + "/"
|
||||
if with_context:
|
||||
trace_list = iter_exc_lines()
|
||||
tb = "\n".join(trace_list)
|
||||
else:
|
||||
trace_list = traceback.format_exception(exc_type, exc_value, exc_tb)
|
||||
tb = "".join(cstr(t) for t in trace_list)
|
||||
|
||||
return "".join(cstr(t) for t in trace_list).replace(bench_path, "")
|
||||
bench_path = get_bench_path() + "/"
|
||||
return tb.replace(bench_path, "")
|
||||
|
||||
|
||||
def log(event, details):
|
||||
frappe.logger().info(details)
|
||||
frappe.logger(event).info(details)
|
||||
|
||||
|
||||
def dict_to_str(args, sep="&"):
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ import frappe.utils.data
|
|||
from frappe import _
|
||||
from frappe.frappeclient import FrappeClient
|
||||
from frappe.handler import execute_cmd
|
||||
from frappe.model.delete_doc import delete_doc
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
from frappe.model.rename_doc import rename_doc
|
||||
from frappe.modules import scrub
|
||||
from frappe.utils.background_jobs import enqueue, get_jobs
|
||||
from frappe.website.utils import get_next_link, get_shade, get_toc
|
||||
|
|
@ -110,12 +113,16 @@ def get_safe_globals():
|
|||
errprint=frappe.errprint,
|
||||
qb=frappe.qb,
|
||||
get_meta=frappe.get_meta,
|
||||
new_doc=frappe.new_doc,
|
||||
get_doc=frappe.get_doc,
|
||||
get_mapped_doc=get_mapped_doc,
|
||||
get_last_doc=frappe.get_last_doc,
|
||||
get_cached_doc=frappe.get_cached_doc,
|
||||
get_list=frappe.get_list,
|
||||
get_all=frappe.get_all,
|
||||
get_system_settings=frappe.get_system_settings,
|
||||
rename_doc=frappe.rename_doc,
|
||||
rename_doc=rename_doc,
|
||||
delete_doc=delete_doc,
|
||||
utils=datautils,
|
||||
get_url=frappe.utils.get_url,
|
||||
render_template=frappe.render_template,
|
||||
|
|
|
|||
|
|
@ -63,10 +63,11 @@ semantic-version~=2.8.5
|
|||
sqlparse~=0.4.1
|
||||
stripe~=2.56.0
|
||||
terminaltables~=3.1.0
|
||||
traceback-with-variables~=2.0.4
|
||||
urllib3~=1.26.4
|
||||
Werkzeug~=2.0.3
|
||||
Whoosh~=2.7.4
|
||||
wrapt~=1.12.1
|
||||
wrapt~=1.14.0
|
||||
xlrd~=2.0.1
|
||||
zxcvbn-python~=4.4.24
|
||||
tenacity~=8.0.1
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue