From ad45ee85107b55f9957104ae49c2e115ba78b0fe Mon Sep 17 00:00:00 2001 From: Jan Lindemann Date: Fri, 23 Jan 2026 14:54:27 +0100 Subject: [PATCH] jw.pkg.cmds.distro: Add directory Add the subdirectory structure for the distro subcommand. Signed-off-by: Jan Lindemann --- src/python/jw/pkg/cmds/CmdDistro.py | 49 ++++++++++++++++++++++++++ src/python/jw/pkg/cmds/__init__.py | 1 + src/python/jw/pkg/cmds/distro/Cmd.py | 44 +++++++++++++++++++++++ src/python/jw/pkg/cmds/distro/Makefile | 4 +++ 4 files changed, 98 insertions(+) create mode 100644 src/python/jw/pkg/cmds/CmdDistro.py create mode 100644 src/python/jw/pkg/cmds/distro/Cmd.py create mode 100644 src/python/jw/pkg/cmds/distro/Makefile diff --git a/src/python/jw/pkg/cmds/CmdDistro.py b/src/python/jw/pkg/cmds/CmdDistro.py new file mode 100644 index 00000000..fcbf2ca0 --- /dev/null +++ b/src/python/jw/pkg/cmds/CmdDistro.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- + +import re, sys +from argparse import ArgumentParser + +from ..App import App +from .Cmd import Cmd as CmdBase + +class CmdDistro(CmdBase): # export + + def __init__(self, parent: App) -> None: + self.__id = None + super().__init__(parent, 'distro', help="System package manager wrapper") + self._add_subcommands() + self.__interactive: bool|None = None + + @property + def distro_id(self): + if self.__id is None: + if self.app.args.id is not None: + self.__id = self.app.args.id + else: + os_release = '/etc/os-release' + with open(os_release, 'r') as file: + matches = re.findall(r'^ID="?([^"]+)"?$', file.read(), re.MULTILINE) + if len(matches) != 1: + raise Exception(f'Could not read "ID=" from "{os_release}"') + self.__id = matches[0] + return self.__id + + def add_arguments(self, p: ArgumentParser) -> None: + super().add_arguments(p) + p.add_argument('--id', default=None, help='Distribution ID (default is taken from /etc/os-release)') + p.add_argument('--interactive', choices=['true', 'false', 'auto'], default='false', help="Wait for user input or try to proceed unattended") + + @property + def interactive(self) -> bool: + if self.__interactive is None: + match self.app.args.interactive: + case 'true': + self.__interactive = True + case 'false': + self.__interactive = False + case 'auto': + self.__interactive = sys.stdin.isatty() + return self.__interactive + + async def _run(self, args): + raise Exception("Running with args", args) diff --git a/src/python/jw/pkg/cmds/__init__.py b/src/python/jw/pkg/cmds/__init__.py index 82cb3002..ea8e84ec 100644 --- a/src/python/jw/pkg/cmds/__init__.py +++ b/src/python/jw/pkg/cmds/__init__.py @@ -1 +1,2 @@ from .CmdProjects import CmdProjects +from .CmdDistro import CmdDistro diff --git a/src/python/jw/pkg/cmds/distro/Cmd.py b/src/python/jw/pkg/cmds/distro/Cmd.py new file mode 100644 index 00000000..4ec541bb --- /dev/null +++ b/src/python/jw/pkg/cmds/distro/Cmd.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- + +import os, importlib + +from ..Cmd import Cmd as Base +from ..CmdDistro import CmdDistro + +class Cmd(Base): # export + + def __init__(self, parent: CmdDistro, name: str, help: str) -> None: + super().__init__(parent, name, help) + self.__backend = None + + @property + def distro_id(self) -> str: + return self.parent.distro_id + + @property + def interactive(self) -> bool: + return self.parent.interactive + + @property + def _backend(self): + if self.__backend is None: + class_name = self.__class__.__name__[3:] # Get rid of "Cmd" + backend_id = self.parent.distro_id.lower().replace('-', '_') + match backend_id: + case 'ubuntu' | 'raspbian': + backend_id = 'debian' + case 'centos': + backend_id = 'redhat' + case 'opensuse_tumbleweed': + backend_id = 'suse' + module_name = ( + os.path.splitext(__name__)[0] + + '.backend.' + + backend_id + + '.' + + class_name + ) + module = importlib.import_module(module_name) + cls = getattr(module, class_name) + self.__backend = cls(self) + return self.__backend diff --git a/src/python/jw/pkg/cmds/distro/Makefile b/src/python/jw/pkg/cmds/distro/Makefile new file mode 100644 index 00000000..7a83c333 --- /dev/null +++ b/src/python/jw/pkg/cmds/distro/Makefile @@ -0,0 +1,4 @@ +TOPDIR = ../../../../../.. + +include $(TOPDIR)/make/proj.mk +include $(JWBDIR)/make/py-mod.mk