cmds.distro: Move all modules to lib
Functions abstracting the distribution are not only needed in the context of the distro subcommand, but also by other code, so make the bulk of the code abstracting the distribution available in some place more universally useful than below cmds.distro. This commit leaves the source files mostly unchanged. They are only patched to fix import paths, so that functionality is preserved. Refactoring the code from command-line API to library API will be done by the next commit. Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
parent
f94a2ac037
commit
7e7cee6d11
45 changed files with 44 additions and 42 deletions
|
|
@ -2,13 +2,15 @@
|
|||
|
||||
import os, importlib
|
||||
|
||||
from ...lib.log import *
|
||||
from ...lib.distros.Util import Util
|
||||
|
||||
from ..Cmd import Cmd as Base
|
||||
from ..CmdDistro import CmdDistro
|
||||
from .backend.Util import Util
|
||||
|
||||
class Cmd(Base): # export
|
||||
|
||||
from .backend.Backend import Backend
|
||||
from ...lib.distros.Backend import Backend
|
||||
|
||||
def __init__(self, parent: CmdDistro, name: str, help: str) -> None:
|
||||
super().__init__(parent, name, help)
|
||||
|
|
@ -35,16 +37,16 @@ class Cmd(Base): # export
|
|||
backend_id = 'redhat'
|
||||
case 'opensuse' | 'suse':
|
||||
backend_id = 'suse'
|
||||
self.__backend_path = (
|
||||
os.path.splitext(__name__)[0]
|
||||
+ '.backend.'
|
||||
+ backend_id
|
||||
+ '.'
|
||||
)
|
||||
self.__backend_path = 'jw.pkg.lib.distros.' + backend_id + '.'
|
||||
return self.__backend_path
|
||||
|
||||
def _instantiate(self, name: str, *args, **kwargs):
|
||||
module = importlib.import_module(self._backend_path + name)
|
||||
module_path = self._backend_path + name
|
||||
try:
|
||||
module = importlib.import_module(module_path)
|
||||
except Exception as e:
|
||||
log(ERR, f'Failed to import module {module_path} ({str(e)})')
|
||||
raise
|
||||
cls = getattr(module, name)
|
||||
return cls(self, *args, **kwargs)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
from argparse import Namespace, ArgumentParser
|
||||
import re
|
||||
|
||||
from ...lib.Package import Package
|
||||
from ...lib.distros.BeSelect import BeSelect
|
||||
from ..CmdDistro import CmdDistro
|
||||
from .lib.Package import Package
|
||||
from .Cmd import Cmd
|
||||
from .backend.BeSelect import BeSelect
|
||||
|
||||
class CmdSelect(Cmd): # export
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from ..CmdPkg import CmdPkg as Parent
|
|||
|
||||
class Cmd(Base): # export
|
||||
|
||||
from ..backend.Backend import Backend
|
||||
from ....lib.distros.Backend import Backend
|
||||
|
||||
def __init__(self, parent: Parent, name: str, help: str) -> None:
|
||||
super().__init__(parent, name, help)
|
||||
|
|
|
|||
51
src/python/jw/pkg/lib/Package.py
Normal file
51
src/python/jw/pkg/lib/Package.py
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from typing import Any
|
||||
|
||||
meta_tags = [
|
||||
"name",
|
||||
"vendor",
|
||||
"packager",
|
||||
"url",
|
||||
"maintainer",
|
||||
]
|
||||
|
||||
class Package:
|
||||
|
||||
name: str = None
|
||||
vendor: str|None = None
|
||||
packager: str|None = None
|
||||
url: str|None = None
|
||||
maintainer: str|None = None
|
||||
|
||||
@classmethod
|
||||
def parse_spec_str(cls, spec: str, delimiter='|'):
|
||||
tags = spec.split(delimiter)
|
||||
if len(tags) != 5:
|
||||
raise ValueError(f'Invalid package spec string \"{spec}\"')
|
||||
return cls(name=tags[0], vendor=tags[1], packager=tags[2], url=tags[3], maintainer=tags[4])
|
||||
|
||||
@classmethod
|
||||
def parse_specs_str(cls, specs: str, delimiter='|'):
|
||||
ret: list[Package] = []
|
||||
for spec in specs.splitlines():
|
||||
ret.append(cls.parse_spec_str(spec))
|
||||
return ret
|
||||
|
||||
@classmethod
|
||||
def order_tags(cls, mapping: dict[str, Any]):
|
||||
ret: dict[str, Any] = {}
|
||||
for tag in meta_tags:
|
||||
ret[tag] = mapping.get(tag, '')
|
||||
return ret
|
||||
|
||||
def __init__(self, name: str, vendor: str|None=None, packager: str|None=None, url: str|None=None, maintainer: str|None=None):
|
||||
self.name = name
|
||||
self.vendor = vendor
|
||||
self.packager = packager
|
||||
self.url = url
|
||||
self.maintainer = maintainer
|
||||
|
||||
def __repr__(self) -> str:
|
||||
global meta_tags
|
||||
return '\n'.join([f'{key:<15}: {getattr(self, key)}' for key in meta_tags])
|
||||
29
src/python/jw/pkg/lib/distros/Backend.py
Normal file
29
src/python/jw/pkg/lib/distros/Backend.py
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ..util import run_sudo
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..Cmd import Cmd
|
||||
|
||||
class Backend:
|
||||
|
||||
def __init__(self, parent: Cmd):
|
||||
self.__parent = parent
|
||||
|
||||
async def _sudo(self, *args, **kwargs):
|
||||
return await run_sudo(*args, interactive=self.interactive, **kwargs)
|
||||
|
||||
@property
|
||||
def util(self):
|
||||
return self.__parent.util
|
||||
|
||||
@property
|
||||
def parent(self):
|
||||
return self.__parent
|
||||
|
||||
@property
|
||||
def interactive(self) -> bool:
|
||||
return self.__parent.interactive
|
||||
16
src/python/jw/pkg/lib/distros/BeDelete.py
Normal file
16
src/python/jw/pkg/lib/distros/BeDelete.py
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import abc
|
||||
from argparse import Namespace
|
||||
|
||||
from .Backend import Backend as Base
|
||||
from ..Cmd import Cmd as Parent
|
||||
|
||||
class BeDelete(Base):
|
||||
|
||||
def __init__(self, parent: Parent):
|
||||
super().__init__(parent)
|
||||
|
||||
@abc.abstractmethod
|
||||
async def run(self, args: Namespace) -> None:
|
||||
pass
|
||||
16
src/python/jw/pkg/lib/distros/BeDup.py
Normal file
16
src/python/jw/pkg/lib/distros/BeDup.py
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import abc
|
||||
from argparse import Namespace
|
||||
|
||||
from .Backend import Backend as Base
|
||||
from ..Cmd import Cmd as Parent
|
||||
|
||||
class BeDup(Base):
|
||||
|
||||
def __init__(self, parent: Parent):
|
||||
super().__init__(parent)
|
||||
|
||||
@abc.abstractmethod
|
||||
async def run(self, args: Namespace) -> None:
|
||||
pass
|
||||
16
src/python/jw/pkg/lib/distros/BeInstall.py
Normal file
16
src/python/jw/pkg/lib/distros/BeInstall.py
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import abc
|
||||
from argparse import Namespace
|
||||
|
||||
from .Backend import Backend as Base
|
||||
from ..Cmd import Cmd as Parent
|
||||
|
||||
class BeInstall(Base):
|
||||
|
||||
def __init__(self, parent: Parent):
|
||||
super().__init__(parent)
|
||||
|
||||
@abc.abstractmethod
|
||||
async def run(self, args: Namespace) -> None:
|
||||
pass
|
||||
31
src/python/jw/pkg/lib/distros/BePkg.py
Normal file
31
src/python/jw/pkg/lib/distros/BePkg.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import annotations
|
||||
from typing import Iterable, TYPE_CHECKING
|
||||
|
||||
import abc
|
||||
|
||||
from ..Package import Package
|
||||
from .Backend import Backend as Base
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..Cmd import Cmd as Parent
|
||||
|
||||
class BePkg(Base):
|
||||
|
||||
def __init__(self, parent: Parent):
|
||||
super().__init__(parent)
|
||||
|
||||
async def files(self, name: str) -> Iterable[str]:
|
||||
return await self._files(name)
|
||||
|
||||
@abc.abstractmethod
|
||||
async def _files(self, name: str) -> Iterable[str]:
|
||||
pass
|
||||
|
||||
async def meta_data(self, names: Iterable[str]) -> Iterable[Package]:
|
||||
return await self._meta_data(names)
|
||||
|
||||
@abc.abstractmethod
|
||||
async def _meta_data(self, names: Iterable[str]) -> Iterable[Package]:
|
||||
pass
|
||||
16
src/python/jw/pkg/lib/distros/BeRebootRequired.py
Normal file
16
src/python/jw/pkg/lib/distros/BeRebootRequired.py
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import abc
|
||||
from argparse import Namespace
|
||||
|
||||
from .Backend import Backend as Base
|
||||
from ..Cmd import Cmd as Parent
|
||||
|
||||
class BeRebootRequired(Base):
|
||||
|
||||
def __init__(self, parent: Parent):
|
||||
super().__init__(parent)
|
||||
|
||||
@abc.abstractmethod
|
||||
async def run(self, args: Namespace) -> None:
|
||||
pass
|
||||
16
src/python/jw/pkg/lib/distros/BeRefresh.py
Normal file
16
src/python/jw/pkg/lib/distros/BeRefresh.py
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import abc
|
||||
from argparse import Namespace
|
||||
|
||||
from .Backend import Backend as Base
|
||||
from ..Cmd import Cmd as Parent
|
||||
|
||||
class BeRefresh(Base):
|
||||
|
||||
def __init__(self, parent: Parent):
|
||||
super().__init__(parent)
|
||||
|
||||
@abc.abstractmethod
|
||||
async def run(self, args: Namespace) -> None:
|
||||
pass
|
||||
26
src/python/jw/pkg/lib/distros/BeSelect.py
Normal file
26
src/python/jw/pkg/lib/distros/BeSelect.py
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import abc
|
||||
from typing import Iterable
|
||||
|
||||
from .Backend import Backend as Base
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..Cmd import Cmd as Parent
|
||||
from .Package import Package
|
||||
|
||||
class BeSelect(Base):
|
||||
|
||||
def __init__(self, parent: Parent):
|
||||
super().__init__(parent)
|
||||
|
||||
@property
|
||||
async def all_installed_packages(self) -> Iterable[Package]:
|
||||
return await self._all_installed_packages()
|
||||
|
||||
@abc.abstractmethod
|
||||
async def _all_installed_packages(self) -> Iterable[Package]:
|
||||
pass
|
||||
4
src/python/jw/pkg/lib/distros/Makefile
Normal file
4
src/python/jw/pkg/lib/distros/Makefile
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
TOPDIR = ../../../../../..
|
||||
|
||||
include $(TOPDIR)/make/proj.mk
|
||||
include $(JWBDIR)/make/py-mod.mk
|
||||
25
src/python/jw/pkg/lib/distros/Util.py
Normal file
25
src/python/jw/pkg/lib/distros/Util.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ..util import run_sudo
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..Cmd import Cmd
|
||||
|
||||
class Util:
|
||||
|
||||
def __init__(self, parent: Cmd):
|
||||
self.__parent = parent
|
||||
|
||||
async def _sudo(self, *args, **kwargs):
|
||||
return await run_sudo(*args, interactive=self.interactive, **kwargs)
|
||||
|
||||
@property
|
||||
def parent(self):
|
||||
return self.__parent
|
||||
|
||||
@property
|
||||
def interactive(self) -> bool:
|
||||
return self.__parent.interactive
|
||||
17
src/python/jw/pkg/lib/distros/arch/Dup.py
Normal file
17
src/python/jw/pkg/lib/distros/arch/Dup.py
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from argparse import Namespace
|
||||
|
||||
from ...Cmd import Cmd
|
||||
from ..BeDup import BeDup as Base
|
||||
|
||||
class Dup(Base):
|
||||
|
||||
def __init__(self, parent: Cmd):
|
||||
super().__init__(parent)
|
||||
|
||||
async def run(self, args: Namespace):
|
||||
pm_args = ['-Su']
|
||||
if args.download_only:
|
||||
pm_args.append('-w')
|
||||
return await self.util.pacman(pm_args)
|
||||
18
src/python/jw/pkg/lib/distros/arch/Install.py
Normal file
18
src/python/jw/pkg/lib/distros/arch/Install.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from argparse import Namespace
|
||||
|
||||
from ...Cmd import Cmd
|
||||
from ..BeInstall import BeInstall as Base
|
||||
|
||||
class Install(Base):
|
||||
|
||||
def __init__(self, parent: Cmd):
|
||||
super().__init__(parent)
|
||||
|
||||
async def run(self, args: Namespace):
|
||||
if args.only_update:
|
||||
raise NotImplementedError('--only-update is not yet implemented for pacman')
|
||||
pacman_args = ['-S', '--needed']
|
||||
pacman_args.extend(args.packages)
|
||||
await self.util.pacman(*pacman_args)
|
||||
4
src/python/jw/pkg/lib/distros/arch/Makefile
Normal file
4
src/python/jw/pkg/lib/distros/arch/Makefile
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
TOPDIR = ../../../../../../..
|
||||
|
||||
include $(TOPDIR)/make/proj.mk
|
||||
include $(JWBDIR)/make/py-mod.mk
|
||||
14
src/python/jw/pkg/lib/distros/arch/Refresh.py
Normal file
14
src/python/jw/pkg/lib/distros/arch/Refresh.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from argparse import Namespace
|
||||
|
||||
from ...Cmd import Cmd
|
||||
from ..BeRefresh import BeRefresh as Base
|
||||
|
||||
class Refresh(Base):
|
||||
|
||||
def __init__(self, parent: Cmd):
|
||||
super().__init__(parent)
|
||||
|
||||
async def run(self, args: Namespace):
|
||||
raise NotImplementedError('distro refresh is not yet implemented for Arch-like distributions')
|
||||
16
src/python/jw/pkg/lib/distros/arch/Util.py
Normal file
16
src/python/jw/pkg/lib/distros/arch/Util.py
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from ...Cmd import Cmd
|
||||
from ..Util import Util as Base
|
||||
|
||||
class Util(Base):
|
||||
|
||||
def __init__(self, parent: Cmd):
|
||||
super().__init__(parent)
|
||||
|
||||
async def pacman(self, *args):
|
||||
cmd = ['/usr/bin/pacman']
|
||||
if not self.interactive:
|
||||
cmd.extend(['--noconfirm'])
|
||||
cmd.extend(args)
|
||||
return await self._sudo(cmd)
|
||||
14
src/python/jw/pkg/lib/distros/debian/Delete.py
Normal file
14
src/python/jw/pkg/lib/distros/debian/Delete.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from argparse import Namespace
|
||||
|
||||
from ...Cmd import Cmd
|
||||
from ..BeDelete import BeDelete as Base
|
||||
|
||||
class Delete(Base):
|
||||
|
||||
def __init__(self, parent: Cmd):
|
||||
super().__init__(parent)
|
||||
|
||||
async def run(self, args: Namespace):
|
||||
return await self.util.dpkg(['-P', *args.names], sudo=True)
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue