Skip to content

Commit

Permalink
Rework config and reload config on file change/creation/deletion (#663)
Browse files Browse the repository at this point in the history
* add config.py and config_event_handler.py
also introduces the utils folder

* update config imports and variables

* add 'pyinotify' dependency

* config: check for changes using threading

* config: handle errors and new eventsx

* config: set_path even if file doesn't exist and make new ConfigParser on every update

* fix get_config call

* config: check for changes on moved file

* call notifier.start() manually to prevent hanging

* config: update comments

* battery: fix config imports

* config: fix config deletion detection

* Add load from user config in XDG_CONFIG_HOME if available (#672)

* Add load from user config from in XDG_CONFIG_HOME if available

This update introduces the flexibility to load the configuration file from
multiple locations, prioritizing user preferences and system standards.
Previously, the configuration was strictly read from a hardcoded
system path (`/etc/auto-cpufreq.conf`). Now, the application first checks if the
user has specified a configuration file path via command line arguments. If not,
it looks for a configuration file in the user's config
directory (`$XDG_CONFIG_HOME/auto-cpufreq/auto-cpufreq.conf`). If neither is
found, it defaults to the original system-wide configuration file.

This allows users to add their auto-cpufreq configuration to their dotfiles.

* If --config is set but invalid, exit with error

* Remove redundant empty string check on config file path

* Remove duplicate isfile check for config path

See also: #672 (comment)

* Update configuration options in README

See also: #672

* config: move find_config_file function and fix finding home directory

* auto_cpufreq: fix hanging on --daemon, --live, and --monitor

* swap pyinotify for patched version

---------

Co-authored-by: Steven Braun <steven.braun.mz@gmail.com>
  • Loading branch information
shadeyg56 and braun-steven committed Apr 30, 2024
1 parent 8bb7478 commit 0815e7e
Show file tree
Hide file tree
Showing 13 changed files with 206 additions and 72 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,11 @@ See [`--force` flag](#overriding-governor) for more info.

You can configure separate profiles for the battery and power supply. These profiles will let you pick which governor to use, as well as how and when turbo boost is enabled. The possible values for turbo boost behavior are `always`, `auto`, and `never`. The default behavior is `auto`, which only activates turbo during high load.

By default, auto-cpufreq does not use the config file! If you wish to use it, the location where it needs to be placed to be read automatically is: `/etc/auto-cpufreq.conf`
By default, auto-cpufreq does not use a config file. If you wish to configure auto-cpufreq statically, we look for a configuration file in the following order:

1. Commandline argument: `--config <FILE>` if passed as commandline argument to `auto-cpufreq`
2. User-specific configuration: `$XDG_CONFIG_HOME/auto-cpufreq/auto-cpufreq.conf`
3. System-wide configuration: `/etc/auto-cpufreq.conf`

#### Example config file contents
```python
Expand Down
1 change: 1 addition & 0 deletions auto_cpufreq/battery_scripts/battery.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def battery_setup():


def battery_get_thresholds():

if lsmod("thinkpad_acpi"):
thinkpad_print_thresholds()

Expand Down
14 changes: 7 additions & 7 deletions auto_cpufreq/battery_scripts/ideapad_acpi.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
import os
import subprocess
from auto_cpufreq.core import get_config
from auto_cpufreq.utils.config import config


def set_battery(value, mode, bat):
Expand All @@ -14,9 +14,9 @@ def set_battery(value, mode, bat):

def get_threshold_value(mode):

config = get_config()
if config.has_option("battery", f"{mode}_threshold"):
return config["battery"][f"{mode}_threshold"]
conf = config.get_config()
if conf.has_option("battery", f"{mode}_threshold"):
return conf["battery"][f"{mode}_threshold"]
else:
if mode == "start":

Expand All @@ -26,11 +26,11 @@ def get_threshold_value(mode):


def ideapad_acpi_setup():
config = get_config()
conf = config.get_config()

if not config.has_option("battery", "enable_thresholds"):
if not conf.has_option("battery", "enable_thresholds"):
return
if not config["battery"]["enable_thresholds"] == "true":
if not conf["battery"]["enable_thresholds"] == "true":
return

battery_count = len([name for name in os.listdir(
Expand Down
20 changes: 10 additions & 10 deletions auto_cpufreq/battery_scripts/ideapad_laptop.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
import os
import subprocess
from auto_cpufreq.core import get_config
from auto_cpufreq.utils.config import config


def set_battery(value, mode, bat):
Expand All @@ -14,9 +14,9 @@ def set_battery(value, mode, bat):

def get_threshold_value(mode):

config = get_config()
if config.has_option("battery", f"{mode}_threshold"):
return config["battery"][f"{mode}_threshold"]
conf = config.get_config()
if conf.has_option("battery", f"{mode}_threshold"):
return conf["battery"][f"{mode}_threshold"]
else:
if mode == "start":
return 0
Expand Down Expand Up @@ -52,21 +52,21 @@ def check_conservation_mode():


def ideapad_laptop_setup():
config = get_config()
conf = config.get_config()

if not config.has_option("battery", "enable_thresholds"):
if not conf.has_option("battery", "enable_thresholds"):
return
if not config["battery"]["enable_thresholds"] == "true":
if not conf["battery"]["enable_thresholds"] == "true":
return

battery_count = len([name for name in os.listdir(
"/sys/class/power_supply/") if name.startswith('BAT')])

if config.has_option("battery", "ideapad_laptop_conservation_mode"):
if config["battery"]["ideapad_laptop_conservation_mode"] == "true":
if conf.has_option("battery", "ideapad_laptop_conservation_mode"):
if conf["battery"]["ideapad_laptop_conservation_mode"] == "true":
conservation_mode(1)
return
if config["battery"]["ideapad_laptop_conservation_mode"] == "false":
if conf["battery"]["ideapad_laptop_conservation_mode"] == "false":
conservation_mode(0)

if check_conservation_mode() is False:
Expand Down
14 changes: 7 additions & 7 deletions auto_cpufreq/battery_scripts/thinkpad.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
import os
import subprocess
from auto_cpufreq.core import get_config
from auto_cpufreq.utils.config import config


def set_battery(value, mode, bat):
Expand All @@ -14,9 +14,9 @@ def set_battery(value, mode, bat):

def get_threshold_value(mode):

config = get_config()
if config.has_option("battery", f"{mode}_threshold"):
return config["battery"][f"{mode}_threshold"]
conf = config.get_config()
if conf.has_option("battery", f"{mode}_threshold"):
return conf["battery"][f"{mode}_threshold"]
else:
if mode == "start":

Expand All @@ -26,11 +26,11 @@ def get_threshold_value(mode):


def thinkpad_setup():
config = get_config()
conf = config.get_config()

if not config.has_option("battery", "enable_thresholds"):
if not conf.has_option("battery", "enable_thresholds"):
return
if not config["battery"]["enable_thresholds"] == "true":
if not conf["battery"]["enable_thresholds"] == "true":
return

battery_count = len([name for name in os.listdir(
Expand Down
58 changes: 30 additions & 28 deletions auto_cpufreq/bin/auto_cpufreq.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from auto_cpufreq.core import *
from auto_cpufreq.power_helper import *
from auto_cpufreq.battery_scripts.battery import *
from auto_cpufreq.utils.config import config as conf, find_config_file
# cli
@click.command()
@click.option("--monitor", is_flag=True, help="Monitor and see suggestions for CPU optimizations")
Expand All @@ -28,7 +29,7 @@
@click.option(
"--config",
is_flag=False,
default="/etc/auto-cpufreq.conf",
required=False,
help="Use config file at defined path",
)
@click.option("--debug", is_flag=True, help="Show debug info (include when submitting bugs)")
Expand All @@ -40,9 +41,11 @@
def main(config, daemon, debug, update, install, remove, live, log, monitor, stats, version, donate, force, get_state, completions):

# display info if config file is used
config_path = find_config_file(config)
conf.set_path(config_path)
def config_info_dialog():
if get_config(config) and hasattr(get_config, "using_cfg_file"):
print("\nUsing settings defined in " + config + " file")
if conf.has_config():
print("\nUsing settings defined in " + config_path + " file")

# set governor override unless None or invalid
if force is not None:
Expand All @@ -67,60 +70,58 @@ def config_info_dialog():
if os.getenv("PKG_MARKER") == "SNAP" and dcheck == "enabled":
gnome_power_detect_snap()
tlp_service_detect_snap()
battery_setup()
while True:
footer()
gov_check()
cpufreqctl()
distro_info()
sysinfo()
set_autofreq()
countdown(2)
elif os.getenv("PKG_MARKER") != "SNAP":
gnome_power_detect()
tlp_service_detect()
battery_setup()
while True:
battery_setup()
conf.notifier.start()
while True:
try:
footer()
gov_check()
cpufreqctl()
distro_info()
sysinfo()
set_autofreq()
countdown(2)
else:
pass
#"daemon_not_found" is not defined
#daemon_not_found()
except KeyboardInterrupt:
break;
conf.notifier.stop()
elif monitor:
config_info_dialog()
root_check()
print('\nNote: You can quit monitor mode by pressing "ctrl+c"')
battery_setup()
battery_get_thresholds()
conf.notifier.start()
if os.getenv("PKG_MARKER") == "SNAP":
gnome_power_detect_snap()
tlp_service_detect_snap()
else:
gnome_power_detect()
tlp_service_detect()
while True:
time.sleep(1)
running_daemon_check()
footer()
gov_check()
cpufreqctl()
distro_info()
sysinfo()
mon_autofreq()
countdown(2)
try:
time.sleep(1)
running_daemon_check()
footer()
gov_check()
cpufreqctl()
distro_info()
sysinfo()
mon_autofreq()
countdown(2)
except KeyboardInterrupt:
break
conf.notifier.stop()
elif live:
root_check()
config_info_dialog()
print('\nNote: You can quit live mode by pressing "ctrl+c"')
time.sleep(1)
battery_setup()
battery_get_thresholds()
conf.notifier.start()
if os.getenv("PKG_MARKER") == "SNAP":
gnome_power_detect_snap()
tlp_service_detect_snap()
Expand All @@ -141,7 +142,8 @@ def config_info_dialog():
except KeyboardInterrupt:
gnome_power_start_live()
print("")
sys.exit()
break
conf.notifier.stop()
elif stats:
not_running_daemon_check()
config_info_dialog()
Expand Down
17 changes: 4 additions & 13 deletions auto_cpufreq/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import click
import pickle
import warnings
import configparser
# import pkg_resources
import importlib.metadata
from math import isclose
Expand All @@ -27,6 +26,7 @@

sys.path.append("../")
from auto_cpufreq.power_helper import *
from auto_cpufreq.utils.config import config

warnings.filterwarnings("ignore")

Expand Down Expand Up @@ -84,15 +84,6 @@ def file_stats():
auto_cpufreq_stats_file = open(auto_cpufreq_stats_path, "w")
sys.stdout = auto_cpufreq_stats_file

def get_config(config_file=""):
if not hasattr(get_config, "config"):
get_config.config = configparser.ConfigParser()

if os.path.isfile(config_file):
get_config.config.read(config_file)
get_config.using_cfg_file = True

return get_config.config

def get_override():
if os.path.isfile(governor_override_state):
Expand Down Expand Up @@ -645,7 +636,7 @@ def set_frequencies():
if not hasattr(set_frequencies, "min_limit"):
set_frequencies.min_limit = int(getoutput(f"cpufreqctl.auto-cpufreq --frequency-min-limit"))

conf = get_config()
conf = config.get_config()

for freq_type in frequency.keys():
value = None
Expand Down Expand Up @@ -686,7 +677,7 @@ def set_frequencies():

# set powersave and enable turbo
def set_powersave():
conf = get_config()
conf = config.get_config()
if conf.has_option("battery", "governor"):
gov = conf["battery"]["governor"]
else:
Expand Down Expand Up @@ -909,7 +900,7 @@ def mon_powersave():

# set performance and enable turbo
def set_performance():
conf = get_config()
conf = config.get_config()
if conf.has_option("charger", "governor"):
gov = conf["charger"]["governor"]
else:
Expand Down
Empty file added auto_cpufreq/utils/__init__.py
Empty file.
Loading

0 comments on commit 0815e7e

Please sign in to comment.