From b6493edc7033beac216b8836af4994e56c6682f4 Mon Sep 17 00:00:00 2001 From: Adnan Hodzic Date: Sun, 13 Apr 2025 23:01:00 +0200 Subject: [PATCH] Remove needs_confirmation & Readme update --- README.md | 4 +- auto_cpufreq/bin/auto_cpufreq.py | 286 ++++++++++--------------------- 2 files changed, 96 insertions(+), 194 deletions(-) diff --git a/README.md b/README.md index ac2e6cb..744d693 100644 --- a/README.md +++ b/README.md @@ -21,11 +21,11 @@ If you're having a problem with auto-cpufreq, before ([submitting an issue](http Example of auto-cpufreq GUI (available >= v2.0) -Example of auto-cpufreq desktop entry (icon) +Example of auto-cpufreq GUI (available >= v2.0) Example of `auto-cpufreq --stats` CLI output -Example of auto-cpufreq desktop entry (icon) +Example of auto-cpufreq CLI output ## Looking for developers and co-maintainers diff --git a/auto_cpufreq/bin/auto_cpufreq.py b/auto_cpufreq/bin/auto_cpufreq.py index f37c625..fa7872c 100755 --- a/auto_cpufreq/bin/auto_cpufreq.py +++ b/auto_cpufreq/bin/auto_cpufreq.py @@ -12,7 +12,7 @@ from shutil import rmtree from auto_cpufreq.battery_scripts.battery import * from auto_cpufreq.config.config import config as conf, find_config_file from auto_cpufreq.core import * -from auto_cpufreq.globals import GITHUB, IS_INSTALLED_WITH_AUR, IS_INSTALLED_WITH_SNAP, SNAP_DAEMON_CHECK +from auto_cpufreq.globals import GITHUB, IS_INSTALLED_WITH_AUR, IS_INSTALLED_WITH_SNAP from auto_cpufreq.modules.system_monitor import ViewType, SystemMonitor # import everything from power_helper, including bluetooth_disable and bluetooth_enable from auto_cpufreq.power_helper import * @@ -35,9 +35,7 @@ from threading import Thread @click.option("--version", is_flag=True, help="Show currently installed version") @click.option("--donate", is_flag=True, help="Support the project") def main(monitor, live, daemon, install, update, remove, force, config, stats, get_state, - bluetooth_boot_off, - bluetooth_boot_on, - debug, version, donate): + bluetooth_boot_off, bluetooth_boot_on, debug, version, donate): # display info if config file is used config_path = find_config_file(config) conf.set_path(config_path) @@ -45,25 +43,22 @@ def main(monitor, live, daemon, install, update, remove, force, config, stats, g if conf.has_config(): print("\nUsing settings defined in " + config_path + " file") - # Check for empty arguments first - is_empty_run = len(sys.argv) == 1 - - # set governor override unless None or invalid, but not if it's an empty run - if not is_empty_run and force is not None: - not_running_daemon_check() - root_check() - set_override(force) - - # Handle empty run after potential force override is processed or skipped - if is_empty_run: + if len(sys.argv) == 1: print("\n" + "-" * 32 + " auto-cpufreq " + "-" * 33 + "\n") print("Automatic CPU speed & power optimizer for Linux") + print("\nExample usage:\nauto-cpufreq --monitor") print("\n-----\n") + run(["auto-cpufreq", "--help"]) footer() - # Handle other flags if it's not an empty run else: + # set governor override unless None or invalid + if force is not None: + not_running_daemon_check() + root_check() # Calling root_check before set_override as it will require sudo access + set_override(force) # Calling set override, only if force has some values + if monitor: root_check() battery_setup() @@ -74,22 +69,16 @@ def main(monitor, live, daemon, install, update, remove, force, config, stats, g else: gnome_power_detect() tlp_service_detect() - - # Determine if confirmation is needed - needs_confirmation = IS_INSTALLED_WITH_SNAP or tlp_stat_exists - # Check gnome_power_status only if relevant variables exist - if not IS_INSTALLED_WITH_SNAP and 'systemctl_exists' in globals() and systemctl_exists and 'gnome_power_status' in locals() and not bool(gnome_power_status): - needs_confirmation = True - - if needs_confirmation: + + if IS_INSTALLED_WITH_SNAP or tlp_stat_exists or (systemctl_exists and not bool(gnome_power_status)): try: input("press Enter to continue or Ctrl + c to exit...") except KeyboardInterrupt: conf.notifier.stop() sys.exit(0) - - monitor_instance = SystemMonitor(suggestion=True, type=ViewType.MONITOR) - monitor_instance.run(on_quit=conf.notifier.stop) + + monitor = SystemMonitor(suggestion=True, type=ViewType.MONITOR) + monitor.run(on_quit=conf.notifier.stop) elif live: root_check() battery_setup() @@ -102,51 +91,44 @@ def main(monitor, live, daemon, install, update, remove, force, config, stats, g gnome_power_stop_live() tuned_stop_live() tlp_service_detect() - - # Determine if confirmation is needed - needs_confirmation = IS_INSTALLED_WITH_SNAP or tlp_stat_exists - # Check gnome_power_status only if relevant variables exist - if not IS_INSTALLED_WITH_SNAP and 'systemctl_exists' in globals() and systemctl_exists and 'gnome_power_status' in locals() and not bool(gnome_power_status): - needs_confirmation = True - - if needs_confirmation: + + if IS_INSTALLED_WITH_SNAP or tlp_stat_exists or (systemctl_exists and not bool(gnome_power_status)): try: input("press Enter to continue or Ctrl + c to exit...") except KeyboardInterrupt: conf.notifier.stop() sys.exit(0) - + cpufreqctl() def live_daemon(): + # Redirect stdout to suppress prints class NullWriter: def write(self, _): pass def flush(self): pass - original_stdout = sys.stdout try: sys.stdout = NullWriter() + while True: time.sleep(1) set_autofreq() - except Exception as e: # Catch specific exceptions if possible - print(f"Error in live daemon thread: {e}", file=original_stdout) # Log errors - finally: - sys.stdout = original_stdout # Ensure stdout is restored - + except: + pass + def live_daemon_off(): gnome_power_start_live() tuned_start_live() cpufreqctl_restore() conf.notifier.stop() - + thread = Thread(target=live_daemon, daemon=True) thread.start() - - monitor_instance = SystemMonitor(type=ViewType.LIVE) - monitor_instance.run(on_quit=live_daemon_off) + + monitor = SystemMonitor(type=ViewType.LIVE) + monitor.run(on_quit=live_daemon_off) elif daemon: config_info_dialog() root_check() - file_stats() # This function from core.py likely uses the stats paths internally + file_stats() if IS_INSTALLED_WITH_SNAP and SNAP_DAEMON_CHECK == "enabled": gnome_power_detect_snap() tlp_service_detect_snap() @@ -155,142 +137,83 @@ def main(monitor, live, daemon, install, update, remove, force, config, stats, g tlp_service_detect() battery_setup() conf.notifier.start() - print("Starting auto-cpufreq daemon...") # Add startup message - try: - # Initial setup before loop - gov_check() - cpufreqctl() - distro_info() # Show info once on start - sysinfo() # Show info once on start - while True: + while True: + try: + footer() + gov_check() + cpufreqctl() + distro_info() + sysinfo() set_autofreq() - time.sleep(2) # Use simple sleep instead of countdown - except KeyboardInterrupt: - print("\nDaemon interrupted. Restoring settings...") - finally: # Ensure cleanup happens - conf.notifier.stop() - cpufreqctl_restore() # Restore system state when daemon stops - footer() + countdown(2) + except KeyboardInterrupt: break + conf.notifier.stop() elif install: root_check() if IS_INSTALLED_WITH_SNAP: running_daemon_check() gnome_power_detect_snap() tlp_service_detect_snap() - bluetooth_notif_snap() # Warn about bluetooth boot setting + bluetooth_notif_snap() gov_check() - run("snapctl set daemon=enabled", shell=True, check=True) - run("snapctl start --enable auto-cpufreq", shell=True, check=True) + run("snapctl set daemon=enabled", shell=True) + run("snapctl start --enable auto-cpufreq", shell=True) else: running_daemon_check() gov_check() - deploy_daemon() # This function from core.py likely uses stats paths + deploy_daemon() deploy_complete_msg() elif update: root_check() custom_dir = "/opt/auto-cpufreq/source" - update_flag_present = False - args_to_remove = [] - # Simplified update argument parsing + for arg in sys.argv: + if arg.startswith("--update="): + custom_dir = arg.split("=")[1] + sys.argv.remove(arg) + if "--update" in sys.argv: - update_flag_present = True - args_to_remove.append("--update") - # Simple check if next arg exists and isn't another flag - idx = sys.argv.index("--update") - if idx + 1 < len(sys.argv) and not sys.argv[idx+1].startswith('--'): - custom_dir = sys.argv[idx+1] - args_to_remove.append(custom_dir) + update = True + sys.argv.remove("--update") + if len(sys.argv) == 2: custom_dir = sys.argv[1] + + if IS_INSTALLED_WITH_SNAP: + print("Detected auto-cpufreq was installed using snap") + # refresh snap directly using this command + # path wont work in this case + + print("Please update using snap package manager, i.e: `sudo snap refresh auto-cpufreq`.") + #check for AUR + elif IS_INSTALLED_WITH_AUR: print("Arch-based distribution with AUR support detected. Please refresh auto-cpufreq using your AUR helper.") else: - for arg in sys.argv: - if arg.startswith("--update="): - update_flag_present = True - custom_dir = arg.split("=", 1)[1] - args_to_remove.append(arg) - break # Found it, no need to check further - - # Remove the parsed arguments - # This prevents them from being misinterpreted later if code relies on sys.argv directly - _original_argv = sys.argv[:] # Make a copy if needed elsewhere - sys.argv = [arg for arg in sys.argv if arg not in args_to_remove] - - - if update_flag_present: - if IS_INSTALLED_WITH_SNAP: - print("Detected auto-cpufreq was installed using snap") - print("Please update using snap package manager, i.e: `sudo snap refresh auto-cpufreq`.") - elif IS_INSTALLED_WITH_AUR: - print("Arch-based distribution with AUR support detected. Please refresh auto-cpufreq using your AUR helper.") - else: - is_new_update = check_for_update() - if not is_new_update: return - ans = input(f"Update source will be placed in '{custom_dir}'.\nDo you want to update auto-cpufreq to the latest release? [Y/n]: ").strip().lower() - - if ans in ['', 'y', 'yes']: - # Ensure directory exists - os.makedirs(custom_dir, exist_ok=True) - auto_cpufreq_subdir = os.path.join(custom_dir, "auto-cpufreq") - if os.path.isdir(auto_cpufreq_subdir): - print(f"Removing existing source sub-directory: {auto_cpufreq_subdir}") - try: - rmtree(auto_cpufreq_subdir) - except OSError as e: - print(f"Error removing directory {auto_cpufreq_subdir}: {e}") - print("Update aborted.") - return # Stop update if cleanup fails - - print("Removing existing installation (if any)...") - remove_daemon() # Call remove logic first - # remove_complete_msg() # Optional message - print(f"Downloading new version to {custom_dir}...") - new_update(custom_dir) # Download the update - print("Running installer for the updated version...") - # Use subprocess.run to call the install command of the main script - install_result = run([_original_argv[0], "--install"], check=False) # Use original script path - if install_result.returncode == 0: - print("\nUpdate and installation successful.") - run([_original_argv[0], "--version"]) - else: - print("\nError during installation after update. Please check messages above.") - else: - print("Update aborted.") - # else: # If neither --update nor --update= was found - # Potentially show help or an error if update was expected - # print("Update command not used correctly.") - # run([_original_argv[0], "--help"]) - + is_new_update = check_for_update() + if not is_new_update: return + ans = input("Do you want to update auto-cpufreq to the latest release? [Y/n]: ").strip().lower() + if not os.path.exists(custom_dir): os.makedirs(custom_dir) + if os.path.exists(os.path.join(custom_dir, "auto-cpufreq")): rmtree(os.path.join(custom_dir, "auto-cpufreq")) + if ans in ['', 'y', 'yes']: + remove_daemon() + remove_complete_msg() + new_update(custom_dir) + print("enabling daemon") + run(["auto-cpufreq", "--install"]) + print("auto-cpufreq is installed with the latest version") + run(["auto-cpufreq", "--version"]) + else: print("Aborted") elif remove: root_check() if IS_INSTALLED_WITH_SNAP: - run("snapctl stop auto-cpufreq", shell=True, check=False) - run("snapctl set daemon=disabled", shell=True, check=True) - # run("snapctl disable auto-cpufreq", shell=True, check=True) # Deprecated? Use stop --disable - run("snapctl stop --disable auto-cpufreq", shell=True, check=True) # Correct way to stop and disable + run("snapctl set daemon=disabled", shell=True) + run("snapctl stop --disable auto-cpufreq", shell=True) + if auto_cpufreq_stats_path.exists(): + if auto_cpufreq_stats_file is not None: + auto_cpufreq_stats_file.close() - # Check if stats path/file variables exist before using them - # These should be available from 'from auto_cpufreq.core import *' - if 'auto_cpufreq_stats_path' in globals() and auto_cpufreq_stats_path.exists(): - # Close file handle safely - if 'auto_cpufreq_stats_file' in globals() and auto_cpufreq_stats_file is not None: - if not auto_cpufreq_stats_file.closed: - try: - auto_cpufreq_stats_file.close() - except Exception as e: - print(f"Warning: Could not close stats file handle: {e}") - # Set to None after closing or if already closed - # auto_cpufreq_stats_file = None # Modifying imported var might be tricky - - # Remove the file - try: - auto_cpufreq_stats_path.unlink() - print(f"Removed stats file: {auto_cpufreq_stats_path}") - except OSError as e: - print(f"Warning: Could not remove stats file {auto_cpufreq_stats_path}: {e}") - - # Reminders + auto_cpufreq_stats_path.unlink() + # ToDo: + # {the following snippet also used in --update, update it there too(if required)} + # * undo bluetooth boot disable gnome_power_rm_reminder_snap() - bluetooth_on_notif_snap() - else: - remove_daemon() # Defined in core.py, handles service removal and cleanup including stats file + else: remove_daemon() remove_complete_msg() elif stats: not_running_daemon_check() @@ -301,27 +224,20 @@ def main(monitor, live, daemon, install, update, remove, force, config, stats, g else: gnome_power_detect() tlp_service_detect() - - # Determine if confirmation is needed - needs_confirmation = IS_INSTALLED_WITH_SNAP or tlp_stat_exists - # Check gnome_power_status only if relevant variables exist - if not IS_INSTALLED_WITH_SNAP and 'systemctl_exists' in globals() and systemctl_exists and 'gnome_power_status' in locals() and not bool(gnome_power_status): - needs_confirmation = True - - if needs_confirmation: + + if IS_INSTALLED_WITH_SNAP or tlp_stat_exists or (systemctl_exists and not bool(gnome_power_status)): try: input("press Enter to continue or Ctrl + c to exit...") except KeyboardInterrupt: - # conf.notifier might not be started for stats mode + conf.notifier.stop() sys.exit(0) - - monitor_instance = SystemMonitor(type=ViewType.STATS) - monitor_instance.run() + + monitor = SystemMonitor(type=ViewType.STATS) + monitor.run() elif get_state: not_running_daemon_check() override = get_override() print(override) - elif bluetooth_boot_off: if IS_INSTALLED_WITH_SNAP: footer() @@ -343,6 +259,7 @@ def main(monitor, live, daemon, install, update, remove, force, config, stats, g bluetooth_enable() footer() elif debug: + # ToDo: add status of GNOME Power Profile service status config_info_dialog() root_check() battery_get_thresholds() @@ -356,11 +273,7 @@ def main(monitor, live, daemon, install, update, remove, force, config, stats, g python_info() print() device_info() - # Check charging status function exists and call it - if 'charging' in globals() and callable(charging): - print(f"Battery is: {'' if charging() else 'dis'}charging") - else: - print("Battery status unavailable.") + print(f"Battery is: {'' if charging() else 'dis'}charging") print() app_res_use() get_load() @@ -378,16 +291,5 @@ def main(monitor, live, daemon, install, update, remove, force, config, stats, g print("Show your appreciation by donating!") print(GITHUB+"#donate") footer() - # else: # Optional: Handle unrecognized flags if not caught by click - # print(f"Error: Unrecognized arguments.") - # run([_original_argv[0], "--help"]) - - -if __name__ == "__main__": - try: - import click - except ImportError: - print("Error: Required dependency 'click' not found. Please install it (e.g., pip install click)") - sys.exit(1) - # Call main entry point - main() \ No newline at end of file + +if __name__ == "__main__": main() \ No newline at end of file