diff --git a/frappe/app.py b/frappe/app.py index 8f40fcfa82..0d7fdc1fe1 100644 --- a/frappe/app.py +++ b/frappe/app.py @@ -5,6 +5,7 @@ import logging import os from werkzeug.exceptions import HTTPException, NotFound +from werkzeug.local import LocalManager from werkzeug.middleware.profiler import ProfilerMiddleware from werkzeug.middleware.shared_data import SharedDataMiddleware from werkzeug.wrappers import Request, Response @@ -24,10 +25,13 @@ from frappe.utils import get_site_name, sanitize_html from frappe.utils.error import make_error_snapshot from frappe.website.serve import get_response +local_manager = LocalManager(frappe.local) + _site = None _sites_path = os.environ.get("SITES_PATH", ".") +@local_manager.middleware @Request.application def application(request: Request): response = None diff --git a/frappe/core/doctype/file/file.py b/frappe/core/doctype/file/file.py index 1518c72f95..0e28145c9a 100755 --- a/frappe/core/doctype/file/file.py +++ b/frappe/core/doctype/file/file.py @@ -78,21 +78,38 @@ class File(Document): self.validate_duplicate_entry() def validate(self): + if self.is_folder: + return + # Ensure correct formatting and type self.file_url = unquote(self.file_url) if self.file_url else "" + self.validate_attachment_references() + # when dict is passed to get_doc for creation of new_doc, is_new returns None # this case is handled inside handle_is_private_changed if not self.is_new() and self.has_value_changed("is_private"): self.handle_is_private_changed() - if not self.is_folder: - self.validate_file_path() - self.validate_file_url() - self.validate_file_on_disk() + self.validate_file_path() + self.validate_file_url() + self.validate_file_on_disk() self.file_size = frappe.form_dict.file_size or self.file_size + def validate_attachment_references(self): + if not self.attached_to_doctype: + return + + if self.attached_to_name and not isinstance(self.attached_to_name, str): + frappe.throw(_("Attached To Name must be a string"), TypeError) + + if not self.attached_to_field: + return + + if not frappe.get_meta(self.attached_to_doctype).has_field(self.attached_to_field): + frappe.throw(_("The fieldname you've specified in Attached To Field is invalid")) + def after_rename(self, *args, **kwargs): for successor in self.get_successors(): setup_folder_path(successor, self.name) diff --git a/frappe/tests/test_zbg_job_sanity_test.py b/frappe/tests/test_zbg_job_sanity_test.py deleted file mode 100644 index 19dc168c04..0000000000 --- a/frappe/tests/test_zbg_job_sanity_test.py +++ /dev/null @@ -1,27 +0,0 @@ -""" smoak tests to check that all registered background jobs execute without error. - -Note: Filename is intentional to run this test roughly at end. Don't change.""" - -import time - -import frappe -from frappe.core.doctype.rq_job.rq_job import RQJob, remove_failed_jobs -from frappe.tests.utils import FrappeTestCase, timeout - - -class TestScheduledJobSanity(FrappeTestCase): - def setUp(self): - remove_failed_jobs() - - @timeout(90) - def test_bg_jobs_run(self): - """Enqueue all scheduled jobs, wait for finish and verify that none failed.""" - for scheduled_job_type in frappe.get_all("Scheduled Job Type", pluck="name"): - frappe.get_doc("Scheduled Job Type", scheduled_job_type).enqueue(force=True) - - while RQJob.get_list({"filters": [["RQ Job", "status", "in", ("queued", "started")]]}): - time.sleep(0.5) - - # Check no failed, if failed print full details - failed_jobs = RQJob.get_list({"filters": [["RQ Job", "status", "=", "failed"]]}) - self.assertEqual(len(failed_jobs), 0, "Jobs failed: " + str(failed_jobs))