We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Enable Scheduler from desk
Feature to enable scheduler from desk.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `frappe/utils/scheduler.py`
Content:
```
1 # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
2 # License: MIT. See LICENSE
3 """
4 Events:
5 	always
6 	daily
7 	monthly
8 	weekly
9 """
10 
11 # imports - standard imports
12 import os
13 import time
14 from typing import NoReturn
15 
16 # imports - module imports
17 import frappe
18 from frappe.installer import update_site_config
19 from frappe.utils import cint, get_datetime, get_sites, now_datetime
20 from frappe.utils.background_jobs import get_jobs
21 
22 DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
23 
24 
25 def cprint(*args, **kwargs):
26 	"""Prints only if called from STDOUT"""
27 	try:
28 		os.get_terminal_size()
29 		print(*args, **kwargs)
30 	except Exception:
31 		pass
32 
33 
34 def start_scheduler() -> NoReturn:
35 	"""Run enqueue_events_for_all_sites based on scheduler tick.
36 	Specify scheduler_interval in seconds in common_site_config.json"""
37 
38 	tick = cint(frappe.get_conf().scheduler_tick_interval) or 60
39 
40 	while True:
41 		time.sleep(tick)
42 		enqueue_events_for_all_sites()
43 
44 
45 def enqueue_events_for_all_sites() -> None:
46 	"""Loop through sites and enqueue events that are not already queued"""
47 
48 	if os.path.exists(os.path.join(".", ".restarting")):
49 		# Don't add task to queue if webserver is in restart mode
50 		return
51 
52 	with frappe.init_site():
53 		sites = get_sites()
54 
55 	for site in sites:
56 		try:
57 			enqueue_events_for_site(site=site)
58 		except Exception:
59 			frappe.logger("scheduler").debug(f"Failed to enqueue events for site: {site}", exc_info=True)
60 
61 
62 def enqueue_events_for_site(site: str) -> None:
63 	def log_exc():
64 		frappe.logger("scheduler").error(f"Exception in Enqueue Events for Site {site}", exc_info=True)
65 
66 	try:
67 		frappe.init(site=site)
68 		frappe.connect()
69 		if is_scheduler_inactive():
70 			return
71 
72 		enqueue_events(site=site)
73 
74 		frappe.logger("scheduler").debug(f"Queued events for site {site}")
75 	except Exception as e:
76 		if frappe.db.is_access_denied(e):
77 			frappe.logger("scheduler").debug(f"Access denied for site {site}")
78 		log_exc()
79 
80 	finally:
81 		frappe.destroy()
82 
83 
84 def enqueue_events(site: str) -> list[str] | None:
85 	if schedule_jobs_based_on_activity():
86 		enqueued_jobs = []
87 		for job_type in frappe.get_all("Scheduled Job Type", ("name", "method"), {"stopped": 0}):
88 			job_type = frappe.get_cached_doc("Scheduled Job Type", job_type.name)
89 			if _enqueued := job_type.enqueue():
90 				enqueued_jobs.append(job_type.method)
91 
92 		return enqueued_jobs
93 
94 
95 def is_scheduler_inactive(verbose=True) -> bool:
96 	if frappe.local.conf.maintenance_mode:
97 		if verbose:
98 			cprint(f"{frappe.local.site}: Maintenance mode is ON")
99 		return True
100 
101 	if frappe.local.conf.pause_scheduler:
102 		if verbose:
103 			cprint(f"{frappe.local.site}: frappe.conf.pause_scheduler is SET")
104 		return True
105 
106 	if is_scheduler_disabled(verbose=verbose):
107 		return True
108 
109 	return False
110 
111 
112 def is_scheduler_disabled(verbose=True) -> bool:
113 	if frappe.conf.disable_scheduler:
114 		if verbose:
115 			cprint(f"{frappe.local.site}: frappe.conf.disable_scheduler is SET")
116 		return True
117 
118 	scheduler_disabled = not frappe.utils.cint(
119 		frappe.db.get_single_value("System Settings", "enable_scheduler")
120 	)
121 	if scheduler_disabled:
122 		if verbose:
123 			cprint(f"{frappe.local.site}: SystemSettings.enable_scheduler is UNSET")
124 	return scheduler_disabled
125 
126 
127 def toggle_scheduler(enable):
128 	frappe.db.set_single_value("System Settings", "enable_scheduler", int(enable))
129 
130 
131 def enable_scheduler():
132 	toggle_scheduler(True)
133 
134 
135 def disable_scheduler():
136 	toggle_scheduler(False)
137 
138 
139 def schedule_jobs_based_on_activity(check_time=None):
140 	"""Returns True for active sites defined by Activity Log
141 	Returns True for inactive sites once in 24 hours"""
142 	if is_dormant(check_time=check_time):
143 		# ensure last job is one day old
144 		last_job_timestamp = _get_last_modified_timestamp("Scheduled Job Log")
145 		if not last_job_timestamp:
146 			return True
147 		else:
148 			if ((check_time or now_datetime()) - last_job_timestamp).total_seconds() >= 86400:
149 				# one day is passed since jobs are run, so lets do this
150 				return True
151 			else:
152 				# schedulers run in the last 24 hours, do nothing
153 				return False
154 	else:
155 		# site active, lets run the jobs
156 		return True
157 
158 
159 def is_dormant(check_time=None):
160 	last_activity_log_timestamp = _get_last_modified_timestamp("Activity Log")
161 	since = (frappe.get_system_settings("dormant_days") or 4) * 86400
162 	if not last_activity_log_timestamp:
163 		return True
164 	if ((check_time or now_datetime()) - last_activity_log_timestamp).total_seconds() >= since:
165 		return True
166 	return False
167 
168 
169 def _get_last_modified_timestamp(doctype):
170 	timestamp = frappe.db.get_value(
171 		doctype, filters={}, fieldname="modified", order_by="modified desc"
172 	)
173 	if timestamp:
174 		return get_datetime(timestamp)
175 
176 
177 @frappe.whitelist()
178 def activate_scheduler():
179 	if is_scheduler_disabled():
180 		enable_scheduler()
181 	if frappe.conf.pause_scheduler:
182 		update_site_config("pause_scheduler", 0)
183 
184 
185 @frappe.whitelist()
186 def get_scheduler_status():
187 	if is_scheduler_inactive():
188 		return {"status": "inactive"}
189 	return {"status": "active"}
190
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/frappe/utils/scheduler.py b/frappe/utils/scheduler.py
--- a/frappe/utils/scheduler.py
+++ b/frappe/utils/scheduler.py
@@ -176,6 +176,11 @@
 
 @frappe.whitelist()
 def activate_scheduler():
+	frappe.only_for("Administrator")
+
+	if frappe.local.conf.maintenance_mode:
+		frappe.throw(frappe._("Scheduler can not be re-enabled when maintenance mode is active."))
+
 	if is_scheduler_disabled():
 		enable_scheduler()
 	if frappe.conf.pause_scheduler:

{"golden_diff": "diff --git a/frappe/utils/scheduler.py b/frappe/utils/scheduler.py\n--- a/frappe/utils/scheduler.py\n+++ b/frappe/utils/scheduler.py\n@@ -176,6 +176,11 @@\n \n @frappe.whitelist()\n def activate_scheduler():\n+\tfrappe.only_for(\"Administrator\")\n+\n+\tif frappe.local.conf.maintenance_mode:\n+\t\tfrappe.throw(frappe._(\"Scheduler can not be re-enabled when maintenance mode is active.\"))\n+\n \tif is_scheduler_disabled():\n \t\tenable_scheduler()\n \tif frappe.conf.pause_scheduler:\n", "issue": "Enable Scheduler from desk\nFeature to enable scheduler from desk.\n", "before_files": [{"content": "# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors\n# License: MIT. See LICENSE\n\"\"\"\nEvents:\n\talways\n\tdaily\n\tmonthly\n\tweekly\n\"\"\"\n\n# imports - standard imports\nimport os\nimport time\nfrom typing import NoReturn\n\n# imports - module imports\nimport frappe\nfrom frappe.installer import update_site_config\nfrom frappe.utils import cint, get_datetime, get_sites, now_datetime\nfrom frappe.utils.background_jobs import get_jobs\n\nDATETIME_FORMAT = \"%Y-%m-%d %H:%M:%S\"\n\n\ndef cprint(*args, **kwargs):\n\t\"\"\"Prints only if called from STDOUT\"\"\"\n\ttry:\n\t\tos.get_terminal_size()\n\t\tprint(*args, **kwargs)\n\texcept Exception:\n\t\tpass\n\n\ndef start_scheduler() -> NoReturn:\n\t\"\"\"Run enqueue_events_for_all_sites based on scheduler tick.\n\tSpecify scheduler_interval in seconds in common_site_config.json\"\"\"\n\n\ttick = cint(frappe.get_conf().scheduler_tick_interval) or 60\n\n\twhile True:\n\t\ttime.sleep(tick)\n\t\tenqueue_events_for_all_sites()\n\n\ndef enqueue_events_for_all_sites() -> None:\n\t\"\"\"Loop through sites and enqueue events that are not already queued\"\"\"\n\n\tif os.path.exists(os.path.join(\".\", \".restarting\")):\n\t\t# Don't add task to queue if webserver is in restart mode\n\t\treturn\n\n\twith frappe.init_site():\n\t\tsites = get_sites()\n\n\tfor site in sites:\n\t\ttry:\n\t\t\tenqueue_events_for_site(site=site)\n\t\texcept Exception:\n\t\t\tfrappe.logger(\"scheduler\").debug(f\"Failed to enqueue events for site: {site}\", exc_info=True)\n\n\ndef enqueue_events_for_site(site: str) -> None:\n\tdef log_exc():\n\t\tfrappe.logger(\"scheduler\").error(f\"Exception in Enqueue Events for Site {site}\", exc_info=True)\n\n\ttry:\n\t\tfrappe.init(site=site)\n\t\tfrappe.connect()\n\t\tif is_scheduler_inactive():\n\t\t\treturn\n\n\t\tenqueue_events(site=site)\n\n\t\tfrappe.logger(\"scheduler\").debug(f\"Queued events for site {site}\")\n\texcept Exception as e:\n\t\tif frappe.db.is_access_denied(e):\n\t\t\tfrappe.logger(\"scheduler\").debug(f\"Access denied for site {site}\")\n\t\tlog_exc()\n\n\tfinally:\n\t\tfrappe.destroy()\n\n\ndef enqueue_events(site: str) -> list[str] | None:\n\tif schedule_jobs_based_on_activity():\n\t\tenqueued_jobs = []\n\t\tfor job_type in frappe.get_all(\"Scheduled Job Type\", (\"name\", \"method\"), {\"stopped\": 0}):\n\t\t\tjob_type = frappe.get_cached_doc(\"Scheduled Job Type\", job_type.name)\n\t\t\tif _enqueued := job_type.enqueue():\n\t\t\t\tenqueued_jobs.append(job_type.method)\n\n\t\treturn enqueued_jobs\n\n\ndef is_scheduler_inactive(verbose=True) -> bool:\n\tif frappe.local.conf.maintenance_mode:\n\t\tif verbose:\n\t\t\tcprint(f\"{frappe.local.site}: Maintenance mode is ON\")\n\t\treturn True\n\n\tif frappe.local.conf.pause_scheduler:\n\t\tif verbose:\n\t\t\tcprint(f\"{frappe.local.site}: frappe.conf.pause_scheduler is SET\")\n\t\treturn True\n\n\tif is_scheduler_disabled(verbose=verbose):\n\t\treturn True\n\n\treturn False\n\n\ndef is_scheduler_disabled(verbose=True) -> bool:\n\tif frappe.conf.disable_scheduler:\n\t\tif verbose:\n\t\t\tcprint(f\"{frappe.local.site}: frappe.conf.disable_scheduler is SET\")\n\t\treturn True\n\n\tscheduler_disabled = not frappe.utils.cint(\n\t\tfrappe.db.get_single_value(\"System Settings\", \"enable_scheduler\")\n\t)\n\tif scheduler_disabled:\n\t\tif verbose:\n\t\t\tcprint(f\"{frappe.local.site}: SystemSettings.enable_scheduler is UNSET\")\n\treturn scheduler_disabled\n\n\ndef toggle_scheduler(enable):\n\tfrappe.db.set_single_value(\"System Settings\", \"enable_scheduler\", int(enable))\n\n\ndef enable_scheduler():\n\ttoggle_scheduler(True)\n\n\ndef disable_scheduler():\n\ttoggle_scheduler(False)\n\n\ndef schedule_jobs_based_on_activity(check_time=None):\n\t\"\"\"Returns True for active sites defined by Activity Log\n\tReturns True for inactive sites once in 24 hours\"\"\"\n\tif is_dormant(check_time=check_time):\n\t\t# ensure last job is one day old\n\t\tlast_job_timestamp = _get_last_modified_timestamp(\"Scheduled Job Log\")\n\t\tif not last_job_timestamp:\n\t\t\treturn True\n\t\telse:\n\t\t\tif ((check_time or now_datetime()) - last_job_timestamp).total_seconds() >= 86400:\n\t\t\t\t# one day is passed since jobs are run, so lets do this\n\t\t\t\treturn True\n\t\t\telse:\n\t\t\t\t# schedulers run in the last 24 hours, do nothing\n\t\t\t\treturn False\n\telse:\n\t\t# site active, lets run the jobs\n\t\treturn True\n\n\ndef is_dormant(check_time=None):\n\tlast_activity_log_timestamp = _get_last_modified_timestamp(\"Activity Log\")\n\tsince = (frappe.get_system_settings(\"dormant_days\") or 4) * 86400\n\tif not last_activity_log_timestamp:\n\t\treturn True\n\tif ((check_time or now_datetime()) - last_activity_log_timestamp).total_seconds() >= since:\n\t\treturn True\n\treturn False\n\n\ndef _get_last_modified_timestamp(doctype):\n\ttimestamp = frappe.db.get_value(\n\t\tdoctype, filters={}, fieldname=\"modified\", order_by=\"modified desc\"\n\t)\n\tif timestamp:\n\t\treturn get_datetime(timestamp)\n\n\n@frappe.whitelist()\ndef activate_scheduler():\n\tif is_scheduler_disabled():\n\t\tenable_scheduler()\n\tif frappe.conf.pause_scheduler:\n\t\tupdate_site_config(\"pause_scheduler\", 0)\n\n\n@frappe.whitelist()\ndef get_scheduler_status():\n\tif is_scheduler_inactive():\n\t\treturn {\"status\": \"inactive\"}\n\treturn {\"status\": \"active\"}\n", "path": "frappe/utils/scheduler.py"}], "after_files": [{"content": "# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors\n# License: MIT. See LICENSE\n\"\"\"\nEvents:\n\talways\n\tdaily\n\tmonthly\n\tweekly\n\"\"\"\n\n# imports - standard imports\nimport os\nimport time\nfrom typing import NoReturn\n\n# imports - module imports\nimport frappe\nfrom frappe.installer import update_site_config\nfrom frappe.utils import cint, get_datetime, get_sites, now_datetime\nfrom frappe.utils.background_jobs import get_jobs\n\nDATETIME_FORMAT = \"%Y-%m-%d %H:%M:%S\"\n\n\ndef cprint(*args, **kwargs):\n\t\"\"\"Prints only if called from STDOUT\"\"\"\n\ttry:\n\t\tos.get_terminal_size()\n\t\tprint(*args, **kwargs)\n\texcept Exception:\n\t\tpass\n\n\ndef start_scheduler() -> NoReturn:\n\t\"\"\"Run enqueue_events_for_all_sites based on scheduler tick.\n\tSpecify scheduler_interval in seconds in common_site_config.json\"\"\"\n\n\ttick = cint(frappe.get_conf().scheduler_tick_interval) or 60\n\n\twhile True:\n\t\ttime.sleep(tick)\n\t\tenqueue_events_for_all_sites()\n\n\ndef enqueue_events_for_all_sites() -> None:\n\t\"\"\"Loop through sites and enqueue events that are not already queued\"\"\"\n\n\tif os.path.exists(os.path.join(\".\", \".restarting\")):\n\t\t# Don't add task to queue if webserver is in restart mode\n\t\treturn\n\n\twith frappe.init_site():\n\t\tsites = get_sites()\n\n\tfor site in sites:\n\t\ttry:\n\t\t\tenqueue_events_for_site(site=site)\n\t\texcept Exception:\n\t\t\tfrappe.logger(\"scheduler\").debug(f\"Failed to enqueue events for site: {site}\", exc_info=True)\n\n\ndef enqueue_events_for_site(site: str) -> None:\n\tdef log_exc():\n\t\tfrappe.logger(\"scheduler\").error(f\"Exception in Enqueue Events for Site {site}\", exc_info=True)\n\n\ttry:\n\t\tfrappe.init(site=site)\n\t\tfrappe.connect()\n\t\tif is_scheduler_inactive():\n\t\t\treturn\n\n\t\tenqueue_events(site=site)\n\n\t\tfrappe.logger(\"scheduler\").debug(f\"Queued events for site {site}\")\n\texcept Exception as e:\n\t\tif frappe.db.is_access_denied(e):\n\t\t\tfrappe.logger(\"scheduler\").debug(f\"Access denied for site {site}\")\n\t\tlog_exc()\n\n\tfinally:\n\t\tfrappe.destroy()\n\n\ndef enqueue_events(site: str) -> list[str] | None:\n\tif schedule_jobs_based_on_activity():\n\t\tenqueued_jobs = []\n\t\tfor job_type in frappe.get_all(\"Scheduled Job Type\", (\"name\", \"method\"), {\"stopped\": 0}):\n\t\t\tjob_type = frappe.get_cached_doc(\"Scheduled Job Type\", job_type.name)\n\t\t\tif _enqueued := job_type.enqueue():\n\t\t\t\tenqueued_jobs.append(job_type.method)\n\n\t\treturn enqueued_jobs\n\n\ndef is_scheduler_inactive(verbose=True) -> bool:\n\tif frappe.local.conf.maintenance_mode:\n\t\tif verbose:\n\t\t\tcprint(f\"{frappe.local.site}: Maintenance mode is ON\")\n\t\treturn True\n\n\tif frappe.local.conf.pause_scheduler:\n\t\tif verbose:\n\t\t\tcprint(f\"{frappe.local.site}: frappe.conf.pause_scheduler is SET\")\n\t\treturn True\n\n\tif is_scheduler_disabled(verbose=verbose):\n\t\treturn True\n\n\treturn False\n\n\ndef is_scheduler_disabled(verbose=True) -> bool:\n\tif frappe.conf.disable_scheduler:\n\t\tif verbose:\n\t\t\tcprint(f\"{frappe.local.site}: frappe.conf.disable_scheduler is SET\")\n\t\treturn True\n\n\tscheduler_disabled = not frappe.utils.cint(\n\t\tfrappe.db.get_single_value(\"System Settings\", \"enable_scheduler\")\n\t)\n\tif scheduler_disabled:\n\t\tif verbose:\n\t\t\tcprint(f\"{frappe.local.site}: SystemSettings.enable_scheduler is UNSET\")\n\treturn scheduler_disabled\n\n\ndef toggle_scheduler(enable):\n\tfrappe.db.set_single_value(\"System Settings\", \"enable_scheduler\", int(enable))\n\n\ndef enable_scheduler():\n\ttoggle_scheduler(True)\n\n\ndef disable_scheduler():\n\ttoggle_scheduler(False)\n\n\ndef schedule_jobs_based_on_activity(check_time=None):\n\t\"\"\"Returns True for active sites defined by Activity Log\n\tReturns True for inactive sites once in 24 hours\"\"\"\n\tif is_dormant(check_time=check_time):\n\t\t# ensure last job is one day old\n\t\tlast_job_timestamp = _get_last_modified_timestamp(\"Scheduled Job Log\")\n\t\tif not last_job_timestamp:\n\t\t\treturn True\n\t\telse:\n\t\t\tif ((check_time or now_datetime()) - last_job_timestamp).total_seconds() >= 86400:\n\t\t\t\t# one day is passed since jobs are run, so lets do this\n\t\t\t\treturn True\n\t\t\telse:\n\t\t\t\t# schedulers run in the last 24 hours, do nothing\n\t\t\t\treturn False\n\telse:\n\t\t# site active, lets run the jobs\n\t\treturn True\n\n\ndef is_dormant(check_time=None):\n\tlast_activity_log_timestamp = _get_last_modified_timestamp(\"Activity Log\")\n\tsince = (frappe.get_system_settings(\"dormant_days\") or 4) * 86400\n\tif not last_activity_log_timestamp:\n\t\treturn True\n\tif ((check_time or now_datetime()) - last_activity_log_timestamp).total_seconds() >= since:\n\t\treturn True\n\treturn False\n\n\ndef _get_last_modified_timestamp(doctype):\n\ttimestamp = frappe.db.get_value(\n\t\tdoctype, filters={}, fieldname=\"modified\", order_by=\"modified desc\"\n\t)\n\tif timestamp:\n\t\treturn get_datetime(timestamp)\n\n\n@frappe.whitelist()\ndef activate_scheduler():\n\tfrappe.only_for(\"Administrator\")\n\n\tif frappe.local.conf.maintenance_mode:\n\t\tfrappe.throw(frappe._(\"Scheduler can not be re-enabled when maintenance mode is active.\"))\n\n\tif is_scheduler_disabled():\n\t\tenable_scheduler()\n\tif frappe.conf.pause_scheduler:\n\t\tupdate_site_config(\"pause_scheduler\", 0)\n\n\n@frappe.whitelist()\ndef get_scheduler_status():\n\tif is_scheduler_inactive():\n\t\treturn {\"status\": \"inactive\"}\n\treturn {\"status\": \"active\"}\n", "path": "frappe/utils/scheduler.py"}]}