Browse Source

Merge pull request #17906 from frappe/version-14-hotfix

chore: weekly version 14 release
version-14
Ankush Menat 2 years ago
committed by GitHub
parent
commit
c5b0e47ed6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
71 changed files with 201 additions and 146 deletions
  1. +2
    -1
      frappe/__init__.py
  2. +4
    -4
      frappe/automation/doctype/auto_repeat/auto_repeat.py
  3. +1
    -1
      frappe/automation/doctype/auto_repeat/test_auto_repeat.py
  4. +1
    -1
      frappe/boot.py
  5. +1
    -1
      frappe/cache_manager.py
  6. +1
    -1
      frappe/core/doctype/activity_log/test_activity_log.py
  7. +1
    -1
      frappe/core/doctype/data_import/exporter.py
  8. +6
    -6
      frappe/core/doctype/data_import/importer.py
  9. +1
    -1
      frappe/core/doctype/data_import/test_importer.py
  10. +1
    -1
      frappe/core/doctype/doctype/doctype.py
  11. +1
    -1
      frappe/core/doctype/file/test_file.py
  12. +1
    -1
      frappe/core/doctype/language/language.py
  13. +1
    -1
      frappe/core/doctype/package_release/package_release.py
  14. +1
    -1
      frappe/core/doctype/server_script/server_script.py
  15. +1
    -1
      frappe/core/doctype/translation/translation.py
  16. +1
    -1
      frappe/core/doctype/user/user.py
  17. +1
    -1
      frappe/core/doctype/user_permission/user_permission.py
  18. +1
    -1
      frappe/custom/doctype/doctype_layout/patches/convert_web_forms_to_doctype_layout.py
  19. +1
    -1
      frappe/desk/desktop.py
  20. +1
    -1
      frappe/desk/doctype/dashboard_chart/dashboard_chart.py
  21. +4
    -4
      frappe/desk/doctype/desktop_icon/desktop_icon.py
  22. +1
    -1
      frappe/desk/doctype/notification_log/notification_log.py
  23. +1
    -1
      frappe/desk/doctype/notification_log/test_notification_log.py
  24. +1
    -1
      frappe/desk/doctype/tag/tag.py
  25. +9
    -4
      frappe/desk/doctype/workspace/workspace.json
  26. +17
    -3
      frappe/desk/doctype/workspace/workspace.py
  27. +2
    -2
      frappe/desk/form/assign_to.py
  28. +5
    -7
      frappe/desk/form/linked_with.py
  29. +5
    -3
      frappe/desk/form/load.py
  30. +1
    -1
      frappe/desk/form/meta.py
  31. +2
    -2
      frappe/desk/leaderboard.py
  32. +3
    -3
      frappe/desk/page/user_profile/user_profile.py
  33. +1
    -1
      frappe/email/doctype/email_account/email_account.py
  34. +3
    -3
      frappe/email/doctype/email_group/email_group.py
  35. +2
    -2
      frappe/email/doctype/newsletter/test_newsletter.py
  36. +1
    -1
      frappe/geo/country_info.json
  37. +1
    -1
      frappe/integrations/doctype/webhook/test_webhook.py
  38. +2
    -5
      frappe/model/document.py
  39. +2
    -2
      frappe/model/meta.py
  40. +1
    -1
      frappe/model/rename_doc.py
  41. +1
    -1
      frappe/model/utils/__init__.py
  42. +16
    -0
      frappe/modules/export_file.py
  43. +1
    -1
      frappe/patches/v12_0/change_existing_dashboard_chart_filters.py
  44. +1
    -1
      frappe/patches/v12_0/create_notification_settings_for_user.py
  45. +2
    -4
      frappe/patches/v12_0/set_default_incoming_email_port.py
  46. +1
    -1
      frappe/patches/v13_0/generate_theme_files_in_public_folder.py
  47. +1
    -1
      frappe/patches/v13_0/set_existing_dashboard_charts_as_public.py
  48. +1
    -1
      frappe/patches/v14_0/delete_data_migration_tool.py
  49. +1
    -1
      frappe/patches/v14_0/update_color_names_in_kanban_board_column.py
  50. +1
    -1
      frappe/patches/v14_0/update_multistep_webforms.py
  51. +1
    -1
      frappe/patches/v14_0/update_webforms.py
  52. +3
    -3
      frappe/permissions.py
  53. +1
    -1
      frappe/printing/doctype/print_format/print_format.py
  54. +1
    -1
      frappe/printing/doctype/print_format_field_template/print_format_field_template.py
  55. +2
    -2
      frappe/public/js/frappe/recorder/RequestDetail.vue
  56. +2
    -2
      frappe/share.py
  57. +2
    -2
      frappe/tests/test_db_query.py
  58. +1
    -1
      frappe/tests/test_sitemap.py
  59. +5
    -5
      frappe/tests/ui_test_helpers.py
  60. +22
    -2
      frappe/utils/jinja_globals.py
  61. +1
    -1
      frappe/utils/user.py
  62. +1
    -1
      frappe/website/doctype/web_template/web_template.py
  63. +12
    -10
      frappe/website/doctype/website_settings/website_settings.py
  64. +2
    -2
      frappe/website/doctype/website_theme/website_theme.py
  65. +2
    -0
      frappe/website/page_renderers/static_page.py
  66. +8
    -1
      frappe/website/path_resolver.py
  67. +1
    -1
      frappe/website/router.py
  68. +10
    -20
      frappe/website/utils.py
  69. +3
    -1
      frappe/www/app.py
  70. +1
    -1
      frappe/www/unsubscribe.py
  71. +1
    -0
      pyproject.toml

+ 2
- 1
frappe/__init__.py View File

@@ -240,6 +240,7 @@ def init(site: str, sites_path: str = ".", new_site: bool = False) -> None:
local.document_cache = {}
local.meta_cache = {}
local.form_dict = _dict()
local.preload_assets = {"style": [], "script": []}
local.session = _dict()
local.dev_server = _dev_server
local.qb = get_query_builder(local.conf.db_type or "mariadb")
@@ -2329,7 +2330,7 @@ def get_version(doctype, name, limit=None, head=False, raise_err=True):
"""
meta = get_meta(doctype)
if meta.track_changes:
names = db.get_all(
names = get_all(
"Version",
filters={
"ref_doctype": doctype,


+ 4
- 4
frappe/automation/doctype/auto_repeat/auto_repeat.py View File

@@ -241,7 +241,7 @@ class AutoRepeat(Document):
def set_auto_repeat_period(self, new_doc):
mcount = month_map.get(self.frequency)
if mcount and new_doc.meta.get_field("from_date") and new_doc.meta.get_field("to_date"):
last_ref_doc = frappe.db.get_all(
last_ref_doc = frappe.get_all(
doctype=self.reference_doctype,
fields=["name", "from_date", "to_date"],
filters=[
@@ -470,7 +470,7 @@ def create_repeated_entries(data):
def get_auto_repeat_entries(date=None):
if not date:
date = getdate(today())
return frappe.db.get_all(
return frappe.get_all(
"Auto Repeat", filters=[["next_schedule_date", "<=", date], ["status", "=", "Active"]]
)

@@ -504,7 +504,7 @@ def make_auto_repeat(doctype, docname, frequency="Daily", start_date=None, end_d
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_auto_repeat_doctypes(doctype, txt, searchfield, start, page_len, filters):
res = frappe.db.get_all(
res = frappe.get_all(
"Property Setter",
{
"property": "allow_auto_repeat",
@@ -514,7 +514,7 @@ def get_auto_repeat_doctypes(doctype, txt, searchfield, start, page_len, filters
)
docs = [r.doc_type for r in res]

res = frappe.db.get_all(
res = frappe.get_all(
"DocType",
{
"allow_auto_repeat": 1,


+ 1
- 1
frappe/automation/doctype/auto_repeat/test_auto_repeat.py View File

@@ -228,7 +228,7 @@ class TestAutoRepeat(unittest.TestCase):

data = get_auto_repeat_entries(current_date)
create_repeated_entries(data)
docnames = frappe.db.get_all(
docnames = frappe.get_all(
doc.reference_doctype, filters={"auto_repeat": doc.name}, fields=["docstatus"], limit=1
)
self.assertEqual(docnames[0].docstatus, 1)


+ 1
- 1
frappe/boot.py View File

@@ -336,7 +336,7 @@ def get_success_action():
def get_link_preview_doctypes():
from frappe.utils import cint

link_preview_doctypes = [d.name for d in frappe.db.get_all("DocType", {"show_preview_popup": 1})]
link_preview_doctypes = [d.name for d in frappe.get_all("DocType", {"show_preview_popup": 1})]
customizations = frappe.get_all(
"Property Setter", fields=["doc_type", "value"], filters={"property": "show_preview_popup"}
)


+ 1
- 1
frappe/cache_manager.py View File

@@ -134,7 +134,7 @@ def clear_doctype_cache(doctype=None):

# clear all parent doctypes

for dt in frappe.db.get_all(
for dt in frappe.get_all(
"DocField", "parent", dict(fieldtype=["in", frappe.model.table_fields], options=doctype)
):
clear_single(dt.parent)


+ 1
- 1
frappe/core/doctype/activity_log/test_activity_log.py View File

@@ -41,7 +41,7 @@ class TestActivityLog(unittest.TestCase):
frappe.local.form_dict = frappe._dict()

def get_auth_log(self, operation="Login"):
names = frappe.db.get_all(
names = frappe.get_all(
"Activity Log",
filters={
"user": "Administrator",


+ 1
- 1
frappe/core/doctype/data_import/exporter.py View File

@@ -183,7 +183,7 @@ class Exporter:
child_fields = ["name", "idx", "parent", "parentfield"] + list(
{format_column_name(df) for df in self.fields if df.parent == child_table_doctype}
)
data = frappe.db.get_all(
data = frappe.get_all(
child_table_doctype,
filters={
"parent": ("in", parent_names),


+ 6
- 6
frappe/core/doctype/data_import/importer.py View File

@@ -50,7 +50,7 @@ class Importer:
def get_data_for_import_preview(self):
out = self.import_file.get_data_for_import_preview()

out.import_log = frappe.db.get_all(
out.import_log = frappe.get_all(
"Data Import Log",
fields=["row_indexes", "success"],
filters={"data_import": self.data_import.name},
@@ -90,7 +90,7 @@ class Importer:

# setup import log
import_log = (
frappe.db.get_all(
frappe.get_all(
"Data Import Log",
fields=["row_indexes", "success", "log_index"],
filters={"data_import": self.data_import.name},
@@ -204,7 +204,7 @@ class Importer:

# Logs are db inserted directly so will have to be fetched again
import_log = (
frappe.db.get_all(
frappe.get_all(
"Data Import Log",
fields=["row_indexes", "success", "log_index"],
filters={"data_import": self.data_import.name},
@@ -297,7 +297,7 @@ class Importer:
return

import_log = (
frappe.db.get_all(
frappe.get_all(
"Data Import Log",
fields=["row_indexes", "success"],
filters={"data_import": self.data_import.name},
@@ -327,7 +327,7 @@ class Importer:
if not self.data_import:
return

import_log = frappe.db.get_all(
import_log = frappe.get_all(
"Data Import Log",
fields=["row_indexes", "success", "messages", "exception", "docname"],
filters={"data_import": self.data_import.name},
@@ -985,7 +985,7 @@ class Column:
# find all values that dont exist
values = list({cstr(v) for v in self.column_values[1:] if v})
exists = [
cstr(d.name) for d in frappe.db.get_all(self.df.options, filters={"name": ("in", values)})
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:


+ 1
- 1
frappe/core/doctype/data_import/test_importer.py View File

@@ -67,7 +67,7 @@ class TestImporter(unittest.TestCase):
data_import.start_import()
data_import.reload()

import_log = frappe.db.get_all(
import_log = frappe.get_all(
"Data Import Log",
fields=["row_indexes", "success", "messages", "exception", "docname"],
filters={"data_import": data_import.name},


+ 1
- 1
frappe/core/doctype/doctype/doctype.py View File

@@ -325,7 +325,7 @@ class DocType(Document):
"""Change the timestamp of parent DocType if the current one is a child to clear caches."""
if frappe.flags.in_import:
return
parent_list = frappe.db.get_all(
parent_list = frappe.get_all(
"DocField", "parent", dict(fieldtype=["in", frappe.model.table_fields], options=self.name)
)
for p in parent_list:


+ 1
- 1
frappe/core/doctype/file/test_file.py View File

@@ -239,7 +239,7 @@ class TestFile(FrappeTestCase):
pass

def delete_test_data(self):
test_file_data = frappe.db.get_all(
test_file_data = frappe.get_all(
"File",
pluck="name",
filters={"is_home_folder": 0, "is_attachments_folder": 0},


+ 1
- 1
frappe/core/doctype/language/language.py View File

@@ -30,7 +30,7 @@ def validate_with_regex(name, label):

def export_languages_json():
"""Export list of all languages"""
languages = frappe.db.get_all("Language", fields=["name", "language_name"])
languages = frappe.get_all("Language", fields=["name", "language_name"])
languages = [{"name": d.language_name, "code": d.name} for d in languages]

languages.sort(key=lambda a: a["code"])


+ 1
- 1
frappe/core/doctype/package_release/package_release.py View File

@@ -60,7 +60,7 @@ class PackageRelease(Document):
self.make_tarfile(package)

def export_modules(self):
for m in frappe.db.get_all("Module Def", dict(package=self.package)):
for m in frappe.get_all("Module Def", dict(package=self.package)):
module = frappe.get_doc("Module Def", m.name)
for l in module.meta.links:
if l.link_doctype == "Module Def":


+ 1
- 1
frappe/core/doctype/server_script/server_script.py View File

@@ -129,7 +129,7 @@ class ServerScript(Document):

Returns:
list: Returns list of autocompletion items.
For e.g., ["frappe.utils.cint", "frappe.db.get_all", ...]
For e.g., ["frappe.utils.cint", "frappe.get_all", ...]
"""

def get_keys(obj):


+ 1
- 1
frappe/core/doctype/translation/translation.py View File

@@ -39,7 +39,7 @@ def create_translations(translation_map, language):
# first create / update local user translations
for source_id, translation_dict in translation_map.items():
translation_dict = frappe._dict(translation_dict)
existing_doc_name = frappe.db.get_all(
existing_doc_name = frappe.get_all(
"Translation",
{
"source_text": translation_dict.source_text,


+ 1
- 1
frappe/core/doctype/user/user.py View File

@@ -621,7 +621,7 @@ class User(Document):
if login_with_username:
or_filters.append({"username": user_name})

users = frappe.db.get_all("User", fields=["name", "enabled"], or_filters=or_filters, limit=1)
users = frappe.get_all("User", fields=["name", "enabled"], or_filters=or_filters, limit=1)
if not users:
return



+ 1
- 1
frappe/core/doctype/user_permission/user_permission.py View File

@@ -27,7 +27,7 @@ class UserPermission(Document):
def validate_user_permission(self):
"""checks for duplicate user permission records"""

duplicate_exists = frappe.db.get_all(
duplicate_exists = frappe.get_all(
self.doctype,
filters={
"allow": self.allow,


+ 1
- 1
frappe/custom/doctype/doctype_layout/patches/convert_web_forms_to_doctype_layout.py View File

@@ -2,7 +2,7 @@ import frappe


def execute():
for web_form_name in frappe.db.get_all("Web Form", pluck="name"):
for web_form_name in frappe.get_all("Web Form", pluck="name"):
web_form = frappe.get_doc("Web Form", web_form_name)
doctype_layout = frappe.get_doc(
dict(


+ 1
- 1
frappe/desk/desktop.py View File

@@ -172,7 +172,7 @@ class Workspace:

if not exists and frappe.db.exists(name):
if not frappe.db.get_value("DocType", name, "issingle"):
exists = bool(frappe.db.get_all(name, limit=1))
exists = bool(frappe.get_all(name, limit=1))
else:
exists = True
self.table_counts[name] = exists


+ 1
- 1
frappe/desk/doctype/dashboard_chart/dashboard_chart.py View File

@@ -249,7 +249,7 @@ def get_heatmap_chart_config(chart, filters, heatmap_year):
timestamp_field = f"extract(epoch from timestamp {datefield})"

data = dict(
frappe.db.get_all(
frappe.get_all(
doctype,
fields=[
timestamp_field,


+ 4
- 4
frappe/desk/doctype/desktop_icon/desktop_icon.py View File

@@ -61,7 +61,7 @@ def get_desktop_icons(user=None):

blocked_doctypes = [d.get("name") for d in blocked_doctypes]

standard_icons = frappe.db.get_all("Desktop Icon", fields=fields, filters={"standard": 1})
standard_icons = frappe.get_all("Desktop Icon", fields=fields, filters={"standard": 1})

standard_map = {}
for icon in standard_icons:
@@ -69,7 +69,7 @@ def get_desktop_icons(user=None):
icon.blocked = 1
standard_map[icon.module_name] = icon

user_icons = frappe.db.get_all(
user_icons = frappe.get_all(
"Desktop Icon", fields=fields, filters={"standard": 0, "owner": user}
)

@@ -430,7 +430,7 @@ def get_context(context):
context.user = frappe.session.user

if "System Manager" in frappe.get_roles():
context.users = frappe.db.get_all(
context.users = frappe.get_all(
"User",
filters={"user_type": "System User", "enabled": 1},
fields=["name", "first_name", "last_name"],
@@ -443,7 +443,7 @@ def get_module_icons(user=None):
frappe.only_for("System Manager")

if not user:
icons = frappe.db.get_all("Desktop Icon", fields="*", filters={"standard": 1}, order_by="idx")
icons = frappe.get_all("Desktop Icon", fields="*", filters={"standard": 1}, order_by="idx")
else:
frappe.cache().hdel("desktop_icons", user)
icons = get_user_icons(user)


+ 1
- 1
frappe/desk/doctype/notification_log/notification_log.py View File

@@ -151,7 +151,7 @@ def get_notification_logs(limit=20):

@frappe.whitelist()
def mark_all_as_read():
unread_docs_list = frappe.db.get_all(
unread_docs_list = frappe.get_all(
"Notification Log", filters={"read": 0, "for_user": frappe.session.user}
)
unread_docnames = [doc.name for doc in unread_docs_list]


+ 1
- 1
frappe/desk/doctype/notification_log/test_notification_log.py View File

@@ -38,7 +38,7 @@ class TestNotificationLog(unittest.TestCase):


def get_last_email_queue():
res = frappe.db.get_all("Email Queue", fields=["message"], order_by="creation desc", limit=1)
res = frappe.get_all("Email Queue", fields=["message"], order_by="creation desc", limit=1)
return res[0]




+ 1
- 1
frappe/desk/doctype/tag/tag.py View File

@@ -192,4 +192,4 @@ def get_documents_for_tag(tag):

@frappe.whitelist()
def get_tags_list_for_awesomebar():
return [t.name for t in frappe.get_list("Tag")]
return frappe.get_list("Tag", pluck="name", order_by=None)

+ 9
- 4
frappe/desk/doctype/workspace/workspace.json View File

@@ -107,7 +107,8 @@
{
"fieldname": "icon",
"fieldtype": "Icon",
"label": "Icon"
"label": "Icon",
"read_only": 1
},
{
"fieldname": "links",
@@ -122,18 +123,21 @@
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Public",
"read_only": 1,
"search_index": 1
},
{
"fieldname": "title",
"fieldtype": "Data",
"label": "Title",
"read_only": 1,
"reqd": 1
},
{
"fieldname": "parent_page",
"fieldtype": "Data",
"label": "Parent Page"
"label": "Parent Page",
"read_only": 1
},
{
"default": "[]",
@@ -145,7 +149,8 @@
{
"fieldname": "sequence_id",
"fieldtype": "Float",
"label": "Sequence Id"
"label": "Sequence Id",
"read_only": 1
},
{
"fieldname": "roles",
@@ -172,7 +177,7 @@
],
"in_create": 1,
"links": [],
"modified": "2022-05-12 13:00:03.925605",
"modified": "2022-08-16 18:01:42.632238",
"modified_by": "Administrator",
"module": "Desk",
"name": "Workspace",


+ 17
- 3
frappe/desk/doctype/workspace/workspace.py View File

@@ -9,7 +9,7 @@ from frappe.desk.desktop import save_new_widget
from frappe.desk.utils import validate_route_conflict
from frappe.model.document import Document
from frappe.model.rename_doc import rename_doc
from frappe.modules.export_file import export_to_files
from frappe.modules.export_file import delete_folder, export_to_files


class Workspace(Document):
@@ -28,8 +28,22 @@ class Workspace(Document):
if disable_saving_as_public():
return

if frappe.conf.developer_mode and self.module and self.public:
export_to_files(record_list=[["Workspace", self.name]], record_module=self.module)
if frappe.conf.developer_mode and self.public:
if self.module:
export_to_files(record_list=[["Workspace", self.name]], record_module=self.module)

if self.has_value_changed("title") or self.has_value_changed("module"):
previous = self.get_doc_before_save()
if previous and previous.get("module") and previous.get("title"):
delete_folder(previous.get("module"), "Workspace", previous.get("title"))

def before_export(self, doc):
if doc.title != doc.label and doc.label == doc.name:
self.name = doc.name = doc.label = doc.title

def after_delete(self):
if self.module:
delete_folder(self.module, "Workspace", self.title)

@staticmethod
def get_module_page_map():


+ 2
- 2
frappe/desk/form/assign_to.py View File

@@ -138,7 +138,7 @@ def add_multiple(args=None):


def close_all_assignments(doctype, name):
assignments = frappe.db.get_all(
assignments = frappe.get_all(
"ToDo",
fields=["allocated_to"],
filters=dict(reference_type=doctype, reference_name=name, status=("!=", "Cancelled")),
@@ -189,7 +189,7 @@ def clear(doctype, name):
"""
Clears assignments, return False if not assigned.
"""
assignments = frappe.db.get_all(
assignments = frappe.get_all(
"ToDo", fields=["allocated_to"], filters=dict(reference_type=doctype, reference_name=name)
)
if not assignments:


+ 5
- 7
frappe/desk/form/linked_with.py View File

@@ -136,7 +136,7 @@ class SubmittableDocumentTree:
def get_submittable_doctypes(self) -> list[str]:
"""Returns list of submittable doctypes."""
if not self._submittable_doctypes:
self._submittable_doctypes = frappe.db.get_all("DocType", {"is_submittable": 1}, pluck="name")
self._submittable_doctypes = frappe.get_all("DocType", {"is_submittable": 1}, pluck="name")
return self._submittable_doctypes


@@ -288,9 +288,7 @@ def get_references_across_doctypes_by_dynamic_link_field(
for doctype, fieldname, doctype_fieldname in links:
try:
filters = [[doctype_fieldname, "in", to_doctypes]] if to_doctypes else []
for linked_to in frappe.db.get_all(
doctype, pluck=doctype_fieldname, filters=filters, distinct=1
):
for linked_to in frappe.get_all(doctype, pluck=doctype_fieldname, filters=filters, distinct=1):
if linked_to:
links_by_doctype[linked_to].append(
{"doctype": doctype, "fieldname": fieldname, "doctype_fieldname": doctype_fieldname}
@@ -330,17 +328,17 @@ def get_referencing_documents(

if not link_info.get("is_child"):
filters.extend(parent_filters or [])
return {from_table: frappe.db.get_all(from_table, filters, pluck="name")}
return {from_table: frappe.get_all(from_table, filters, pluck="name")}

filters.extend(child_filters or [])
res = frappe.db.get_all(from_table, filters=filters, fields=["name", "parenttype", "parent"])
res = frappe.get_all(from_table, filters=filters, fields=["name", "parenttype", "parent"])
documents = defaultdict(list)

for parent, rows in itertools.groupby(res, key=lambda row: row["parenttype"]):
if allowed_parents and parent not in allowed_parents:
continue
filters = (parent_filters or []) + [["name", "in", tuple(row.parent for row in rows)]]
documents[parent].extend(frappe.db.get_all(parent, filters=filters, pluck="name") or [])
documents[parent].extend(frappe.get_all(parent, filters=filters, pluck="name") or [])
return documents




+ 5
- 3
frappe/desk/form/load.py View File

@@ -178,7 +178,7 @@ def add_comments(doc, docinfo):


def get_milestones(doctype, name):
return frappe.db.get_all(
return frappe.get_all(
"Milestone",
fields=["creation", "owner", "track_field", "value"],
filters=dict(reference_type=doctype, reference_name=name),
@@ -249,7 +249,7 @@ def get_comments(


def get_point_logs(doctype, docname):
return frappe.db.get_all(
return frappe.get_all(
"Energy Point Log",
filters={"reference_doctype": doctype, "reference_name": docname, "type": ["!=", "Review"]},
fields=["*"],
@@ -452,7 +452,9 @@ def get_title_values_for_link_and_dynamic_link_fields(doc, link_fields=None):
if not meta or not (meta.title_field and meta.show_title_field_in_link):
continue

link_title = frappe.db.get_value(doctype, doc.get(field.fieldname), meta.title_field, cache=True)
link_title = frappe.db.get_value(
doctype, doc.get(field.fieldname), meta.title_field, cache=True, order_by=None
)
link_titles.update({doctype + "::" + doc.get(field.fieldname): link_title})

return link_titles


+ 1
- 1
frappe/desk/form/meta.py View File

@@ -146,7 +146,7 @@ class FormMeta(Meta):
"""embed all require files"""
# custom script
client_scripts = (
frappe.db.get_all(
frappe.get_all(
"Client Script",
filters={"dt": self.name, "enabled": 1},
fields=["name", "script", "view"],


+ 2
- 2
frappe/desk/leaderboard.py View File

@@ -16,7 +16,7 @@ def get_leaderboards():

@frappe.whitelist()
def get_energy_point_leaderboard(date_range, company=None, field=None, limit=None):
all_users = frappe.db.get_all(
all_users = frappe.get_all(
"User",
filters={
"name": ["not in", ["Administrator", "Guest"]],
@@ -31,7 +31,7 @@ def get_energy_point_leaderboard(date_range, company=None, field=None, limit=Non
if date_range:
date_range = frappe.parse_json(date_range)
filters.append(["creation", "between", [date_range[0], date_range[1]]])
energy_point_users = frappe.db.get_all(
energy_point_users = frappe.get_all(
"Energy Point Log",
fields=["user as name", "sum(points) as value"],
filters=filters,


+ 3
- 3
frappe/desk/page/user_profile/user_profile.py View File

@@ -31,7 +31,7 @@ def get_energy_points_heatmap_data(user, date):

@frappe.whitelist()
def get_energy_points_percentage_chart_data(user, field):
result = frappe.db.get_all(
result = frappe.get_all(
"Energy Point Log",
filters={"user": user, "type": ["!=", "Review"]},
group_by=field,
@@ -49,7 +49,7 @@ def get_energy_points_percentage_chart_data(user, field):
@frappe.whitelist()
def get_user_rank(user):
month_start = datetime.today().replace(day=1)
monthly_rank = frappe.db.get_all(
monthly_rank = frappe.get_all(
"Energy Point Log",
group_by="user",
filters={"creation": [">", month_start], "type": ["!=", "Review"]},
@@ -58,7 +58,7 @@ def get_user_rank(user):
as_list=True,
)

all_time_rank = frappe.db.get_all(
all_time_rank = frappe.get_all(
"Energy Point Log",
group_by="user",
filters={"type": ["!=", "Review"]},


+ 1
- 1
frappe/email/doctype/email_account/email_account.py View File

@@ -846,7 +846,7 @@ def get_max_email_uid(email_account):
# get maximum uid of emails
max_uid = 1

result = frappe.db.get_all(
result = frappe.get_all(
"Communication",
filters={
"communication_medium": "Email",


+ 3
- 3
frappe/email/doctype/email_group/email_group.py View File

@@ -9,10 +9,10 @@ from frappe.utils import parse_addr, validate_email_address

class EmailGroup(Document):
def onload(self):
singles = [d.name for d in frappe.db.get_all("DocType", "name", {"issingle": 1})]
singles = [d.name for d in frappe.get_all("DocType", "name", {"issingle": 1})]
self.get("__onload").import_types = [
{"value": d.parent, "label": f"{d.parent} ({d.label})"}
for d in frappe.db.get_all("DocField", ("parent", "label"), {"options": "Email"})
for d in frappe.get_all("DocField", ("parent", "label"), {"options": "Email"})
if d.parent not in singles
]

@@ -27,7 +27,7 @@ class EmailGroup(Document):
unsubscribed_field = "unsubscribed" if meta.get_field("unsubscribed") else None
added = 0

for user in frappe.db.get_all(doctype, [email_field, unsubscribed_field or "name"]):
for user in frappe.get_all(doctype, [email_field, unsubscribed_field or "name"]):
try:
email = parse_addr(user.get(email_field))[1] if user.get(email_field) else None
if email:


+ 2
- 2
frappe/email/doctype/newsletter/test_newsletter.py View File

@@ -107,7 +107,7 @@ class TestNewsletterMixin:
"content_type": "Rich Text",
"message": "Testing my news.",
}
similar_newsletters = frappe.db.get_all(doctype, newsletter_content, pluck="name")
similar_newsletters = frappe.get_all(doctype, newsletter_content, pluck="name")

for similar_newsletter in similar_newsletters:
frappe.delete_doc(doctype, similar_newsletter)
@@ -180,7 +180,7 @@ class TestNewsletter(TestNewsletterMixin, FrappeTestCase):
newsletter.save = MagicMock()
self.assertFalse(newsletter.save.called)
# check if the test email is in the queue
email_queue = frappe.db.get_all(
email_queue = frappe.get_all(
"Email Queue",
filters=[
["reference_doctype", "=", "Newsletter"],


+ 1
- 1
frappe/geo/country_info.json View File

@@ -2723,7 +2723,7 @@
"currency_fraction": "Kuru\u015f",
"currency_fraction_units": 100,
"currency_symbol": "\u20ba",
"number_format": "#,###.##",
"number_format": "#.###,##",
"timezones": [
"Europe/Istanbul"
],


+ 1
- 1
frappe/integrations/doctype/webhook/test_webhook.py View File

@@ -176,7 +176,7 @@ class TestWebhook(unittest.TestCase):
webhook = frappe.get_doc("Webhook", {"webhook_doctype": "User"})
enqueue_webhook(user, webhook)

self.assertTrue(frappe.db.get_all("Webhook Request Log", pluck="name"))
self.assertTrue(frappe.get_all("Webhook Request Log", pluck="name"))

def test_webhook_with_array_body(self):
"""Check if array request body are supported."""


+ 2
- 5
frappe/model/document.py View File

@@ -15,6 +15,7 @@ from frappe.model import optional_fields, table_fields
from frappe.model.base_document import BaseDocument, get_controller
from frappe.model.docstatus import DocStatus
from frappe.model.naming import set_new_name, validate_name
from frappe.model.utils import is_virtual_doctype
from frappe.model.workflow import set_workflow_state_on_action, validate_workflow
from frappe.utils import cstr, date_diff, file_lock, flt, get_datetime_str, now
from frappe.utils.data import get_absolute_url
@@ -154,11 +155,7 @@ class Document(BaseDocument):
# Make sure not to query the DB for a child table, if it is a virtual one.
# During frappe is installed, the property "is_virtual" is not available in tabDocType, so
# we need to filter those cases for the access to frappe.db.get_value() as it would crash otherwise.
if (
hasattr(self, "doctype")
and not hasattr(self, "module")
and frappe.db.get_value("DocType", df.options, "is_virtual", cache=True)
):
if hasattr(self, "doctype") and not hasattr(self, "module") and is_virtual_doctype(df.options):
self.set(df.fieldname, [])
continue



+ 2
- 2
frappe/model/meta.py View File

@@ -666,7 +666,7 @@ def is_single(doctype):


def get_parent_dt(dt):
parent_dt = frappe.db.get_all(
parent_dt = frappe.get_all(
"DocField", "parent", dict(fieldtype=["in", frappe.model.table_fields], options=dt), limit=1
)
return parent_dt and parent_dt[0].parent or ""
@@ -764,7 +764,7 @@ def trim_tables(doctype=None, dry_run=False, quiet=False):
if doctype:
filters["name"] = doctype

for doctype in frappe.db.get_all("DocType", filters=filters, pluck="name"):
for doctype in frappe.get_all("DocType", filters=filters, pluck="name"):
try:
dropped_columns = trim_table(doctype, dry_run=dry_run)
if dropped_columns:


+ 1
- 1
frappe/model/rename_doc.py View File

@@ -237,7 +237,7 @@ def update_assignments(old: str, new: str, doctype: str) -> None:

for user in common_assignments:
# delete todos linked to old doc
todos = frappe.db.get_all(
todos = frappe.get_all(
"ToDo",
{
"owner": user,


+ 1
- 1
frappe/model/utils/__init__.py View File

@@ -128,6 +128,6 @@ def get_fetch_values(doctype, fieldname, value):
return result


@site_cache(maxsize=128)
@site_cache()
def is_virtual_doctype(doctype):
return frappe.db.get_value("DocType", doctype, "is_virtual")

+ 16
- 0
frappe/modules/export_file.py View File

@@ -2,6 +2,7 @@
# License: MIT. See LICENSE

import os
import shutil

import frappe
import frappe.model
@@ -90,6 +91,21 @@ def get_module_name(doc):
return module


def delete_folder(module, dt, dn):
if frappe.db.get_value("Module Def", module, "custom"):
module_path = get_custom_module_path(module)
else:
module_path = get_module_path(module)

dt, dn = scrub_dt_dn(dt, dn)

# delete folder
folder = os.path.join(module_path, dt, dn)

if os.path.exists(folder):
shutil.rmtree(folder)


def create_folder(module, dt, dn, create_init):
if frappe.db.get_value("Module Def", module, "custom"):
module_path = get_custom_module_path(module)


+ 1
- 1
frappe/patches/v12_0/change_existing_dashboard_chart_filters.py View File

@@ -7,7 +7,7 @@ def execute():
if not frappe.db.table_exists("Dashboard Chart"):
return

charts_to_modify = frappe.db.get_all(
charts_to_modify = frappe.get_all(
"Dashboard Chart",
fields=["name", "filters_json", "document_type"],
filters={"chart_type": ["not in", ["Report", "Custom"]]},


+ 1
- 1
frappe/patches/v12_0/create_notification_settings_for_user.py View File

@@ -8,6 +8,6 @@ def execute():
frappe.reload_doc("desk", "doctype", "notification_settings")
frappe.reload_doc("desk", "doctype", "notification_subscribed_document")

users = frappe.db.get_all("User", fields=["name"])
users = frappe.get_all("User", fields=["name"])
for user in users:
create_notification_settings(user.name)

+ 2
- 4
frappe/patches/v12_0/set_default_incoming_email_port.py View File

@@ -15,9 +15,7 @@ def execute():


def setup_incoming_email_port_in_email_domains():
email_domains = frappe.db.get_all(
"Email Domain", ["incoming_port", "use_imap", "use_ssl", "name"]
)
email_domains = frappe.get_all("Email Domain", ["incoming_port", "use_imap", "use_ssl", "name"])
for domain in email_domains:
if not domain.incoming_port:
incoming_port = get_port(domain)
@@ -33,7 +31,7 @@ def setup_incoming_email_port_in_email_domains():


def setup_incoming_email_port_in_email_accounts():
email_accounts = frappe.db.get_all(
email_accounts = frappe.get_all(
"Email Account", ["incoming_port", "use_imap", "use_ssl", "name", "enable_incoming"]
)



+ 1
- 1
frappe/patches/v13_0/generate_theme_files_in_public_folder.py View File

@@ -6,7 +6,7 @@ import frappe

def execute():
frappe.reload_doc("website", "doctype", "website_theme_ignore_app")
themes = frappe.db.get_all(
themes = frappe.get_all(
"Website Theme", filters={"theme_url": ("not like", "/files/website_theme/%")}
)
for theme in themes:


+ 1
- 1
frappe/patches/v13_0/set_existing_dashboard_charts_as_public.py View File

@@ -15,7 +15,7 @@ def execute():
)

users = [item.parent for item in users_with_permission]
charts = frappe.db.get_all("Dashboard Chart", filters={"owner": ["in", users]})
charts = frappe.get_all("Dashboard Chart", filters={"owner": ["in", users]})

for chart in charts:
frappe.db.set_value("Dashboard Chart", chart.name, "is_public", 1)

+ 1
- 1
frappe/patches/v14_0/delete_data_migration_tool.py View File

@@ -5,7 +5,7 @@ import frappe


def execute():
doctypes = frappe.db.get_all("DocType", {"module": "Data Migration", "custom": 0}, pluck="name")
doctypes = frappe.get_all("DocType", {"module": "Data Migration", "custom": 0}, pluck="name")
for doctype in doctypes:
frappe.delete_doc("DocType", doctype, ignore_missing=True)



+ 1
- 1
frappe/patches/v14_0/update_color_names_in_kanban_board_column.py View File

@@ -17,6 +17,6 @@ def execute():
"yellow": "Yellow",
"lightblue": "Light Blue",
}
for d in frappe.db.get_all("Kanban Board Column", fields=["name", "indicator"]):
for d in frappe.get_all("Kanban Board Column", fields=["name", "indicator"]):
color_name = indicator_map.get(d.indicator, "Gray")
frappe.db.set_value("Kanban Board Column", d.name, "indicator", color_name)

+ 1
- 1
frappe/patches/v14_0/update_multistep_webforms.py View File

@@ -4,7 +4,7 @@ import frappe
def execute():
frappe.reload_doctype("Web Form")

for web_form in frappe.db.get_all("Web Form", filters={"is_multi_step_form": 1}):
for web_form in frappe.get_all("Web Form", filters={"is_multi_step_form": 1}):
web_form_fields = frappe.get_doc("Web Form", web_form.name).web_form_fields
for web_form_field in web_form_fields:
if web_form_field.fieldtype == "Section Break" and web_form_field.idx != 1:


+ 1
- 1
frappe/patches/v14_0/update_webforms.py View File

@@ -9,6 +9,6 @@ def execute():
frappe.reload_doc("website", "doctype", "web_form_list_column")
frappe.reload_doctype("Web Form")

for web_form in frappe.db.get_all("Web Form", fields=["*"]):
for web_form in frappe.get_all("Web Form", fields=["*"]):
if web_form.allow_multiple and not web_form.show_list:
frappe.db.set_value("Web Form", web_form.name, "show_list", True)

+ 3
- 3
frappe/permissions.py View File

@@ -451,13 +451,13 @@ def get_doctype_roles(doctype, access_type="read"):
def get_perms_for(roles, perm_doctype="DocPerm"):
"""Get perms for given roles"""
filters = {"permlevel": 0, "docstatus": 0, "role": ["in", roles]}
return frappe.db.get_all(perm_doctype, fields=["*"], filters=filters)
return frappe.get_all(perm_doctype, fields=["*"], filters=filters)


def get_doctypes_with_custom_docperms():
"""Returns all the doctypes with Custom Docperms"""

doctypes = frappe.db.get_all("Custom DocPerm", fields=["parent"], distinct=1)
doctypes = frappe.get_all("Custom DocPerm", fields=["parent"], distinct=1)
return [d.parent for d in doctypes]


@@ -525,7 +525,7 @@ def clear_user_permissions_for_doctype(doctype, user=None):
filters = {"allow": doctype}
if user:
filters["user"] = user
user_permissions_for_doctype = frappe.db.get_all("User Permission", filters=filters)
user_permissions_for_doctype = frappe.get_all("User Permission", filters=filters)
for d in user_permissions_for_doctype:
frappe.delete_doc("User Permission", d.name)



+ 1
- 1
frappe/printing/doctype/print_format/print_format.py View File

@@ -13,7 +13,7 @@ from frappe.utils.weasyprint import download_pdf, get_html

class PrintFormat(Document):
def onload(self):
templates = frappe.db.get_all(
templates = frappe.get_all(
"Print Format Field Template",
fields=["template", "field", "name"],
filters={"document_type": self.doc_type},


+ 1
- 1
frappe/printing/doctype/print_format_field_template/print_format_field_template.py View File

@@ -27,7 +27,7 @@ class PrintFormatFieldTemplate(Document):
filters = {"document_type": self.document_type, "field": self.field}
if not self.is_new():
filters.update({"name": ("!=", self.name)})
result = frappe.db.get_all("Print Format Field Template", filters=filters, limit=1)
result = frappe.get_all("Print Format Field Template", filters=filters, limit=1)
if result:
frappe.throw(
_("A template already exists for field {0} of {1}").format(


+ 2
- 2
frappe/public/js/frappe/recorder/RequestDetail.vue View File

@@ -25,8 +25,8 @@
<li v-for="(column, index) in table_columns.filter(c => c.sortable)" :key="index" @click="query.sort = column.slug"><a class="option">{{ column.label }}</a></li>
</ul>
</div>
<button class="btn btn-default btn-xs btn-order">
<span class="octicon text-muted" :class="query.order == 'asc' ? 'octicon-arrow-down' : 'octicon-arrow-up'" @click="query.order = (query.order == 'asc') ? 'desc' : 'asc'"></span>
<button class="btn btn-default btn-xs btn-order" @click="query.order = (query.order == 'asc') ? 'desc' : 'asc'">
<span class="octicon text-muted" :class="query.order == 'asc' ? 'octicon-arrow-down' : 'octicon-arrow-up'"></span>
</button>
</div>
</div>


+ 2
- 2
frappe/share.py View File

@@ -101,7 +101,7 @@ def set_permission(doctype, name, user, permission_to, value=1, everyone=0):
@frappe.whitelist()
def get_users(doctype, name):
"""Get list of users with which this document is shared"""
return frappe.db.get_all(
return frappe.get_all(
"DocShare",
fields=[
"`name`",
@@ -137,7 +137,7 @@ def get_shared(doctype, user=None, rights=None):
if user != "Guest":
or_filters += [["everyone", "=", 1]]

shared_docs = frappe.db.get_all(
shared_docs = frappe.get_all(
"DocShare", fields=["share_name"], filters=filters, or_filters=or_filters
)



+ 2
- 2
frappe/tests/test_db_query.py View File

@@ -42,7 +42,7 @@ class TestReportview(unittest.TestCase):
content="test",
seen_by=[{"user": "Administrator"}],
).insert()
result = frappe.db.get_all(
result = frappe.get_all(
"Note",
filters={"name": note.name},
fields=["name", "seen_by.user as seen_by"],
@@ -55,7 +55,7 @@ class TestReportview(unittest.TestCase):
todo = frappe.get_doc(
doctype="ToDo", description="Test ToDo", allocated_to="Administrator"
).insert()
result = frappe.db.get_all(
result = frappe.get_all(
"ToDo",
filters={"name": todo.name},
fields=["name", "allocated_to.email as allocated_user_email"],


+ 1
- 1
frappe/tests/test_sitemap.py View File

@@ -9,7 +9,7 @@ class TestSitemap(unittest.TestCase):
from frappe.test_runner import make_test_records

make_test_records("Blog Post")
blogs = frappe.db.get_all("Blog Post", {"published": 1}, ["route"], limit=1)
blogs = frappe.get_all("Blog Post", {"published": 1}, ["route"], limit=1)
xml = get_html_for_route("sitemap.xml")
self.assertTrue("/about</loc>" in xml)
self.assertTrue("/contact</loc>" in xml)


+ 5
- 5
frappe/tests/ui_test_helpers.py View File

@@ -38,7 +38,7 @@ def create_if_not_exists(doc):

@frappe.whitelist()
def create_todo_records():
if frappe.db.get_all("ToDo", {"description": "this is first todo"}):
if frappe.get_all("ToDo", {"description": "this is first todo"}):
return

frappe.get_doc(
@@ -80,7 +80,7 @@ def setup_workflow():

@frappe.whitelist()
def create_contact_phone_nos_records():
if frappe.db.get_all("Contact", {"first_name": "Test Contact"}):
if frappe.get_all("Contact", {"first_name": "Test Contact"}):
return

doc = frappe.new_doc("Contact")
@@ -127,7 +127,7 @@ def create_child_doctype(name, fields):

@frappe.whitelist()
def create_contact_records():
if frappe.db.get_all("Contact", {"first_name": "Test Form Contact 1"}):
if frappe.get_all("Contact", {"first_name": "Test Form Contact 1"}):
return

insert_contact("Test Form Contact 1", "12345")
@@ -137,7 +137,7 @@ def create_contact_records():

@frappe.whitelist()
def create_multiple_todo_records():
if frappe.db.get_all("ToDo", {"description": "Multiple ToDo 1"}):
if frappe.get_all("ToDo", {"description": "Multiple ToDo 1"}):
return

values = [(f"100{i}", f"Multiple ToDo {i}") for i in range(1, 1002)]
@@ -291,7 +291,7 @@ def update_child_table(name):

@frappe.whitelist()
def insert_doctype_with_child_table_record(name):
if frappe.db.get_all(name, {"title": "Test Grid Search"}):
if frappe.get_all(name, {"title": "Test Grid Search"}):
return

def insert_child(doc, data, barcode, check, rating, duration, date):


+ 22
- 2
frappe/utils/jinja_globals.py View File

@@ -95,13 +95,33 @@ def get_dom_id(seed=None):
return "id-" + generate_hash(seed, 12)


def include_script(path):
def include_script(path, preload=True):
"""Get path of bundled script files.

If preload is specified the path will be added to preload headers so browsers can prefetch
assets."""
path = bundled_asset(path)

if preload:
import frappe

frappe.local.preload_assets["script"].append(path)

return f'<script type="text/javascript" src="{path}"></script>'


def include_style(path, rtl=None):
def include_style(path, rtl=None, preload=True):
"""Get path of bundled style files.

If preload is specified the path will be added to preload headers so browsers can prefetch
assets."""
path = bundled_asset(path)

if preload:
import frappe

frappe.local.preload_assets["style"].append(path)

return f'<link type="text/css" rel="stylesheet" href="{path}">'




+ 1
- 1
frappe/utils/user.py View File

@@ -273,7 +273,7 @@ def get_user_fullname(user: str) -> str:

def get_fullname_and_avatar(user: str) -> _dict:
first_name, last_name, avatar, name = frappe.db.get_value(
"User", user, ["first_name", "last_name", "user_image", "name"]
"User", user, ["first_name", "last_name", "user_image", "name"], order_by=None
)
return _dict(
{


+ 1
- 1
frappe/website/doctype/web_template/web_template.py View File

@@ -33,7 +33,7 @@ class WebTemplate(Document):

def on_update(self):
"""Clear cache for all Web Pages in which this template is used"""
routes = frappe.db.get_all(
routes = frappe.get_all(
"Web Page",
filters=[
["Web Page Block", "web_template", "=", self.name],


+ 12
- 10
frappe/website/doctype/website_settings/website_settings.py View File

@@ -103,12 +103,12 @@ class WebsiteSettings(Document):
def get_website_settings(context=None):
hooks = frappe.get_hooks()
context = frappe._dict(context or {})
settings: "WebsiteSettings" = frappe.get_single("Website Settings")
settings: "WebsiteSettings" = frappe.get_cached_doc("Website Settings")

context = context.update(
{
"top_bar_items": get_items("top_bar_items"),
"footer_items": get_items("footer_items"),
"top_bar_items": modify_header_footer_items(settings.top_bar_items),
"footer_items": modify_header_footer_items(settings.footer_items),
"post_login": [
{"label": _("My Account"), "url": "/me"},
{"label": _("Log out"), "url": "/?cmd=web_logout"},
@@ -203,22 +203,24 @@ def get_items(parentfield: str) -> list[dict]:
order_by="idx asc",
fields="*",
)
top_items = _items.copy()
return modify_header_footer_items(_items)


def modify_header_footer_items(items: list):
top_items = items.copy()
# attach child items to top bar
for item in _items:
if not item["parent_label"]:
for item in items:
if not item.parent_label:
continue

for top_bar_item in top_items:
if top_bar_item["label"] != item["parent_label"]:
if top_bar_item.label != item.parent_label:
continue

if "child_items" not in top_bar_item:
if not top_bar_item.get("child_items"):
top_bar_item["child_items"] = []

top_bar_item["child_items"].append(item)

top_bar_item.child_items.append(item)
break

return top_items


+ 2
- 2
frappe/website/doctype/website_theme/website_theme.py View File

@@ -133,9 +133,9 @@ class WebsiteTheme(Document):


def get_active_theme() -> Optional["WebsiteTheme"]:
if website_theme := frappe.db.get_single_value("Website Settings", "website_theme"):
if website_theme := frappe.get_website_settings("website_theme"):
try:
return frappe.get_doc("Website Theme", website_theme)
return frappe.get_cached_doc("Website Theme", website_theme)
except frappe.DoesNotExistError:
pass



+ 2
- 0
frappe/website/page_renderers/static_page.py View File

@@ -12,6 +12,8 @@ UNSUPPORTED_STATIC_PAGE_TYPES = ("html", "md", "js", "xml", "css", "txt", "py",


class StaticPage(BaseRenderer):
__slots__ = ("path", "file_path")

def __init__(self, path, http_status_code=None):
super().__init__(path=path, http_status_code=http_status_code)
self.set_file_path()


+ 8
- 1
frappe/website/path_resolver.py View File

@@ -17,6 +17,8 @@ from frappe.website.utils import can_cache, get_home_page


class PathResolver:
__slots__ = ("path",)

def __init__(self, path):
self.path = path.strip("/ ")

@@ -36,6 +38,11 @@ class PathResolver:
return frappe.flags.redirect_location, RedirectPage(self.path)

endpoint = resolve_path(self.path)

# WARN: Hardcoded for better performance
if endpoint == "app":
return endpoint, TemplatePage(endpoint, 200)

custom_renderers = self.get_custom_page_renderers()
renderers = custom_renderers + [
StaticPage,
@@ -98,7 +105,7 @@ def resolve_redirect(path, query_string=None):
]
"""
redirects = frappe.get_hooks("website_redirects")
redirects += frappe.db.get_all("Website Route Redirect", ["source", "target"])
redirects += frappe.get_all("Website Route Redirect", ["source", "target"], order_by=None)

if not redirects:
return


+ 1
- 1
frappe/website/router.py View File

@@ -33,7 +33,7 @@ def get_page_info_from_web_page_with_dynamic_routes(path):
def get_page_info_from_web_form(path):
"""Query published web forms and evaluate if the route matches"""
rules, page_info = [], {}
web_forms = frappe.db.get_all("Web Form", ["name", "route", "modified"], {"published": 1})
web_forms = frappe.get_all("Web Form", ["name", "route", "modified"], {"published": 1})
for d in web_forms:
rules.append(Rule(f"/{d.route}", endpoint=d.name))
rules.append(Rule(f"/{d.route}/list", endpoint=d.name))


+ 10
- 20
frappe/website/utils.py View File

@@ -527,7 +527,8 @@ def build_response(path, data, http_status_code, headers: dict | None = None):
response.headers["X-Page-Name"] = path.encode("ascii", errors="xmlcharrefreplace")
response.headers["X-From-Cache"] = frappe.local.response.from_cache or False

add_preload_headers(response)
add_preload_for_bundled_assets(response)

if headers:
for key, val in headers.items():
response.headers[key] = val.encode("ascii", errors="xmlcharrefreplace")
@@ -557,29 +558,18 @@ def set_content_type(response, data, path):
return data


def add_preload_headers(response):
from bs4 import BeautifulSoup, SoupStrainer

try:
preload = []
strainer = SoupStrainer(re.compile("script|link"))
soup = BeautifulSoup(response.data, "html.parser", parse_only=strainer)
for elem in soup.find_all("script", src=re.compile(".*")):
preload.append(("script", elem.get("src")))
def add_preload_for_bundled_assets(response):

for elem in soup.find_all("link", rel="stylesheet"):
preload.append(("style", elem.get("href")))
links = []

links = []
for _type, link in preload:
links.append(f"<{link}>; rel=preload; as={_type}")
for css in frappe.local.preload_assets["style"]:
links.append(f"<{css}>; rel=preload; as=style")

if links:
response.headers["Link"] = ",".join(links)
except Exception:
import traceback
for js in frappe.local.preload_assets["script"]:
links.append(f"<{js}>; rel=preload; as=script")

traceback.print_exc()
if links:
response.headers["Link"] = ",".join(links)


@lru_cache


+ 3
- 1
frappe/www/app.py View File

@@ -18,7 +18,9 @@ CLOSING_SCRIPT_TAG_PATTERN = re.compile(r"</script\>")
def get_context(context):
if frappe.session.user == "Guest":
frappe.throw(_("Log in to access this page."), frappe.PermissionError)
elif frappe.db.get_value("User", frappe.session.user, "user_type") == "Website User":
elif (
frappe.db.get_value("User", frappe.session.user, "user_type", order_by=None) == "Website User"
):
frappe.throw(_("You are not permitted to access this page."), frappe.PermissionError)

hooks = frappe.get_hooks()


+ 1
- 1
frappe/www/unsubscribe.py View File

@@ -40,7 +40,7 @@ def get_email_groups(user_email):

def get_current_groups(name):
# Return current group by which the mail has been sent.
return frappe.db.get_all(
return frappe.get_all(
"Newsletter Email Group",
fields=["email_group"],
filters={"parent": name, "parenttype": "Newsletter"},


+ 1
- 0
pyproject.toml View File

@@ -58,6 +58,7 @@ dependencies = [
"pytz==2022.1",
"rauth~=0.7.3",
"redis~=3.5.3",
"hiredis~=2.0.0",
"requests-oauthlib~=1.3.0",
"requests~=2.27.1",
"rq~=1.10.1",


Loading…
Cancel
Save