spiegel-keyman/linux/keyman-config/keyman_config/list_installed_kmp.py
Eberhard Beilharz d4c27a4d44
chore(linux): Properly compare version numbers
We changed the comparison of version numbers a while ago, but this
one slipped through. Using string comparison for version numbers
is a bad idea... This addresses code review comments.
2023-06-12 19:43:38 +02:00

166 lines
6 KiB
Python
Executable file

#!/usr/bin/python3
import json
import logging
import os
from pkg_resources import parse_version
from keyman_config import secure_lookup
from keyman_config.deprecated_decorator import deprecated
from keyman_config.get_kmp import InstallLocation, get_keyman_dir
from keyman_config.kmpmetadata import parseinfdata, parsemetadata
@deprecated('Use get_keyman_dir(area) instead')
def get_install_area_path(area):
return get_keyman_dir(area)
def get_installed_kmp(area):
"""
Get list of installed kmp in an install area.
Args:
area (InstallLocation): install area to check
InstallLocation.User: ~/.local/share/keyman
InstallLocation.Shared: /usr/local/share/keyman
InstallLocation.OS: /usr/share/keyman
Returns:
list: Installed kmp
dict: Keyboard
id (str): Keyboard ID
name (str): Keyboard name
kmpname (str): Keyboard name in local
version (str): available Keyboard version
kmpversion (str): installed Keyboard version
path (str): base path where keyboard is installed
description (str): Keyboard description
"""
check_paths = [get_keyman_dir(area)]
return get_installed_kmp_paths(check_paths)
def get_installed_kmp_paths(check_paths):
"""
Get list of installed kmp.
Args:
check_paths (list): list of paths to check
Returns:
list: Installed kmp
dict: Keyboard
packageID (str): kmp ID
keyboardID (str): Keyboard ID
name (str): Keyboard name
kmpname (str): Keyboard name in local
version (str): Keyboard version
kmpversion (str):
areapath (str): base path of area where kmp is installed
description (str): Keyboard description
has_kbjson (bool): Keyboard is in the json file
has_kboptions (bool): Keyboard uses options.htm form
"""
installed_keyboards = {}
for keymanpath in check_paths:
if os.path.isdir(keymanpath):
for o in os.listdir(keymanpath):
if os.path.isdir(os.path.join(keymanpath, o)) and o != "icons":
name = md_name = version = md_version = keyboardID = description = kbdata = None
info, system, options, keyboards, files = parsemetadata(os.path.join(keymanpath, o, "kmp.json"))
if not info:
info, system, options, keyboards, files = parseinfdata(os.path.join(keymanpath, o, "kmp.inf"))
has_kbjson = False
kbjson = os.path.join(keymanpath, o, o + ".json")
if os.path.isfile(kbjson):
try:
with open(kbjson, "r") as read_file:
kbdata = json.load(read_file)
if kbdata:
if 'description' in kbdata:
description = kbdata['description']
version = kbdata['version']
name = kbdata['name']
has_kbjson = True
except Exception as e:
logging.warning('Exception %s loading %s %s', type(e), kbjson, e.args)
if info:
md_version = secure_lookup(info, 'version', 'description')
md_name = secure_lookup(info, 'name', 'description')
if keyboards:
keyboardID = keyboards[0]['id']
else:
keyboardID = o
if not name:
version = md_version
name = md_name
has_kboptions = False
if files:
for fileinfo in files:
if fileinfo['name'] == "options.htm":
has_kboptions = True
break
installed_keyboards[o] = {
"packageID": o, "keyboardID": keyboardID, "name": name,
"kmpname": md_name, "version": version, "kmpversion": md_version,
"areapath": keymanpath, "description": description,
"has_kbjson": has_kbjson, "has_kboptions": has_kboptions}
return installed_keyboards
def get_kmp_version(packageID):
"""
Get version of the kmp for a package ID.
This return the highest version if installed in more than one area
Args:
packageID (dict): kmp ID
Returns:
str: kmp version if kmp ID is installed
None: if not found
"""
version = None
version = _get_kmp_version_internal(packageID, InstallLocation.OS, version)
version = _get_kmp_version_internal(packageID, InstallLocation.Shared, version)
version = _get_kmp_version_internal(packageID, InstallLocation.User, version)
return version
def _get_kmp_version_internal(packageId, location, previousVersion):
kmp = get_installed_kmp(location)
if packageId in kmp:
version = kmp[packageId]['kmpversion']
if not previousVersion or parse_version(previousVersion) < parse_version(version):
previousVersion = version
return previousVersion
def get_kmp_version_user(packageID):
"""
Get version of the kmp for a kmp ID.
This only checks the user area.
Args:
packageID (dict): kmp ID
Returns:
str: kmp version if kmp ID is installed
None: if not found
"""
return _get_kmp_version_internal(packageID, InstallLocation.User, None)
def get_kmp_version_shared(packageID):
"""
Get version of the kmp for a kmp ID.
This only checks the shared area.
Args:
packageID (dict): kmp ID
Returns:
str: kmp version if kmp ID is installed
None: if not found
"""
return _get_kmp_version_internal(packageID, InstallLocation.Shared, None)