mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-07 09:25:33 +00:00
221 lines
8.7 KiB
Python
Executable file
221 lines
8.7 KiB
Python
Executable file
#!/usr/bin/python3
|
|
|
|
import argparse
|
|
import datetime
|
|
import logging
|
|
import os
|
|
import sys
|
|
import time
|
|
from pkg_resources import parse_version
|
|
from zipfile import is_zipfile
|
|
|
|
from keyman_config import KeymanApiUrl, __version__, secure_lookup
|
|
from keyman_config.install_kmp import extract_kmp
|
|
from keyman_config.kmpmetadata import get_metadata
|
|
from keyman_config.uninstall_kmp import uninstall_kmp
|
|
|
|
|
|
def get_languages():
|
|
import requests
|
|
import requests_cache
|
|
|
|
from keyman_config.get_kmp import keyman_cache_dir
|
|
|
|
logging.info("Getting language list from search")
|
|
api_url = KeymanApiUrl + "/search?q=l:*&platform=linux"
|
|
logging.debug("At URL %s", api_url)
|
|
cache_dir = keyman_cache_dir()
|
|
current_dir = os.getcwd()
|
|
expire_after = datetime.timedelta(days=7)
|
|
if not os.path.isdir(cache_dir):
|
|
os.makedirs(cache_dir)
|
|
os.chdir(cache_dir)
|
|
requests_cache.install_cache(cache_name='keyman_cache', backend='sqlite', expire_after=expire_after)
|
|
now = time.ctime(int(time.time()))
|
|
try:
|
|
response = requests.get(api_url)
|
|
logging.debug("Time: {0} / Used Cache: {1}".format(now, response.from_cache))
|
|
os.chdir(current_dir)
|
|
requests_cache.uninstall_cache()
|
|
if response.status_code == 200:
|
|
return response.json()
|
|
else:
|
|
return None
|
|
except Exception:
|
|
return None
|
|
|
|
|
|
def get_keyboard_list():
|
|
languages = get_languages()
|
|
keyboards = []
|
|
if not languages:
|
|
return []
|
|
|
|
if "languages" in languages:
|
|
for lang in languages["languages"]:
|
|
if "keyboards" in lang:
|
|
for kb in lang["keyboards"]:
|
|
kbnospace = kb.replace(" ", "%20")
|
|
if kbnospace not in keyboards:
|
|
keyboards.append(kbnospace)
|
|
if keyboards:
|
|
keyboards.sort()
|
|
return keyboards
|
|
|
|
|
|
def write_kmpdirlist(kmpdirfile):
|
|
try:
|
|
with open(kmpdirfile, 'wt') as kmpdirlist:
|
|
keyboards = get_keyboard_list()
|
|
if keyboards:
|
|
for kb in get_keyboard_list():
|
|
print(kb, file=kmpdirlist)
|
|
except Exception as e:
|
|
logging.warning('Exception %s writing %s %s', type(e), kmpdirfile, e.args)
|
|
|
|
|
|
def list_keyboards():
|
|
from keyman_config.get_kmp import keyman_cache_dir
|
|
kmpdirfile = os.path.join(keyman_cache_dir(), 'kmpdirlist')
|
|
if not os.path.exists(kmpdirfile):
|
|
write_kmpdirlist(kmpdirfile)
|
|
else:
|
|
logging.debug("kmpdirlist already exists")
|
|
# file empty
|
|
if os.path.getsize(kmpdirfile) == 0:
|
|
write_kmpdirlist(kmpdirfile)
|
|
|
|
|
|
def _list_languages_for_keyboard_impl(packageId, packageDir):
|
|
from keyman_config.get_kmp import keyman_cache_dir
|
|
kmpfile = os.path.join(keyman_cache_dir(), packageId)
|
|
if not os.path.exists(kmpfile):
|
|
kmpfile = kmpfile + '.kmp'
|
|
if not os.path.exists(kmpfile):
|
|
return ''
|
|
extract_kmp(kmpfile, packageDir)
|
|
info, system, options, keyboards, files = get_metadata(packageDir)
|
|
if not keyboards:
|
|
return ''
|
|
firstKeyboard = keyboards[0]
|
|
if not secure_lookup(firstKeyboard, 'languages') or len(firstKeyboard['languages']) <= 0:
|
|
return ''
|
|
result = ''
|
|
for lang in firstKeyboard['languages']:
|
|
if result:
|
|
result += '\n'
|
|
result += lang['id']
|
|
return result
|
|
|
|
|
|
def list_languages_for_keyboard(packageId, packageDir):
|
|
result = _list_languages_for_keyboard_impl(packageId, packageDir)
|
|
print(result)
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description='Install a Keyman keyboard package, either a local .kmp file or specify a ' +
|
|
'keyboard id to download and install, optionally specifying a language for which to ' +
|
|
'install the keyboard.',
|
|
epilog='Example: km-package-install -s -p sil_el_ethiopian_latin --bcp47 ssy-latn')
|
|
parser.add_argument('-s', '--shared', action='store_true', help='Install to shared area /usr/local')
|
|
parser.add_argument('-f', '--file', metavar='KMPFILE', help='Keyman kmp file')
|
|
parser.add_argument('-p', '--package', metavar='PACKAGE', help='Keyman package id')
|
|
parser.add_argument('-l', '--bcp47', metavar='LANGTAG', help='bcp47 language tag')
|
|
parser.add_argument('--version', action='version', version='%(prog)s version ' + __version__)
|
|
parser.add_argument('-v', '--verbose', action='store_true', help='verbose logging')
|
|
parser.add_argument('-vv', '--veryverbose', action='store_true', help='very verbose logging')
|
|
|
|
args = parser.parse_args()
|
|
if args.verbose:
|
|
logging.basicConfig(level=logging.INFO, format='%(levelname)s:%(message)s')
|
|
elif args.veryverbose:
|
|
logging.basicConfig(level=logging.DEBUG, format='%(levelname)s:%(message)s')
|
|
else:
|
|
logging.basicConfig(format='%(levelname)s:%(message)s')
|
|
|
|
if args.package and args.file:
|
|
parser.print_usage()
|
|
logging.error(
|
|
"km-package-install: error: too many arguments: either install a local kmp file or " +
|
|
"specify a keyboard id to download and install.")
|
|
sys.exit(2)
|
|
|
|
from keyman_config.get_kmp import (get_keyboard_data, get_kmp,
|
|
keyman_cache_dir)
|
|
from keyman_config.install_kmp import (InstallError, InstallStatus,
|
|
install_kmp)
|
|
from keyman_config.list_installed_kmp import get_kmp_version_shared, get_kmp_version_user
|
|
|
|
if os.path.exists(os.path.join(keyman_cache_dir(), 'kmpdirlist')):
|
|
os.remove(os.path.join(keyman_cache_dir(), 'kmpdirlist'))
|
|
|
|
def try_install_kmp(inputfile, arg, language=None, sharedarea=False):
|
|
try:
|
|
install_kmp(inputfile, sharedarea, language)
|
|
except InstallError as e:
|
|
if e.status == InstallStatus.Abort:
|
|
logging.error("km-package-install: error: Failed to install %s", arg)
|
|
logging.error(e.message)
|
|
sys.exit(3)
|
|
else:
|
|
logging.warning(e.message)
|
|
|
|
if args.file:
|
|
name, ext = os.path.splitext(args.file)
|
|
if ext != ".kmp" or not is_zipfile(args.file):
|
|
logging.error("km-package-install: Input file %s is not a kmp file.", args.file)
|
|
logging.error("km-package-install -f <kmpfile>")
|
|
sys.exit(2)
|
|
|
|
if not os.path.isfile(args.file):
|
|
logging.error("km-package-install: Keyman kmp file %s not found.", args.file)
|
|
logging.error("km-package-install -f <kmpfile>")
|
|
sys.exit(2)
|
|
try_install_kmp(args.file, "file " + args.file, args.bcp47, args.shared)
|
|
elif args.package:
|
|
if args.shared:
|
|
if get_kmp_version_user(args.package):
|
|
print("km-package-install: Warning: Keyboard %s is also installed for the current user."
|
|
% args.package)
|
|
installed_kmp_v = get_kmp_version_shared(args.package)
|
|
else:
|
|
if get_kmp_version_shared(args.package):
|
|
print("km-package-install: Warning: Keyboard %s is already installed in the shared area."
|
|
% args.package)
|
|
installed_kmp_v = get_kmp_version_user(args.package)
|
|
kbdata = get_keyboard_data(args.package)
|
|
if not kbdata:
|
|
logging.error("km-package-install: error: Could not download keyboard data for %s", args.package)
|
|
sys.exit(3)
|
|
kbdata_v = secure_lookup(kbdata, 'version')
|
|
if installed_kmp_v and kbdata_v:
|
|
kbdata_version = parse_version(kbdata_v)
|
|
installed_kmp_ver = parse_version(installed_kmp_v)
|
|
if kbdata_version == installed_kmp_ver:
|
|
print("km-package-install: Version %s of the %s keyboard package is already installed."
|
|
% (installed_kmp_ver, args.package))
|
|
sys.exit(1)
|
|
elif kbdata_version > installed_kmp_ver:
|
|
print("km-package-install: A newer version of %s keyboard package is available. Uninstalling old "
|
|
"version %s then downloading and installing new version %s."
|
|
% (args.package, installed_kmp_ver, kbdata_version))
|
|
uninstall_kmp(args.package, args.shared)
|
|
|
|
kmpfile = get_kmp(args.package)
|
|
if kmpfile:
|
|
try_install_kmp(kmpfile, "keyboard package " + args.package, args.bcp47, args.shared)
|
|
else:
|
|
logging.error("km-package-install: error: Could not download keyboard package %s", args.package)
|
|
sys.exit(2)
|
|
else:
|
|
parser.print_usage()
|
|
logging.error(
|
|
"km-package-install: error: no arguments: either install a local kmp file " +
|
|
"or specify a keyboard package id to download and install.")
|
|
sys.exit(2)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|