Files
controller-wisetopdataserver/python/biopro/util/package.py
T
2021-12-20 14:52:55 +08:00

172 lines
4.0 KiB
Python

from typing import List, Optional
from biopro.util.sys import system_call, CalledProcessError
class Package:
def __init__(self):
self.name = ''
self.version = ''
@classmethod
def manager(cls) -> str:
try:
system_call('which', 'dpkg')
return 'dpkg'
except CalledProcessError:
pass
try:
system_call('which', 'pacman')
return 'pacman'
except CalledProcessError:
pass
raise RuntimeError()
@classmethod
def list(cls) -> List['Package']:
manager = cls.manager()
if manager == 'dpkg':
return AptGetPackage.list()
elif manager == 'pacman':
return PacmanPackage.list()
return []
_DESIRED = ( # TODO use typing.Literal in Python 3.8
'u', # Unknown
'i', # Install
'r', # Remove
'p', # Purge
'h', # Hold
)
_STATUS = ( # TODO use typing.Literal in Python 3.8
'n', # Not (The package is not installed)
'i', # Inst (The package is successfully installed)
'c', # Conf-files (Configuration files are present)
'u', # Unpacked (The package is stilled unpacked)
'f', # Failed-conf (Failed to remove configuration files)
'h', # Half-inst (The package is only partially installed)
'W', # trig-aWait ()
't', # Trig-pend ()
)
class AptGetPackage(Package):
def __init__(self):
super().__init__()
self.desired = '' # Unknown/Install/Remove/Purge/Hold
self.status = '' # Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
self.err: Optional[str] = None # (none)/Reinst-required (Status,Err: uppercase=bad)
self.architecture = ''
self.description = ''
def __repr__(self):
return '%s%s%s %s %s %s %s' % (
self.desired,
self.status,
'' if self.err is None else self.err,
self.name,
self.version,
self.architecture,
self.description
)
@classmethod
def list(cls) -> List['AptGetPackage']:
output = system_call('dpkg', '-l')
ret = []
for line in output.split('\n')[6:]:
if len(line) == 0:
continue
part: List[str] = list(filter(len, line.split(' ')))
package = AptGetPackage()
ret.append(package)
c = part[0]
package.desired = c[0]
package.status = c[1]
try:
package.err = c[2]
except IndexError:
pass
package.name = part[1]
package.version = part[2]
package.architecture = part[3]
package.description = ' '.join(part[4:])
return ret
class PacmanPackage(Package):
def __repr__(self):
return '%s %s' % (
self.name,
self.version,
)
@classmethod
def list(cls) -> List['PacmanPackage']:
output = system_call('pacman', '-Q')
ret = []
for line in output.split('\n'):
if len(line) == 0:
continue
part: List[str] = list(filter(len, line.split(' ')))
package = PacmanPackage()
ret.append(package)
package.name = part[0]
package.version = part[1]
return ret
class PipPackage(Package):
def __repr__(self):
return '%s %s' % (
self.name,
self.version,
)
@classmethod
def list(cls) -> List['PipPackage']:
output = system_call('pip3', 'list')
ret = []
for line in output.split('\n')[2:]:
if len(line) == 0:
continue
part: List[str] = list(filter(len, line.split(' ')))
package = PipPackage()
ret.append(package)
package.name = part[0]
package.version = part[1]
return ret
if __name__ == '__main__':
print(Package.manager())
for p in Package.list():
print(p)