Skip to content

Commit

Permalink
Merge pull request #194 from AndreWohnsland/dev
Browse files Browse the repository at this point in the history
Make migrator always respect local config
  • Loading branch information
AndreWohnsland authored Oct 19, 2024
2 parents c846001 + e836153 commit db2e45b
Show file tree
Hide file tree
Showing 19 changed files with 108 additions and 65 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
- name: Update version in pyproject.toml
run: |
sed -i "s/version = \".*\"/version = \"${{ steps.get_version.outputs.version }}\"/" pyproject.toml
sed -i "/^version = \".*\"$/s/version = \".*\"/version = \"${{ steps.get_version.outputs.version }}\"/" pyproject.toml
- name: Commit changes
run: |
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ allow-direct-references = true
# don't check import order in the migration script
line-length = 120
exclude = ["ui_elements", "addon_skeleton.py"]
target-version = "1.38.1"
target-version = "py39"

[tool.ruff.lint]
extend-safe-fixes = [
Expand Down
9 changes: 9 additions & 0 deletions src/config/config_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,17 @@ def __init__(self) -> None:
"EXP_MAKER_UNIT": StringType(),
"EXP_MAKER_FACTOR": FloatType([build_number_limiter(0.01, 100)]),
}

def read_local_config(self, update_config: bool = False):
"""Read the local config file and set the values if they are valid.
Might throw a ConfigError if the config is not valid.
Ignore the error if the file is not found, as it is created at the first start of the program.
"""
with contextlib.suppress(FileNotFoundError):
self._read_config()
if update_config:
self.sync_config_to_file()

def sync_config_to_file(self):
"""Write the config attributes to the config file.
Expand Down
2 changes: 1 addition & 1 deletion src/dialog_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def handle_dialog_outcome(result: bool):

def password_prompt(
self,
right_password: int = cfg.UI_MASTERPASSWORD,
right_password: int,
header_type: Literal["master", "maker"] = "master",
):
"""Open a password prompt, return if successful entered password.
Expand Down
5 changes: 4 additions & 1 deletion src/error_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ def wrapper(*args, **kwargs):
msg = f"The function {func.__name__} did run into an error at module: {module} function {fname} in row: {row}!" # noqa
_logger.log_exception(msg)
time_print(msg)
MACHINE.close_all_pumps()
try:
MACHINE.close_all_pumps()
except Exception as e:
_logger.log_exception(f"Error while closing the pumps: {e}")
raise
return result

Expand Down
18 changes: 10 additions & 8 deletions src/machine/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,15 @@ class MachineController:
"""Controller Class for all Machine related Pin routines."""

def __init__(self):
super().__init__()
self.pin_controller = self._chose_controller()
self._led_controller = LedController(self.pin_controller)
self._reverter = Reverter(self.pin_controller)
# Time for print intervals, need to remember the last print time
self._print_time = 0.0

def init_machine(self):
self._pin_controller = self._chose_controller()
self._led_controller = LedController(self._pin_controller)
self._reverter = Reverter(self._pin_controller, cfg.MAKER_PUMP_REVERSION, cfg.MAKER_REVERSION_PIN)
self.set_up_pumps()

def _chose_controller(self) -> PinController:
"""Select the controller class for the Pin."""
if cfg.MAKER_BOARD == "RPI":
Expand Down Expand Up @@ -185,14 +187,14 @@ def set_up_pumps(self):
used_config = cfg.PUMP_CONFIG[: cfg.MAKER_NUMBER_BOTTLES]
active_pins = [x.pin for x in used_config]
time_print(f"<i> Initializing Pins: {active_pins}")
self.pin_controller.initialize_pin_list(active_pins)
self._pin_controller.initialize_pin_list(active_pins)
self._reverter.initialize_pin()
atexit.register(self.cleanup)

def _start_pumps(self, pin_list: list[int], print_prefix: str = ""):
"""Informs and opens all given pins."""
time_print(f"{print_prefix}<o> Opening Pins: {pin_list}")
self.pin_controller.activate_pin_list(pin_list)
self._pin_controller.activate_pin_list(pin_list)

def close_all_pumps(self):
"""Close all pins connected to the pumps."""
Expand All @@ -203,12 +205,12 @@ def close_all_pumps(self):
def cleanup(self):
"""Cleanup for shutdown the machine."""
self.close_all_pumps()
self.pin_controller.cleanup_pin_list()
self._pin_controller.cleanup_pin_list()

def _stop_pumps(self, pin_list: list[int], print_prefix: str = ""):
"""Informs and closes all given pins."""
time_print(f"{print_prefix}<x> Closing Pins: {pin_list}")
self.pin_controller.close_pin_list(pin_list)
self._pin_controller.close_pin_list(pin_list)

def default_led(self):
"""Turn the LED on."""
Expand Down
4 changes: 1 addition & 3 deletions src/machine/gpio_factory.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Module to create the according GPIO controller for the appropriate Board."""

from src.config.config_manager import CONFIG as cfg
from src.machine.generic_board import GenericGPIO
from src.machine.interface import GPIOController
from src.machine.raspberry import RaspberryGPIO
Expand All @@ -11,12 +10,11 @@ def __init__(self, inverted: bool) -> None:
# global general inverted status
self.inverted = inverted

def generate_gpio(self, inverted: bool, pin: int) -> GPIOController:
def generate_gpio(self, inverted: bool, pin: int, board: str) -> GPIOController:
"""Return the appropriate GPIO.
Option to specific invert one GPIO relative to general setting.
"""
board = cfg.MAKER_BOARD
# using xor here to created the right inverted status
is_inverted = self.inverted ^ inverted
if board == "RPI":
Expand Down
16 changes: 8 additions & 8 deletions src/machine/leds.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

class LedController:
def __init__(self, pin_controller: PinController) -> None:
self.pin_controller = pin_controller
self._pin_controller = pin_controller
self.pins = cfg.LED_PINS
enabled = len(cfg.LED_PINS) > 0
self.controllable = cfg.LED_IS_WS and MODULE_AVAILABLE
Expand All @@ -34,7 +34,7 @@ def __init__(self, pin_controller: PinController) -> None:
return
# If not controllable use normal LEDs
if not cfg.LED_IS_WS:
self.led_list = [_normalLED(pin, self.pin_controller) for pin in self.pins]
self.led_list = [_normalLED(pin, self._pin_controller) for pin in self.pins]
return
# If controllable try to set up the WS281x LEDs
try:
Expand Down Expand Up @@ -76,21 +76,21 @@ def turn_off(self) -> None:


class _normalLED(_LED):
def __init__(self, pin: int, pin_controller: PinController) -> None:
def __init__(self, pin: int, _pin_controller: PinController) -> None:
self.pin = pin
self.pin_controller = pin_controller
self.pin_controller.initialize_pin_list([self.pin])
self._pin_controller = _pin_controller
self._pin_controller.initialize_pin_list([self.pin])

def __del__(self):
self.pin_controller.cleanup_pin_list([self.pin])
self._pin_controller.cleanup_pin_list([self.pin])

def turn_on(self):
"""Turn the LEDs on."""
self.pin_controller.activate_pin_list([self.pin])
self._pin_controller.activate_pin_list([self.pin])

def turn_off(self):
"""Turn the LEDs off."""
self.pin_controller.close_pin_list([self.pin])
self._pin_controller.close_pin_list([self.pin])

def preparation_start(self):
"""Turn the LED on during preparation."""
Expand Down
12 changes: 6 additions & 6 deletions src/machine/reverter.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
from src.config.config_manager import CONFIG as cfg
from src.machine.interface import PinController
from src.utils import time_print


class Reverter:
def __init__(self, pin_controller: PinController):
def __init__(self, pin_controller: PinController, use_reversion: bool, revert_pin: int):
self._pin_controller = pin_controller
# only init if reversion is enabled, otherwise it may be an invalid pin
self.revert_pin = cfg.MAKER_REVERSION_PIN
self.use_reversion = use_reversion
self.revert_pin = revert_pin

def initialize_pin(self):
if cfg.MAKER_PUMP_REVERSION:
if self.use_reversion:
time_print(f"Initializing Reversion Pin: {self.revert_pin}")
self._pin_controller.initialize_pin_list([self.revert_pin])

def revert_on(self):
"""Reverts the pump to be inverted."""
if not cfg.MAKER_PUMP_REVERSION:
if not self.use_reversion:
return
self._pin_controller.activate_pin_list([self.revert_pin])

def revert_off(self):
"""Disables the reversion pin."""
if not cfg.MAKER_PUMP_REVERSION:
if not self.use_reversion:
return
self._pin_controller.close_pin_list([self.revert_pin])
17 changes: 12 additions & 5 deletions src/migration/migrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import yaml

from src import FUTURE_PYTHON_VERSION, __version__
from src.config.config_types import PumpConfig
from src.filepath import CUSTOM_CONFIG_FILE, CUSTOM_STYLE_FILE, CUSTOM_STYLE_SCSS, VERSION_FILE
from src.logger_handler import LoggerHandler
from src.migration.update_data import (
Expand Down Expand Up @@ -228,12 +227,20 @@ def _combine_pump_setting_into_one_config():
if configuration is None:
return
# get the value from the config, if not exists fall back to default
pump_pins = configuration.get("PUMP_PINS", [14, 15, 18, 23, 24, 25, 8, 7, 17, 27])
pump_volume_flow = configuration.get("PUMP_VOLUMEFLOW", [30.0] * 10)
pump_pins = configuration.get("PUMP_PINS")
if pump_pins is None:
pump_pins = [14, 15, 18, 23, 24, 25, 8, 7, 17, 27]
_logger.info("No pump pins found in config, using fallback pins")
pump_volume_flow = configuration.get("PUMP_VOLUMEFLOW")
if pump_volume_flow is None:
pump_volume_flow = [30.0] * len(pump_pins)
_logger.info("No pump volume flow found in config, using fallback volume flow")
tube_volume = configuration.get("MAKER_TUBE_VOLUME", 0)
pump_config = []
_logger.info(f"Using for migration: {tube_volume=}, {pump_pins=}, {pump_volume_flow=}")
pump_config: list[dict] = []
# we just read in the plain dict but not the classes in the migrator, so keep this in mind.
for pin, volume_flow in zip(pump_pins, pump_volume_flow):
pump_config.append(PumpConfig(pin, volume_flow, tube_volume))
pump_config.append({"pin": pin, "volume_flow": volume_flow, "tube_volume": tube_volume})
configuration["PUMP_CONFIG"] = pump_config
with open(CUSTOM_CONFIG_FILE, "w", encoding="UTF-8") as stream:
yaml.dump(configuration, stream, default_flow_style=False)
Expand Down
5 changes: 3 additions & 2 deletions src/programs/calibration.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ def __init__(self, standalone: bool):
super().__init__()
self.setupUi(self)
self.setWindowFlags(Qt.Window | Qt.CustomizeWindowHint | Qt.WindowStaysOnTopHint) # type: ignore
if standalone:
cfg.read_local_config()
MACHINE.init_machine()
# Connect the Button
bottles = cfg.MAKER_NUMBER_BOTTLES
self.PB_start.clicked.connect(self.output_volume)
Expand All @@ -31,8 +34,6 @@ def __init__(self, standalone: bool):
self.showFullScreen()
DP_CONTROLLER.inject_stylesheet(self)
DP_CONTROLLER.set_display_settings(self)
if standalone:
MACHINE.set_up_pumps()
logger.log_start_program("calibration")

def output_volume(self):
Expand Down
15 changes: 14 additions & 1 deletion src/programs/cli.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# pylint: disable=unused-argument
import os
import sys
from pathlib import Path
from typing import Optional

Expand All @@ -8,6 +9,9 @@
from src import PROJECT_NAME
from src.config.config_manager import CONFIG as cfg
from src.config.config_manager import show_start_message, version_callback
from src.config.errors import ConfigError
from src.filepath import CUSTOM_CONFIG_FILE
from src.logger_handler import LoggerHandler
from src.migration.update_data import add_new_recipes_from_default_db
from src.programs.addons import ADDONS, generate_addon_skeleton
from src.programs.calibration import run_calibration
Expand All @@ -17,6 +21,7 @@
from src.programs.microservice_setup import LanguageChoice, setup_service, setup_teams
from src.utils import generate_custom_style_file, start_resource_tracker, time_print

_logger = LoggerHandler("cocktailberry")
cli = typer.Typer(add_completion=False)


Expand All @@ -42,7 +47,15 @@ def main(
show_start_message(displayed_name)
start_resource_tracker()
ADDONS.setup_addons()
cfg.sync_config_to_file()
# Load the config file and check for errors, update the config (sync new values if not present)
try:
cfg.read_local_config(update_config=True)
except ConfigError as e:
_logger.error(f"Config Error: {e}")
_logger.log_exception(e)
time_print(f"Config Error: {e}, please check the config file.")
time_print(f"You can edit the file at: {CUSTOM_CONFIG_FILE}")
sys.exit(1)
if debug:
os.environ.setdefault("DEBUG_MS", "True")
time_print("Using debug mode")
Expand Down
3 changes: 2 additions & 1 deletion src/tabs/ingredients.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
This includes all functions for the Lists, DB and Buttons/Dropdowns.
"""

from src.config.config_manager import CONFIG as cfg
from src.database_commander import DB_COMMANDER
from src.display_controller import DP_CONTROLLER
from src.error_handler import logerror
Expand Down Expand Up @@ -123,7 +124,7 @@ def delete_ingredient(w):
return
if not DP_CONTROLLER.ask_to_delete_x(selected_ingredient):
return
if not DP_CONTROLLER.password_prompt():
if not DP_CONTROLLER.password_prompt(cfg.UI_MASTERPASSWORD):
return

# Check if still used at a bottle or within a recipe
Expand Down
3 changes: 2 additions & 1 deletion src/tabs/recipes.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from collections import Counter

from src.config.config_manager import CONFIG as cfg
from src.database_commander import DB_COMMANDER
from src.display_controller import DP_CONTROLLER
from src.error_handler import logerror
Expand Down Expand Up @@ -198,7 +199,7 @@ def delete_recipe(w):
return
if not DP_CONTROLLER.ask_to_delete_x(recipe_name):
return
if not DP_CONTROLLER.password_prompt():
if not DP_CONTROLLER.password_prompt(cfg.UI_MASTERPASSWORD):
return

DB_COMMANDER.delete_recipe(recipe_name)
Expand Down
Loading

0 comments on commit db2e45b

Please sign in to comment.