diff --git a/yafti/__init__.py b/yafti/__init__.py index 16c7447..e591c45 100644 --- a/yafti/__init__.py +++ b/yafti/__init__.py @@ -1,15 +1,2 @@ -""" -Copyright 2023 Marco Ceppi - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" +# Copyright 2023 Marco Ceppi +# SPDX-License-Identifier: Apache-2.0 diff --git a/yafti/__main__.py b/yafti/__main__.py index e5ba677..0dcb41d 100644 --- a/yafti/__main__.py +++ b/yafti/__main__.py @@ -1,18 +1,5 @@ -""" -Copyright 2023 Marco Ceppi - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" +# Copyright 2023 Marco Ceppi +# SPDX-License-Identifier: Apache-2.0 import logging from typing import Annotated @@ -21,9 +8,9 @@ import yaml import yafti.setup # noqa -from yafti import log +from yafti.core import log from yafti.app import Yafti -from yafti.parser import Config +from yafti.core.config import Config def run( diff --git a/yafti/app.py b/yafti/app.py index 105539f..a9c91c1 100644 --- a/yafti/app.py +++ b/yafti/app.py @@ -21,7 +21,7 @@ from gi.repository import Adw from pathlib import Path -from yafti.parser import Config, YaftiRunModes, YaftSaveState +from yafti.core.config import Config, YaftiRunModes, YaftSaveState from yafti.screen.window import Window diff --git a/yafti/cli/__init__.py b/yafti/cli/__init__.py new file mode 100644 index 0000000..e591c45 --- /dev/null +++ b/yafti/cli/__init__.py @@ -0,0 +1,2 @@ +# Copyright 2023 Marco Ceppi +# SPDX-License-Identifier: Apache-2.0 diff --git a/yafti/cli/app.py b/yafti/cli/app.py new file mode 100644 index 0000000..e591c45 --- /dev/null +++ b/yafti/cli/app.py @@ -0,0 +1,2 @@ +# Copyright 2023 Marco Ceppi +# SPDX-License-Identifier: Apache-2.0 diff --git a/yafti/core/__init__.py b/yafti/core/__init__.py new file mode 100644 index 0000000..e591c45 --- /dev/null +++ b/yafti/core/__init__.py @@ -0,0 +1,2 @@ +# Copyright 2023 Marco Ceppi +# SPDX-License-Identifier: Apache-2.0 diff --git a/yafti/abc.py b/yafti/core/abc.py similarity index 71% rename from yafti/abc.py rename to yafti/core/abc.py index e681487..ba057c5 100644 --- a/yafti/abc.py +++ b/yafti/core/abc.py @@ -1,18 +1,5 @@ -""" -Copyright 2023 Marco Ceppi - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" +# Copyright 2023 Marco Ceppi +# SPDX-License-Identifier: Apache-2.0 import asyncio from inspect import iscoroutinefunction @@ -26,7 +13,7 @@ class YaftiPlugin: async def _show_screen(condition): - from yafti.registry import PLUGINS + from yafti.core.registry import PLUGINS plugin_name = list(condition.keys())[0] plugin = PLUGINS.get(plugin_name) diff --git a/yafti/core/config.py b/yafti/core/config.py new file mode 100644 index 0000000..253d8c2 --- /dev/null +++ b/yafti/core/config.py @@ -0,0 +1,75 @@ +# Copyright 2023 Marco Ceppi +# SPDX-License-Identifier: Apache-2.0 + +from enum import Enum +from pathlib import Path +from typing import Optional, Any + +import yaml +from pydantic import BaseModel, BaseSettings +from pydantic.env_settings import SettingsSourceCallable + + +class ActionConfig(BaseModel): + pre: Optional[list[dict[str, str | dict]]] + post: Optional[list[dict[str, str | dict]]] + + +class ScreenConfig(BaseModel): + source: str + values: Optional[dict] + + +class YaftiRunModes(str, Enum): + changed = "run-on-change" + ignore = "run-once" + disable = "disabled" + + +class YaftSaveState(str, Enum): + always = "always" + end = "last-screen" + + +class YaftiProperties(BaseModel): + path: Optional[Path] = Path("~/.config/yafti/last-run") + mode: YaftiRunModes = YaftiRunModes.changed + save_state: YaftSaveState = YaftSaveState.always + + +class Config(BaseSettings): + title: str + properties: YaftiProperties = YaftiProperties() + actions: Optional[ActionConfig] + screens: Optional[dict[str, ScreenConfig]] # Screens are parsed per plugin + + class Config: + env_prefix = "yafti_" + env_nested_delimiter = "__" + env_file = "/etc/yafti.yml" + + @classmethod + def customise_sources( + cls, + init_settings: SettingsSourceCallable, + env_settings: SettingsSourceCallable, + file_secret_settings: SettingsSourceCallable, + ): + return ( + init_settings, + yaml_config_settings_source, + env_settings, + file_secret_settings, + ) + + +def yaml_config_settings_source(settings: BaseSettings) -> dict[str, Any]: + """ + A simple settings source that loads variables from a JSON file + at the project's root. + + Here we happen to choose to use the `env_file_encoding` from Config + when reading `config.json` + """ + encoding = settings.__config__.env_file_encoding + return yaml.safe_load(Path(settings.__config__.env_file).read_text(encoding)) diff --git a/yafti/log.py b/yafti/core/log.py similarity index 65% rename from yafti/log.py rename to yafti/core/log.py index 24f2f6d..913e41a 100644 --- a/yafti/log.py +++ b/yafti/core/log.py @@ -1,4 +1,8 @@ +# Copyright 2023 Marco Ceppi +# SPDX-License-Identifier: Apache-2.0 + import logging +import inspect __all__ = ["info", "warn", "error", "debug", "set_level"] @@ -6,7 +10,10 @@ def _fmt(msg: dict) -> str: - return " ".join([f"{k}={v}" for k, v in msg.items()]) + frame = inspect.stack()[-1] + mod = inspect.getmodule(frame[0]) + args = {"module": mod.__name__} | msg + return " ".join([f"{k}={v}" for k, v in args.items()]) def set_level(level): diff --git a/yafti/registry.py b/yafti/core/registry.py similarity index 100% rename from yafti/registry.py rename to yafti/core/registry.py diff --git a/yafti/gtk/__init__.py b/yafti/gtk/__init__.py new file mode 100644 index 0000000..e591c45 --- /dev/null +++ b/yafti/gtk/__init__.py @@ -0,0 +1,2 @@ +# Copyright 2023 Marco Ceppi +# SPDX-License-Identifier: Apache-2.0 diff --git a/yafti/parser.py b/yafti/parser.py deleted file mode 100644 index 0ec6754..0000000 --- a/yafti/parser.py +++ /dev/null @@ -1,63 +0,0 @@ -""" -Copyright 2023 Marco Ceppi - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" - -from enum import Enum -from pathlib import Path -from typing import Optional - -import yaml -from pydantic import BaseModel - - -class ActionConfig(BaseModel): - pre: Optional[list[dict[str, str | dict]]] - post: Optional[list[dict[str, str | dict]]] - - -class ScreenConfig(BaseModel): - source: str - values: Optional[dict] - - -class YaftiRunModes(str, Enum): - changed = "run-on-change" - ignore = "run-once" - disable = "disabled" - - -class YaftSaveState(str, Enum): - always = "always" - end = "last-screen" - - -class YaftiProperties(BaseModel): - path: Optional[Path] = Path("~/.config/yafti/last-run") - mode: YaftiRunModes = YaftiRunModes.changed - save_state: YaftSaveState = YaftSaveState.always - - -class Config(BaseModel): - title: str - properties: YaftiProperties = YaftiProperties() - actions: Optional[ActionConfig] - screens: Optional[dict[str, ScreenConfig]] # Screens are parsed per plugin - - -def parse(config_file: str) -> Config: - """Parse the YAML or JSON file passed and return a rendered Config object""" - with open(config_file) as f: - cfg = yaml.safe_load(f) - return Config.parse_obj(cfg) diff --git a/yafti/plugin/flatpak.py b/yafti/plugin/flatpak.py index a6a5580..fd7e732 100644 --- a/yafti/plugin/flatpak.py +++ b/yafti/plugin/flatpak.py @@ -1,20 +1,6 @@ +# Copyright 2023 Marco Ceppi +# SPDX-License-Identifier: Apache-2.0 """ -Copyright 2023 Marco Ceppi - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -\f - Install, remove, list, and manage flatpaks Configuration usage example: @@ -64,7 +50,7 @@ from pydantic import BaseModel, ValidationError, root_validator -from yafti.abc import YaftiPluginReturn +from yafti.core.abc import YaftiPluginReturn from yafti.plugin.run import Run diff --git a/yafti/plugin/run.py b/yafti/plugin/run.py index 473bbe6..a3755e8 100644 --- a/yafti/plugin/run.py +++ b/yafti/plugin/run.py @@ -1,20 +1,6 @@ +# Copyright 2023 Marco Ceppi +# SPDX-License-Identifier: Apache-2.0 """ -Copyright 2023 Marco Ceppi - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -/f - Run a command on the system Configuration usage example: @@ -38,7 +24,6 @@ from yafti.plugin.run import Run r = Run() r.exec(["/usr/bin/whoami"]) - f.exec(pkg="com.github.marcoceppi.PackageName", reinstall=True) r("/usr/bin/whoami") r(cmd="/usr/bin/whoami") @@ -54,11 +39,13 @@ from pydantic import validate_arguments -from yafti import log -from yafti.abc import YaftiPlugin, YaftiPluginReturn +from yafti.core import log +from yafti.core.abc import YaftiPlugin, YaftiPluginReturn class Run(YaftiPlugin): + """Run Plugin""" + async def exec(self, cmd: str) -> subprocess.CompletedProcess: log.debug("running command", cmd=cmd) @@ -70,6 +57,7 @@ async def exec(self, cmd: str) -> subprocess.CompletedProcess: elif which("flatpak-spawn"): cmd = f"flatpak-spawn --host {cmd}" + log.debug("running command", cmd=cmd, is_container=is_container) proc = await asyncio.create_subprocess_shell( cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE ) @@ -89,17 +77,6 @@ async def exec(self, cmd: str) -> subprocess.CompletedProcess: cmd, returncode=proc.returncode, stdout=stdout, stderr=stderr ) - async def install(self, package: str) -> YaftiPluginReturn: - """Execute a command on the host system - - Args: - package: The command to execute - - Returns: - An object containing the stdout and stderr from the command - """ - return await self.exec(package) - @validate_arguments async def __call__(self, cmd: list[str] | str) -> YaftiPluginReturn: log.debug("run called", cmd=cmd) diff --git a/yafti/screen/consent.py b/yafti/screen/consent.py index b22f466..756a438 100644 --- a/yafti/screen/consent.py +++ b/yafti/screen/consent.py @@ -38,8 +38,8 @@ import yafti.share from yafti import events -from yafti.abc import YaftiScreen, YaftiScreenConfig -from yafti.registry import PLUGINS +from yafti.core.abc import YaftiScreen, YaftiScreenConfig +from yafti.core.registry import PLUGINS _xml = """\ diff --git a/yafti/screen/console.py b/yafti/screen/console.py index aa6f738..ebe7193 100644 --- a/yafti/screen/console.py +++ b/yafti/screen/console.py @@ -1,6 +1,6 @@ from gi.repository import Gtk -from yafti.abc import YaftiScreen +from yafti.core.abc import YaftiScreen _xml = """\ diff --git a/yafti/screen/package/screen/install.py b/yafti/screen/package/screen/install.py index 8a82671..7837395 100644 --- a/yafti/screen/package/screen/install.py +++ b/yafti/screen/package/screen/install.py @@ -6,8 +6,8 @@ import yafti.share from yafti import events -from yafti import log -from yafti.abc import YaftiScreen +from yafti.core import log +from yafti.core.abc import YaftiScreen from yafti.screen.console import ConsoleScreen from yafti.screen.package.state import PackageScreenState @@ -84,7 +84,7 @@ def __init__( **kwargs, ): super().__init__(**kwargs) - from yafti.registry import PLUGINS + from yafti.core.registry import PLUGINS self.status_page.set_title(title) self.package_manager = PLUGINS.get(package_manager) diff --git a/yafti/screen/package/screen/package.py b/yafti/screen/package/screen/package.py index cce670f..1d954a4 100644 --- a/yafti/screen/package/screen/package.py +++ b/yafti/screen/package/screen/package.py @@ -4,7 +4,7 @@ import yafti.share from yafti import events -from yafti.abc import YaftiScreen, YaftiScreenConfig +from yafti.core.abc import YaftiScreen, YaftiScreenConfig from yafti.screen.package.models import PackageConfig, PackageGroupConfig from yafti.screen.package.screen import PackageInstallScreen, PackagePickerScreen from yafti.screen.package.state import PackageScreenState diff --git a/yafti/screen/package/screen/picker.py b/yafti/screen/package/screen/picker.py index a3cfea5..2ffb163 100644 --- a/yafti/screen/package/screen/picker.py +++ b/yafti/screen/package/screen/picker.py @@ -4,8 +4,8 @@ from gi.repository import Adw, Gtk from pydantic import BaseModel -from yafti import log -from yafti.abc import YaftiScreen +from yafti.core import log +from yafti.core.abc import YaftiScreen from yafti.screen.dialog import DialogBox from yafti.screen.package.state import PackageScreenState from yafti.screen.utils import find_parent diff --git a/yafti/screen/title.py b/yafti/screen/title.py index 2d2faaf..cd1827b 100644 --- a/yafti/screen/title.py +++ b/yafti/screen/title.py @@ -6,8 +6,8 @@ from gi.repository import Adw, Gtk from yafti import events -from yafti.abc import YaftiScreen, YaftiScreenConfig -from yafti.registry import PLUGINS +from yafti.core.abc import YaftiScreen, YaftiScreenConfig +from yafti.core.registry import PLUGINS _xml = """\ diff --git a/yafti/screen/window.py b/yafti/screen/window.py index 2a78649..5fcc00c 100644 --- a/yafti/screen/window.py +++ b/yafti/screen/window.py @@ -5,7 +5,7 @@ import yafti.share from yafti import events -from yafti.registry import SCREENS +from yafti.core.registry import SCREENS _xml = """\