diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 52ba55ffb5..8b4535ba69 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -58,3 +58,6 @@ e9bbe03354079cfcef65a77b0c33f57b047a7c93 # ruff update 84ef6ec677c8657c3243ac456a1ef794bfb34a50 + +# replace `frappe.flags.in_test` with `frappe.in_test` +653c80b8483cc41aef25cd7d66b9b6bb188bf5f8 diff --git a/frappe/__init__.py b/frappe/__init__.py index de597894e0..8f5e2c436f 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -83,6 +83,9 @@ cache: Optional["RedisWrapper"] = None client_cache: Optional["ClientCache"] = None STANDARD_USERS = ("Guest", "Administrator") +# this global may be subsequently changed by frappe.tests.utils.toggle_test_mode() +in_test = False + _dev_server = int(sbool(os.environ.get("DEV_SERVER", False))) if _dev_server: @@ -219,7 +222,7 @@ def init(site: str, sites_path: str = ".", new_site: bool = False, force: bool = "in_install_db": False, "in_install_app": False, "in_import": False, - "in_test": False, + "in_test": in_test, "mute_messages": False, "ignore_links": False, "mute_emails": False, @@ -640,7 +643,7 @@ def whitelist(allow_guest=False, xss_safe=False, methods=None): global whitelisted, guest_methods, xss_safe_methods, allowed_http_methods_for_whitelisted_func # validate argument types only if request is present - in_request_or_test = lambda: getattr(local, "request", None) or local.flags.in_test # noqa: E731 + in_request_or_test = lambda: getattr(local, "request", None) or in_test # noqa: E731 # get function from the unbound / bound method # this is needed because functions can be compared, but not methods @@ -740,7 +743,7 @@ def only_for(roles: list[str] | tuple[str] | str, message=False): :param roles: Permitted role(s) """ - if local.flags.in_test or local.session.user == "Administrator": + if in_test or local.session.user == "Administrator": return if isinstance(roles, str): @@ -767,7 +770,7 @@ def get_domain_data(module): else: return _dict() except ImportError: - if local.flags.in_test: + if in_test: return _dict() else: raise @@ -1595,7 +1598,7 @@ def copy_doc(doc: "Document", ignore_no_copy: bool = True) -> "Document": fields_to_clear = ["name", "owner", "creation", "modified", "modified_by"] - if not local.flags.in_test: + if not in_test: fields_to_clear.append("docstatus") if isinstance(doc, BaseDocument) or hasattr(doc, "as_dict"): diff --git a/frappe/automation/doctype/auto_repeat/auto_repeat.py b/frappe/automation/doctype/auto_repeat/auto_repeat.py index 0ed66eac66..aba5ae7013 100644 --- a/frappe/automation/doctype/auto_repeat/auto_repeat.py +++ b/frappe/automation/doctype/auto_repeat/auto_repeat.py @@ -86,7 +86,7 @@ class AutoRepeat(Document): validate_template(self.message or "") def before_insert(self): - if not frappe.flags.in_test: + if not frappe.in_test: start_date = getdate(self.start_date) today_date = getdate(today()) if start_date <= today_date: @@ -112,7 +112,7 @@ class AutoRepeat(Document): frappe.db.set_value(self.reference_doctype, self.reference_document, "auto_repeat", "") def validate_reference_doctype(self): - if frappe.flags.in_test or frappe.flags.in_patch: + if frappe.in_test or frappe.flags.in_patch: return if not frappe.get_meta(self.reference_doctype).allow_auto_repeat: frappe.throw( @@ -229,7 +229,7 @@ class AutoRepeat(Document): self.disable_auto_repeat() - if self.reference_document and not frappe.flags.in_test: + if self.reference_document and not frappe.in_test: self.notify_error_to_user(error_log) def make_new_document(self): diff --git a/frappe/core/doctype/access_log/access_log.py b/frappe/core/doctype/access_log/access_log.py index 7e5dbda3f8..5c939587b4 100644 --- a/frappe/core/doctype/access_log/access_log.py +++ b/frappe/core/doctype/access_log/access_log.py @@ -81,7 +81,7 @@ def make_access_log( # `frappe.db.commit` added because insert doesnt `commit` when called in GET requests like `printview` # dont commit in test mode. It must be tempting to put this block along with the in_request in the # whitelisted method...yeah, don't do it. That part would be executed possibly on a read only DB conn - if not frappe.flags.in_test or in_request: + if not frappe.in_test or in_request: frappe.db.commit() diff --git a/frappe/core/doctype/data_import/data_import.py b/frappe/core/doctype/data_import/data_import.py index a0ee30296d..b0ee905689 100644 --- a/frappe/core/doctype/data_import/data_import.py +++ b/frappe/core/doctype/data_import/data_import.py @@ -101,7 +101,7 @@ class DataImport(Document): def start_import(self): from frappe.utils.scheduler import is_scheduler_inactive - run_now = frappe.flags.in_test or frappe.conf.developer_mode + run_now = frappe.in_test or frappe.conf.developer_mode if is_scheduler_inactive() and not run_now: frappe.throw(_("Scheduler is inactive. Cannot import data."), title=_("Scheduler Inactive")) diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index 77a3864860..1b94db76a9 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -322,7 +322,7 @@ class DocType(Document): def check_developer_mode(self): """Throw exception if not developer mode or via patch""" - if frappe.flags.in_patch or frappe.flags.in_test: + if frappe.flags.in_patch or frappe.in_test: return if not frappe.conf.get("developer_mode") and not self.custom: @@ -594,7 +594,7 @@ class DocType(Document): global_search_fields_after_update.append("name") if set(global_search_fields_before_update) != set(global_search_fields_after_update): - now = (not frappe.request) or frappe.flags.in_test or frappe.flags.in_install + now = (not frappe.request) or frappe.in_test or frappe.flags.in_install frappe.enqueue("frappe.utils.global_search.rebuild_for_doctype", now=now, doctype=self.name) def set_base_class_for_controller(self): diff --git a/frappe/core/doctype/role_profile/role_profile.py b/frappe/core/doctype/role_profile/role_profile.py index 9d790bc84a..bab959c545 100644 --- a/frappe/core/doctype/role_profile/role_profile.py +++ b/frappe/core/doctype/role_profile/role_profile.py @@ -29,7 +29,7 @@ class RoleProfile(Document): self.clear_cache() self.queue_action( "update_all_users", - now=frappe.flags.in_test or frappe.flags.in_install, + now=frappe.in_test or frappe.flags.in_install, enqueue_after_commit=True, queue="long", ) diff --git a/frappe/core/doctype/user/test_user.py b/frappe/core/doctype/user/test_user.py index 3cb5991363..ac66c9feb6 100644 --- a/frappe/core/doctype/user/test_user.py +++ b/frappe/core/doctype/user/test_user.py @@ -25,6 +25,7 @@ from frappe.model.delete_doc import delete_doc from frappe.tests import IntegrationTestCase from frappe.tests.classes.context_managers import change_settings from frappe.tests.test_api import FrappeAPITestCase +from frappe.tests.utils import toggle_test_mode from frappe.utils import get_url user_module = frappe.core.doctype.user.user @@ -212,13 +213,15 @@ class TestUser(IntegrationTestCase): # test password strength while saving user with new password user = frappe.get_doc("User", "test@example.com") - frappe.flags.in_test = False - user.new_password = "password" - self.assertRaises(frappe.exceptions.ValidationError, user.save) - user.reload() - user.new_password = "Eastern_43A1W" - user.save() - frappe.flags.in_test = True + toggle_test_mode(False) + try: + user.new_password = "password" + self.assertRaises(frappe.exceptions.ValidationError, user.save) + user.reload() + user.new_password = "Eastern_43A1W" + user.save() + finally: + toggle_test_mode(True) def test_comment_mentions(self): comment = """ diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index c03dc195b2..f53351b4ff 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -173,7 +173,7 @@ class User(Document): self.__new_password = self.new_password self.new_password = "" - if not frappe.flags.in_test: + if not frappe.in_test: self.password_strength_test() if self.name not in STANDARD_USERS: @@ -269,7 +269,7 @@ class User(Document): self.share_with_self() clear_notifications(user=self.name) frappe.clear_cache(user=self.name) - now = frappe.flags.in_test or frappe.flags.in_install + now = frappe.in_test or frappe.flags.in_install self.send_password_notification(self.__new_password) frappe.enqueue( "frappe.core.doctype.user.user.create_contact", diff --git a/frappe/desk/doctype/notification_log/notification_log.py b/frappe/desk/doctype/notification_log/notification_log.py index dc54833b5a..c192eccede 100644 --- a/frappe/desk/doctype/notification_log/notification_log.py +++ b/frappe/desk/doctype/notification_log/notification_log.py @@ -94,8 +94,8 @@ def enqueue_create_notification(users: list[str] | str, doc: dict): "frappe.desk.doctype.notification_log.notification_log.make_notification_logs", doc=doc, users=users, - now=frappe.flags.in_test, - enqueue_after_commit=not frappe.flags.in_test, + now=frappe.in_test, + enqueue_after_commit=not frappe.in_test, ) @@ -141,7 +141,7 @@ def send_notification_email(doc: NotificationLog): template="new_notification", args=args, header=[header, "orange"], - now=frappe.flags.in_test, + now=frappe.in_test, ) diff --git a/frappe/desk/doctype/system_health_report/system_health_report.py b/frappe/desk/doctype/system_health_report/system_health_report.py index fbf6881528..a9fccc4d48 100644 --- a/frappe/desk/doctype/system_health_report/system_health_report.py +++ b/frappe/desk/doctype/system_health_report/system_health_report.py @@ -57,7 +57,7 @@ def health_check(step: str): try: return func(*args, **kwargs) except Exception as e: - if frappe.flags.in_test: + if frappe.in_test: raise frappe.log(frappe.get_traceback()) # nosemgrep diff --git a/frappe/desk/doctype/workspace/workspace.py b/frappe/desk/doctype/workspace/workspace.py index 3dd399f036..07f4c21d26 100644 --- a/frappe/desk/doctype/workspace/workspace.py +++ b/frappe/desk/doctype/workspace/workspace.py @@ -235,7 +235,7 @@ def disable_saving_as_public(): frappe.flags.in_install or frappe.flags.in_uninstall or frappe.flags.in_patch - or frappe.flags.in_test + or frappe.in_test or frappe.flags.in_fixtures or frappe.flags.in_migrate ) diff --git a/frappe/desk/page/setup_wizard/setup_wizard.py b/frappe/desk/page/setup_wizard/setup_wizard.py index 26c21e107d..97d2ee0f61 100755 --- a/frappe/desk/page/setup_wizard/setup_wizard.py +++ b/frappe/desk/page/setup_wizard/setup_wizard.py @@ -244,7 +244,7 @@ def update_system_settings(args): # nosemgrep "date_format": frappe.db.get_value("Country", args.get("country"), "date_format"), "time_format": frappe.db.get_value("Country", args.get("country"), "time_format"), "number_format": number_format, - "enable_scheduler": 1 if not frappe.flags.in_test else 0, + "enable_scheduler": 1 if not frappe.in_test else 0, "backup_limit": 3, # Default for downloadable backups "enable_telemetry": cint(args.get("enable_telemetry")), } diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index 1a0169ea8b..28100bbb9f 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -159,7 +159,7 @@ class EmailAccount(Document): if self.enable_incoming and self.use_imap and len(self.imap_folder) <= 0: frappe.throw(_("You need to set one IMAP folder for {0}").format(frappe.bold(self.email_id))) - if frappe.local.flags.in_patch or frappe.local.flags.in_test: + if frappe.local.flags.in_patch or frappe.in_test: return use_oauth = self.auth_method == "OAuth" @@ -363,9 +363,7 @@ class EmailAccount(Document): @property def _password(self): - raise_exception = not ( - self.auth_method == "OAuth" or self.no_smtp_authentication or frappe.flags.in_test - ) + raise_exception = not (self.auth_method == "OAuth" or self.no_smtp_authentication or frappe.in_test) return self.get_password(raise_exception=raise_exception) @property @@ -565,7 +563,7 @@ class EmailAccount(Document): self.set_failed_attempts_count(self.get_failed_attempts_count() + 1) def _disable_broken_incoming_account(self, description): - if frappe.flags.in_test: + if frappe.in_test: return self.db_set("enable_incoming", 0) diff --git a/frappe/email/doctype/email_domain/email_domain.py b/frappe/email/doctype/email_domain/email_domain.py index adb0597c3e..32c9696b18 100644 --- a/frappe/email/doctype/email_domain/email_domain.py +++ b/frappe/email/doctype/email_domain/email_domain.py @@ -81,7 +81,7 @@ class EmailDomain(Document): def validate(self): """Validate POP3/IMAP and SMTP connections.""" - if frappe.local.flags.in_patch or frappe.local.flags.in_test or frappe.local.flags.in_install: + if frappe.local.flags.in_patch or frappe.in_test or frappe.local.flags.in_install: return self.validate_incoming_server_conn() diff --git a/frappe/email/doctype/email_queue/email_queue.py b/frappe/email/doctype/email_queue/email_queue.py index 526188f050..68cecd4d0e 100644 --- a/frappe/email/doctype/email_queue/email_queue.py +++ b/frappe/email/doctype/email_queue/email_queue.py @@ -182,7 +182,7 @@ class EmailQueue(Document): message = ctx.build_message(recipient.recipient) if method := get_hook_method("override_email_send"): method(self, self.sender, recipient.recipient, message) - elif not frappe.flags.in_test or frappe.flags.testing_email: + elif not frappe.in_test or frappe.flags.testing_email: if ctx.email_account_doc.service == "Frappe Mail": is_newsletter = self.reference_doctype == "Newsletter" ctx.frappe_mail_client.send_raw( @@ -200,7 +200,7 @@ class EmailQueue(Document): ctx.update_recipient_status_to_sent(recipient) - if frappe.flags.in_test and not frappe.flags.testing_email: + if frappe.in_test and not frappe.flags.testing_email: frappe.flags.sent_mail = message return @@ -773,7 +773,7 @@ class QueueBuilder: job_name=frappe.utils.get_job_name( "send_bulk_emails_for", self.reference_doctype, self.reference_name ), - now=frappe.flags.in_test or send_now, + now=frappe.in_test or send_now, queue="long", ) diff --git a/frappe/email/doctype/newsletter/newsletter.py b/frappe/email/doctype/newsletter/newsletter.py index c38f906c6d..8f4702ff28 100644 --- a/frappe/email/doctype/newsletter/newsletter.py +++ b/frappe/email/doctype/newsletter/newsletter.py @@ -210,7 +210,7 @@ class Newsletter(WebsiteGenerator): args["message"] = self.get_message(medium="email") is_auto_commit_set = bool(frappe.db.auto_commit_on_many_writes) - frappe.db.auto_commit_on_many_writes = not frappe.flags.in_test + frappe.db.auto_commit_on_many_writes = not frappe.in_test frappe.sendmail( subject=self.subject, @@ -421,7 +421,7 @@ def send_scheduled_email(): frappe.db.set_value("Newsletter", newsletter_name, "email_sent", 0) newsletter.log_error("Failed to send newsletter") - if not frappe.flags.in_test: + if not frappe.in_test: frappe.db.commit() frappe.flags.is_scheduler_running = False diff --git a/frappe/email/doctype/notification/notification.py b/frappe/email/doctype/notification/notification.py index 24ddc58c81..00fe5f25ec 100644 --- a/frappe/email/doctype/notification/notification.py +++ b/frappe/email/doctype/notification/notification.py @@ -322,7 +322,7 @@ def get_context(context): "frappe.email.doctype.notification.notification.evaluate_alert", doc=doc, alert=self, - now=frappe.flags.in_test, + now=frappe.in_test, enqueue_after_commit=enqueue_after_commit, ) diff --git a/frappe/email/queue.py b/frappe/email/queue.py index bad7e7abd3..cd6de1ff81 100755 --- a/frappe/email/queue.py +++ b/frappe/email/queue.py @@ -95,7 +95,7 @@ def get_unsubcribed_url(reference_doctype, reference_name, email, unsubscribe_me @frappe.whitelist(allow_guest=True) def unsubscribe(doctype, name, email): # unsubsribe from comments and communications - if not frappe.flags.in_test and not verify_request(): + if not frappe.in_test and not verify_request(): return try: diff --git a/frappe/email/receive.py b/frappe/email/receive.py index febbdc63ee..1ddf69afcb 100644 --- a/frappe/email/receive.py +++ b/frappe/email/receive.py @@ -632,7 +632,7 @@ class InboundMail(Email): def process(self): """Create communication record from email.""" if self.is_sender_same_as_receiver() and not self.is_reply(): - if frappe.flags.in_test: + if frappe.in_test: print("WARN: Cannot pull email. Sender same as recipient inbox") raise SentEmailInInboxError diff --git a/frappe/email/smtp.py b/frappe/email/smtp.py index 2b64c8e528..2f87fc166c 100644 --- a/frappe/email/smtp.py +++ b/frappe/email/smtp.py @@ -109,7 +109,7 @@ class SMTPServer: frappe.request.after_response.add(self.quit) elif frappe.job: frappe.job.after_job.add(self.quit) - elif not frappe.flags.in_test: + elif not frappe.in_test: # Console? import atexit diff --git a/frappe/integrations/doctype/webhook/__init__.py b/frappe/integrations/doctype/webhook/__init__.py index 18d5cfa5e3..2d5f75124e 100644 --- a/frappe/integrations/doctype/webhook/__init__.py +++ b/frappe/integrations/doctype/webhook/__init__.py @@ -115,6 +115,6 @@ def flush_webhook_execution_queue(): "frappe.integrations.doctype.webhook.webhook.enqueue_webhook", doc=instance.doc, webhook=instance.webhook, - now=frappe.flags.in_test, + now=frappe.in_test, queue=instance.webhook.background_jobs_queue or "default", ) diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py index fac66fa4d8..7797b4d9ce 100644 --- a/frappe/model/base_document.py +++ b/frappe/model/base_document.py @@ -977,7 +977,7 @@ class BaseDocument: self.set(df.fieldname, cstr(self.get(df.fieldname)).strip()) value = self.get(df.fieldname) - if value not in options and not (frappe.flags.in_test and value.startswith("_T-")): + if value not in options and not (frappe.in_test and value.startswith("_T-")): # show an elaborate message prefix = _("Row #{0}:").format(self.idx) if self.get("parentfield") else "" label = _(self.meta.get_label(df.fieldname)) diff --git a/frappe/model/delete_doc.py b/frappe/model/delete_doc.py index 4306b3c051..849cc06707 100644 --- a/frappe/model/delete_doc.py +++ b/frappe/model/delete_doc.py @@ -153,7 +153,7 @@ def delete_doc( "frappe.model.delete_doc.delete_dynamic_links", doctype=doc.doctype, name=doc.name, - now=frappe.flags.in_test, + now=frappe.in_test, enqueue_after_commit=True, ) diff --git a/frappe/model/document.py b/frappe/model/document.py index 4ab103fd13..59d9549ad1 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -499,7 +499,7 @@ class Document(BaseDocument): if ignore_permissions is not None: self.flags.ignore_permissions = ignore_permissions - self.flags.ignore_version = frappe.flags.in_test if ignore_version is None else ignore_version + self.flags.ignore_version = frappe.in_test if ignore_version is None else ignore_version if self.get("__islocal") or not self.get("name"): return self.insert() diff --git a/frappe/model/dynamic_links.py b/frappe/model/dynamic_links.py index 9ed56be416..a054406c2d 100644 --- a/frappe/model/dynamic_links.py +++ b/frappe/model/dynamic_links.py @@ -32,7 +32,7 @@ def get_dynamic_link_map(for_delete=False): Note: Will not map single doctypes """ - if getattr(frappe.local, "dynamic_link_map", None) is None or frappe.flags.in_test: + if getattr(frappe.local, "dynamic_link_map", None) is None or frappe.in_test: # Build from scratch dynamic_link_map = {} for df in get_dynamic_links(): diff --git a/frappe/model/trace.py b/frappe/model/trace.py index c9b0cb7cc5..4c66e1f3c4 100644 --- a/frappe/model/trace.py +++ b/frappe/model/trace.py @@ -90,7 +90,7 @@ class TracedValue: """ if value in self.forbidden_values: - if frappe.flags.in_test: + if frappe.in_test: frappe.throw(f"{self.field_name} cannot be set to {value}", AssertionError) else: frappe.throw(f"{self.field_name} cannot be set to {value}") @@ -99,7 +99,7 @@ class TracedValue: try: self.custom_validation(obj, value) except Exception as e: - if frappe.flags.in_test: + if frappe.in_test: frappe.throw(str(e), AssertionError) else: frappe.throw(str(e)) diff --git a/frappe/parallel_test_runner.py b/frappe/parallel_test_runner.py index ed2840bfaa..c558c76fee 100644 --- a/frappe/parallel_test_runner.py +++ b/frappe/parallel_test_runner.py @@ -12,7 +12,7 @@ import click import requests import frappe -from frappe.tests.utils import make_test_records +from frappe.tests.utils import make_test_records, toggle_test_mode from .testing.environment import _decorate_all_methods_and_functions_with_type_checker from .testing.result import TestResult @@ -53,7 +53,7 @@ class ParallelTestRunner: if self.dry_run: return - frappe.flags.in_test = True + toggle_test_mode(True) frappe.clear_cache() frappe.utils.scheduler.disable_scheduler() _decorate_all_methods_and_functions_with_type_checker() diff --git a/frappe/printing/doctype/print_format/print_format.py b/frappe/printing/doctype/print_format/print_format.py index 8f8ea8f5d0..7c96225013 100644 --- a/frappe/printing/doctype/print_format/print_format.py +++ b/frappe/printing/doctype/print_format/print_format.py @@ -70,7 +70,7 @@ class PrintFormat(Document): and not frappe.local.conf.get("developer_mode") and not frappe.flags.in_migrate and not frappe.flags.in_install - and not frappe.flags.in_test + and not frappe.in_test ): frappe.throw(frappe._("Standard Print Format cannot be updated")) diff --git a/frappe/printing/doctype/print_style/print_style.py b/frappe/printing/doctype/print_style/print_style.py index 1c1d29a71f..b983326d63 100644 --- a/frappe/printing/doctype/print_style/print_style.py +++ b/frappe/printing/doctype/print_style/print_style.py @@ -26,7 +26,7 @@ class PrintStyle(Document): self.standard == 1 and not frappe.local.conf.get("developer_mode") and not frappe.flags.in_import - and not frappe.flags.in_test + and not frappe.in_test ): frappe.throw(frappe._("Standard Print Style cannot be changed. Please duplicate to edit.")) diff --git a/frappe/recorder.py b/frappe/recorder.py index b20f09355e..e47a064d2c 100644 --- a/frappe/recorder.py +++ b/frappe/recorder.py @@ -360,7 +360,7 @@ def start( @administrator_only def stop(*args, **kwargs): frappe.client_cache.set_value(RECORDER_INTERCEPT_FLAG, False) - frappe.enqueue(post_process, now=frappe.flags.in_test) + frappe.enqueue(post_process, now=frappe.in_test) @frappe.whitelist() diff --git a/frappe/sessions.py b/frappe/sessions.py index f002aee08f..f8eb48e231 100644 --- a/frappe/sessions.py +++ b/frappe/sessions.py @@ -199,7 +199,7 @@ def get_csrf_token(): def generate_csrf_token(): frappe.local.session.data.csrf_token = frappe.generate_hash() - if not frappe.flags.in_test: + if not frappe.in_test: frappe.local.session_obj.update(force=True) diff --git a/frappe/testing/environment.py b/frappe/testing/environment.py index ac7392c99a..079daa588f 100644 --- a/frappe/testing/environment.py +++ b/frappe/testing/environment.py @@ -29,7 +29,7 @@ import tomli import frappe import frappe.utils.scheduler -from frappe.tests.utils import make_test_records +from frappe.tests.utils import make_test_records, toggle_test_mode from .runner import TestRunnerError from .utils import debug_timer @@ -53,7 +53,7 @@ def _initialize_test_environment(site, config): raise TestRunnerError(f"Failed to connect to the database: {e}") from e # Set various test-related flags - frappe.flags.in_test = True + toggle_test_mode(True) frappe.flags.print_messages = logger.getEffectiveLevel() < logging.INFO frappe.flags.tests_verbose = logger.getEffectiveLevel() < logging.INFO diff --git a/frappe/tests/test_api_v2.py b/frappe/tests/test_api_v2.py index c5f66806b4..518c1cc543 100644 --- a/frappe/tests/test_api_v2.py +++ b/frappe/tests/test_api_v2.py @@ -6,6 +6,7 @@ import requests import frappe from frappe.installer import update_site_config from frappe.tests.test_api import FrappeAPITestCase, suppress_stdout +from frappe.tests.utils import toggle_test_mode authorization_token = None @@ -88,7 +89,13 @@ class TestResourceAPIV2(FrappeAPITestCase): def test_copy_document(self): doc = frappe.get_doc(self.DOCTYPE, self.GENERATED_DOCUMENTS[0]) - response = self.get(self.resource(self.DOCTYPE, doc.name, "copy")) + # disabled temporarily to assert that `docstatus` is not copied outside of tests + toggle_test_mode(False) + try: + response = self.get(self.resource(self.DOCTYPE, doc.name, "copy")) + finally: + toggle_test_mode(True) + self.assertEqual(response.status_code, 200) data = response.json["data"] diff --git a/frappe/tests/test_trace.py b/frappe/tests/test_trace.py index 39e01d56db..6bf02dfbd4 100644 --- a/frappe/tests/test_trace.py +++ b/frappe/tests/test_trace.py @@ -5,6 +5,7 @@ import frappe from frappe.model.document import Document from frappe.model.trace import TracedDocument, traced_field from frappe.tests import UnitTestCase +from frappe.tests.utils import toggle_test_mode def create_mock_meta(doctype): @@ -107,9 +108,9 @@ class TestTracedFieldContext(UnitTestCase): def test_traced_field_context_not_in_test_mode(self): doc = TestDocument() - # Temporarily set frappe.flags.in_test to False - original_in_test = frappe.flags.in_test - frappe.flags.in_test = False + # Temporarily set frappe.in_test to False + original_in_test = frappe.in_test + toggle_test_mode(False) try: with self.trace_fields(TestDocument, test_field={"forbidden_values": ["forbidden"]}): @@ -120,7 +121,7 @@ class TestTracedFieldContext(UnitTestCase): self.assertEqual(doc.test_field, "allowed") finally: # Restore the original in_test flag - frappe.flags.in_test = original_in_test + toggle_test_mode(original_in_test) # After context doc.test_field = "forbidden" diff --git a/frappe/tests/test_utils.py b/frappe/tests/test_utils.py index 01871cca2d..9b62316e20 100644 --- a/frappe/tests/test_utils.py +++ b/frappe/tests/test_utils.py @@ -20,6 +20,7 @@ import frappe from frappe.installer import parse_app_name from frappe.model.document import Document from frappe.tests import IntegrationTestCase, MockedRequestTestCase +from frappe.tests.utils import toggle_test_mode from frappe.utils import ( add_trackers_to_url, ceil, @@ -988,9 +989,9 @@ class TestLazyLoader(IntegrationTestCase): class TestIdenticon(IntegrationTestCase): def test_get_gravatar(self): # developers@frappe.io has a gravatar linked so str URL will be returned - frappe.flags.in_test = False + toggle_test_mode(False) gravatar_url = get_gravatar("developers@frappe.io") - frappe.flags.in_test = True + toggle_test_mode(True) self.assertIsInstance(gravatar_url, str) self.assertTrue(gravatar_url.startswith("http")) diff --git a/frappe/tests/ui_test_helpers.py b/frappe/tests/ui_test_helpers.py index f4a26a6325..07343852db 100644 --- a/frappe/tests/ui_test_helpers.py +++ b/frappe/tests/ui_test_helpers.py @@ -7,7 +7,7 @@ UI_TEST_USER = "frappe@example.com" def whitelist_for_tests(fn): - if frappe.request and not frappe.flags.in_test and not frappe._dev_server: + if frappe.request and not frappe.in_test and not frappe._dev_server: frappe.throw("Cannot run UI tests. Use a development server with `bench start`") return frappe.whitelist()(fn) diff --git a/frappe/tests/utils/__init__.py b/frappe/tests/utils/__init__.py index 1d1192eb6c..58f80f6ecb 100644 --- a/frappe/tests/utils/__init__.py +++ b/frappe/tests/utils/__init__.py @@ -26,6 +26,12 @@ def check_orpahned_doctypes(): ) +def toggle_test_mode(enable: bool): + """Enable or disable `frappe.in_test` (and related deprecated flag)""" + frappe.in_test = enable + frappe.local.flags.in_test = enable + + from frappe.deprecation_dumpster import ( get_tests_CompatFrappeTestCase, ) diff --git a/frappe/utils/__init__.py b/frappe/utils/__init__.py index 8f7cb8672f..a9bdee4d1a 100644 --- a/frappe/utils/__init__.py +++ b/frappe/utils/__init__.py @@ -269,7 +269,7 @@ def has_gravatar(email: str) -> str: """Return gravatar url if user has set an avatar at gravatar.com.""" import requests - if frappe.flags.in_import or frappe.flags.in_install or frappe.flags.in_test: + if frappe.flags.in_import or frappe.flags.in_install or frappe.in_test: # no gravatar if via upload # since querying gravatar for every item will be slow return "" diff --git a/frappe/utils/background_jobs.py b/frappe/utils/background_jobs.py index f42fef8032..5926c5c656 100644 --- a/frappe/utils/background_jobs.py +++ b/frappe/utils/background_jobs.py @@ -139,7 +139,7 @@ def enqueue( "unknown", "v17", "Using enqueue with `job_name` is deprecated, use `job_id` instead." ) - if not is_async and not frappe.flags.in_test: + if not is_async and not frappe.in_test: from frappe.deprecation_dumpster import deprecation_warning deprecation_warning( @@ -148,7 +148,7 @@ def enqueue( "Using enqueue with is_async=False outside of tests is not recommended, use now=True instead.", ) - call_directly = now or (not is_async and not frappe.flags.in_test) + call_directly = now or (not is_async and not frappe.in_test) if call_directly: return frappe.call(method, **kwargs) @@ -243,7 +243,9 @@ def execute_job(site, method, event, job_name, kwargs, user=None, is_async=True, frappe.init(site, force=True) frappe.connect() if os.environ.get("CI"): - frappe.flags.in_test = True + from frappe.tests.utils import toggle_test_mode + + toggle_test_mode(True) if user: frappe.set_user(user) diff --git a/frappe/utils/user.py b/frappe/utils/user.py index 680a1d786f..5d9e1dc65e 100644 --- a/frappe/utils/user.py +++ b/frappe/utils/user.py @@ -59,7 +59,7 @@ class UserPermissions: return user - if not frappe.flags.in_install_db and not frappe.flags.in_test: + if not frappe.flags.in_install_db and not frappe.in_test: user_doc = frappe.cache.hget("user_doc", self.name, get_user_doc) if user_doc: self.doc = frappe.get_doc(user_doc) diff --git a/frappe/website/doctype/personal_data_deletion_request/personal_data_deletion_request.py b/frappe/website/doctype/personal_data_deletion_request/personal_data_deletion_request.py index 188ccba6b6..ecd5437e06 100644 --- a/frappe/website/doctype/personal_data_deletion_request/personal_data_deletion_request.py +++ b/frappe/website/doctype/personal_data_deletion_request/personal_data_deletion_request.py @@ -136,7 +136,7 @@ class PersonalDataDeletionRequest(Document): "_anonymize_data", queue="long", timeout=3000, - now=frappe.flags.in_test, + now=frappe.in_test, ) def notify_user_after_deletion(self): diff --git a/frappe/website/doctype/personal_data_download_request/personal_data_download_request.py b/frappe/website/doctype/personal_data_download_request/personal_data_download_request.py index c725ca8c0b..a41011e9fb 100644 --- a/frappe/website/doctype/personal_data_download_request/personal_data_download_request.py +++ b/frappe/website/doctype/personal_data_download_request/personal_data_download_request.py @@ -32,7 +32,7 @@ class PersonalDataDownloadRequest(Document): "generate_file_and_send_mail", queue="short", personal_data=personal_data, - now=frappe.flags.in_test, + now=frappe.in_test, ) def generate_file_and_send_mail(self, personal_data): diff --git a/frappe/website/doctype/web_form/web_form.py b/frappe/website/doctype/web_form/web_form.py index 615a1ae16d..c426e79e94 100644 --- a/frappe/website/doctype/web_form/web_form.py +++ b/frappe/website/doctype/web_form/web_form.py @@ -79,10 +79,7 @@ class WebForm(WebsiteGenerator): self.module = frappe.db.get_value("DocType", self.doc_type, "module") in_user_env = not ( - frappe.flags.in_install - or frappe.flags.in_patch - or frappe.flags.in_test - or frappe.flags.in_fixtures + frappe.flags.in_install or frappe.flags.in_patch or frappe.in_test or frappe.flags.in_fixtures ) if in_user_env and self.is_standard and not frappe.conf.developer_mode: # only published can be changed for standard web forms diff --git a/frappe/website/doctype/website_theme/website_theme.py b/frappe/website/doctype/website_theme/website_theme.py index e7487bf4d8..2ae69a92ba 100644 --- a/frappe/website/doctype/website_theme/website_theme.py +++ b/frappe/website/doctype/website_theme/website_theme.py @@ -55,7 +55,7 @@ class WebsiteTheme(Document): not self.custom and frappe.local.conf.get("developer_mode") and not frappe.flags.in_import - and not frappe.flags.in_test + and not frappe.in_test ): self.export_doc() @@ -65,7 +65,7 @@ class WebsiteTheme(Document): return ( not self.custom and not frappe.local.conf.get("developer_mode") - and not (frappe.flags.in_import or frappe.flags.in_test or frappe.flags.in_migrate) + and not (frappe.flags.in_import or frappe.in_test or frappe.flags.in_migrate) ) def on_trash(self): diff --git a/frappe/website/utils.py b/frappe/website/utils.py index f3b06647b2..5dca169bc0 100644 --- a/frappe/website/utils.py +++ b/frappe/website/utils.py @@ -94,7 +94,7 @@ def get_comment_list(doctype, name): def get_home_page(): - if frappe.local.flags.home_page and not frappe.flags.in_test: + if frappe.local.flags.home_page and not frappe.in_test: return frappe.local.flags.home_page def _get_home_page(): diff --git a/frappe/website/website_generator.py b/frappe/website/website_generator.py index 17d2a6f1bb..cdf05cce8e 100644 --- a/frappe/website/website_generator.py +++ b/frappe/website/website_generator.py @@ -155,7 +155,7 @@ class WebsiteGenerator(Document): def remove_old_route_from_index(self): """Remove page from the website index if the route has changed.""" - if self.allow_website_search_indexing() or frappe.flags.in_test: + if self.allow_website_search_indexing() or frappe.in_test: return old_doc = self.get_doc_before_save() # Check if the route is changed @@ -169,7 +169,7 @@ class WebsiteGenerator(Document): - remove document from index if document is unpublished - update index otherwise """ - if not self.allow_website_search_indexing() or frappe.flags.in_test: + if not self.allow_website_search_indexing() or frappe.in_test: return if self.is_website_published(): diff --git a/frappe/workflow/doctype/workflow_action/workflow_action.py b/frappe/workflow/doctype/workflow_action/workflow_action.py index 2982a9842e..7766970b84 100644 --- a/frappe/workflow/doctype/workflow_action/workflow_action.py +++ b/frappe/workflow/doctype/workflow_action/workflow_action.py @@ -122,7 +122,7 @@ def process_workflow_actions(doc, state): doc=doc, transitions=next_possible_transitions, enqueue_after_commit=True, - now=frappe.flags.in_test, + now=frappe.in_test, ) diff --git a/frappe/www/list.py b/frappe/www/list.py index 090e65ab74..ad83262912 100644 --- a/frappe/www/list.py +++ b/frappe/www/list.py @@ -56,7 +56,7 @@ def get(doctype, txt=None, limit_start=0, limit=20, pathname=None, **kwargs): new_context.doc = frappe.get_doc(doc.doctype, doc.name) new_context.update(new_context.doc.as_dict()) - if not frappe.flags.in_test: + if not frappe.in_test: pathname = pathname or frappe.local.request.path new_context["pathname"] = pathname.strip("/ ") new_context.update(list_context)