Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework config and reload config on file change/creation/deletion #663

Merged
merged 19 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions auto_cpufreq/battery_scripts/battery.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#!/usr/bin/env python3
import subprocess
from auto_cpufreq.core import get_config, root_check
from auto_cpufreq.core import root_check

from auto_cpufreq.battery_scripts.thinkpad import *
from auto_cpufreq.battery_scripts.ideapad import *
from auto_cpufreq.utils.config import config


def lsmod(module):
Expand All @@ -16,7 +17,7 @@ def lsmod(module):


def battery_start_threshold():
conf = get_config()
conf = config.get_config()
if conf.has_option("battery", "start_threshold"):
start_threshold = conf["battery"]["start_threshold"]
return int(start_threshold)
Expand All @@ -25,7 +26,7 @@ def battery_start_threshold():


def battery_stop_threshold():
conf = get_config()
conf = config.get_config()
if conf.has_option("battery", "stop_threshold"):
stop_threshold = conf["battery"]["stop_threshold"]
return int(stop_threshold)
Expand All @@ -35,7 +36,7 @@ def battery_stop_threshold():

def battery_setup():
root_check()
conf = get_config()
conf = config.get_config()
if conf.has_option("battery", "enable_thresholds"):
if conf["battery"]["enable_thresholds"] == "true":
if lsmod("thinkpad_acpi"):
Expand All @@ -53,7 +54,7 @@ def battery_setup():


def battery_get_thresholds():
conf = get_config()
conf = config.get_config()
if conf.has_option("battery", "enable_thresholds"):
if conf["battery"]["enable_thresholds"] == "true":
print("-" * 30)
Expand Down
4 changes: 3 additions & 1 deletion 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
# cli
@click.command()
@click.option("--monitor", is_flag=True, help="Monitor and see suggestions for CPU optimizations")
Expand All @@ -40,8 +41,9 @@
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
conf.set_path(config)
def config_info_dialog():
if get_config(config) and hasattr(get_config, "using_cfg_file"):
if conf.has_config():
print("\nUsing settings defined in " + config + " file")

# set governor override unless None or invalid
Expand Down
18 changes: 4 additions & 14 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,16 +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=""):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that this is gone, I fail to understand where the "config" file is picked up with _Config class and pyinotify. Could you please point me to line where this is happening?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the config instance is imported from the config.py file and you can access the config by calling config.get_config(). This is seen in core.py in all of the set functions (where just get_config()) used to be

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):
with open(governor_override_state, "rb") as store:
Expand Down Expand Up @@ -638,7 +628,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 @@ -679,7 +669,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 @@ -902,7 +892,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.
40 changes: 40 additions & 0 deletions auto_cpufreq/utils/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from configparser import ConfigParser, ParsingError
from auto_cpufreq.utils.config_event_handler import ConfigEventHandler
import pyinotify
import os

class _Config:
def __init__(self) -> None:
self.path: str = ""
self._config: ConfigParser = ConfigParser()
self.watch_manager: pyinotify.WatchManager = pyinotify.WatchManager()
self.config_handler = ConfigEventHandler(self)

# check for file changes using threading
notifier: pyinotify.ThreadedNotifierNotifier = pyinotify.ThreadedNotifier(
self.watch_manager, self.config_handler)
notifier.start()

def set_path(self, path: str) -> None:
self.path = path;
mask = pyinotify.IN_CREATE | pyinotify.IN_DELETE | pyinotify.IN_MODIFY
self.watch_manager.add_watch(os.path.dirname(path), mask=mask)
if os.path.isfile(path):
self.update_config()


def has_config(self) -> bool:
return os.path.isfile(self.path)

def get_config(self) -> ConfigParser:
return self._config

def update_config(self) -> None:
# create new ConfigParser to prevent old data from remaining
self._config = ConfigParser()
try:
self._config.read(self.path)
except ParsingError as e:
print(f"The following error occured while parsing the config file: \n{e}")

config = _Config()
20 changes: 20 additions & 0 deletions auto_cpufreq/utils/config_event_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import pyinotify

class ConfigEventHandler(pyinotify.ProcessEvent):
def __init__(self, config) -> None:
self.config = config

# activates when file is modified
shadeyg56 marked this conversation as resolved.
Show resolved Hide resolved
def process_IN_MODIFY(self, event: pyinotify.Event) -> None:
if event.pathname.rstrip("~") == self.config.path:
self.config.update_config()

# activates when file is deleted
def process_IN_DELETE(self, event: pyinotify.Event) -> None:
if event.pathname.rstrip("~") == self.config.path:
self.config.update_config()

# activates when file is created
def process_IN_CREATE(self, event: pyinotify.Event) -> None:
if event.pathname.rstrip("~") == self.config.path:
self.config.update_config()
2 changes: 1 addition & 1 deletion nix/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ python310Packages.buildPythonPackage {

buildInputs = with pkgs; [gtk3 python310Packages.poetry-core];

propagatedBuildInputs = with python310Packages; [requests pygobject3 click distro psutil setuptools poetry-dynamic-versioning];
propagatedBuildInputs = with python310Packages; [requests pygobject3 click distro psutil setuptools poetry-dynamic-versioning pyinotify];

doCheck = false;
pythonImportsCheck = ["auto_cpufreq"];
Expand Down
14 changes: 12 additions & 2 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ click = "^8.1.0"
distro = "^1.8.0"
requests = "^2.31.0"
PyGObject = "^3.46.0"
pyinotify = "^0.9.6"

[tool.poetry.group.dev.dependencies]
poetry = "^1.6.1"
Expand Down