diff --git a/HISTORY.md b/HISTORY.md index 5f7d768460..0703b2d18f 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,11 @@ # Keyman Version History +## 17.0.139 alpha 2023-07-13 + +* (#9259) +* chore(linux): Add unit tests for dconf_util.py (#9215) +* refactor(linux): Refactor image loading (#9245) + ## 17.0.138 alpha 2023-07-11 * chore: Update standards data (#9193) diff --git a/VERSION.md b/VERSION.md index f106a1f76a..de2f3430c5 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -17.0.139 \ No newline at end of file +17.0.140 \ No newline at end of file diff --git a/common/web/types/src/kmx/kmx-plus-builder/build-vars.ts b/common/web/types/src/kmx/kmx-plus-builder/build-vars.ts index 25c7f174ec..5f70689e96 100644 --- a/common/web/types/src/kmx/kmx-plus-builder/build-vars.ts +++ b/common/web/types/src/kmx/kmx-plus-builder/build-vars.ts @@ -3,7 +3,7 @@ import { KMXPlusData } from "../kmx-plus.js"; import { build_strs_index, BUILDER_STR_REF, BUILDER_STRS } from "./build-strs.js"; import { BUILDER_SECTION } from "./builder-section.js"; import { BUILDER_LIST_REF } from "./build-list.js"; -import { /*build_elem_index, BUILDER_ELEM,*/ BUILDER_ELEM_REF } from "./build-elem.js"; +import { build_elem_index, BUILDER_ELEM, BUILDER_ELEM_REF } from "./build-elem.js"; interface BUILDER_VARS_ITEM { @@ -22,7 +22,7 @@ export interface BUILDER_VARS extends BUILDER_SECTION { /** * Builder for the 'vars' section */ -export function build_vars(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS /*, sect_elem: BUILDER_ELEM */) : BUILDER_VARS { +export function build_vars(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS, sect_elem: BUILDER_ELEM) : BUILDER_VARS { if(!kmxplus.vars) { return null; } @@ -36,8 +36,7 @@ export function build_vars(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS /*, sec type: constants.vars_entry_type_set, id: build_strs_index(sect_strs, v.id), value: build_strs_index(sect_strs, v.value), - // TODO-LDML: elem - // elem: build_elem_index(sect_elem, v.items), + elem: build_elem_index(sect_elem, v.items), }); const uniSetVars = kmxplus.vars.unicodeSets.map(v => { type: constants.vars_entry_type_unicodeSet, diff --git a/common/web/types/src/kmx/kmx-plus-builder/kmx-plus-builder.ts b/common/web/types/src/kmx/kmx-plus-builder/kmx-plus-builder.ts index 74f363011f..001223697e 100644 --- a/common/web/types/src/kmx/kmx-plus-builder/kmx-plus-builder.ts +++ b/common/web/types/src/kmx/kmx-plus-builder/kmx-plus-builder.ts @@ -99,7 +99,7 @@ export default class KMXPlusBuilder { this.sect.name = build_name(this.file.kmxplus, this.sect.strs); this.sect.tran = build_tran(this.file.kmxplus.tran, this.sect.strs, this.sect.elem); this.sect.uset = build_uset(this.file.kmxplus, this.sect.strs); - this.sect.vars = build_vars(this.file.kmxplus, this.sect.strs, /*TODO-LDML: this.sect.elem*/); + this.sect.vars = build_vars(this.file.kmxplus, this.sect.strs, this.sect.elem); this.sect.vkey = build_vkey(this.file.kmxplus); // Finalize the sect (index) section diff --git a/developer/src/kmc-ldml/test/fixtures/basic.txt b/developer/src/kmc-ldml/test/fixtures/basic.txt index d5d8a93f14..0fe6d67a30 100644 --- a/developer/src/kmc-ldml/test/fixtures/basic.txt +++ b/developer/src/kmc-ldml/test/fixtures/basic.txt @@ -528,7 +528,7 @@ block(vars) # struct COMP_KMXPLUS_VARS { 01 00 00 00 # KMX_DWORD type = set index(strNull,strVse,2) # KMXPLUS_STR id 'vse' index(strNull,strSet,2) # KMXPLUS_STR value 'a b c' - 00 00 00 00 # KMXPLUS_ELEM elem TODO-LDML should be set + 01 00 00 00 # KMXPLUS_ELEM elem 'a b c' see 'elemSet' # var 1 00 00 00 00 # KMX_DWORD type = string diff --git a/docs/build/linux-ubuntu.md b/docs/build/linux-ubuntu.md index 09867b1e2e..ee45d4eb4a 100644 --- a/docs/build/linux-ubuntu.md +++ b/docs/build/linux-ubuntu.md @@ -49,6 +49,10 @@ sudo apt install devscripts equivs sudo mk-build-deps --install linux/debian/control ``` +### Node.js + +Node.js v18 is required for Core build, Web tests, and Developer command line tools. + ## Keyman for Linux All dependencies are already installed if you followed the instructions under [Prerequisites](#Prerequisites). diff --git a/linux/keyman-config/keyman_config/convertico.py b/linux/keyman-config/keyman_config/convertico.py index 1a836f9610..fa6f7b39ab 100755 --- a/linux/keyman-config/keyman_config/convertico.py +++ b/linux/keyman-config/keyman_config/convertico.py @@ -8,7 +8,6 @@ import sys import numpy as np from PIL import Image, ImageFile -Image.LOAD_TRUNCATED_IMAGES = True ImageFile.LOAD_TRUNCATED_IMAGES = True @@ -20,8 +19,7 @@ def changeblacktowhite(im): white_areas = (red == 0) & (blue == 0) & (green == 0) data[..., :-1][white_areas.T] = (255, 255, 255) # Transpose back needed - im2 = Image.fromarray(data) - return im2 + return Image.fromarray(data) def checkandsaveico(icofile): @@ -35,32 +33,34 @@ def checkandsaveico(icofile): icofile (str): path to ico file """ name, ext = os.path.splitext(icofile) - bmpfile = name + ".bmp" + bmpfile = f"{name}.bmp" if ext == '.ico': - im = Image.open(icofile) - im = im.convert('RGBA') - im2 = im - num, colour = max(im.getcolors(im.size[0] * im.size[1])) - logging.debug("checkandsaveico maxcolour: num {0}: colour {1}".format(num, colour)) - if num > 160 and colour == (0, 0, 0, 0): - logging.info("checkandsaveico:" + icofile + " mostly black so changing black to white") - im2 = changeblacktowhite(im) - im2.save(bmpfile) - + _convert_ico_to_bmp(icofile, bmpfile) try: - im3 = Image.open(bmpfile) - im4 = im3.resize([64, 64], Image.ANTIALIAS) - # Using .bmp.png file extension so it won't conflict if the package already contains .png - im4.save(bmpfile + '.png', 'png') + with Image.open(bmpfile) as im3: + with im3.resize((64, 64), Image.LANCZOS) as im4: + # Using .bmp.png file extension so it won't conflict if the package already contains .png + im4.save(f'{bmpfile}.png', 'png') except (IOError, OSError): logging.error("Cannot convert %s to png", icofile) - pass finally: # Clean up intermediary .bmp file if it was generated if ext == '.ico': os.remove(bmpfile) +def _convert_ico_to_bmp(icofile, bmpfile): + with Image.open(icofile) as im: + with im.convert('RGBA') as im2: + num, colour = max(im.getcolors(im2.size[0] * im2.size[1])) + logging.debug(f"checkandsaveico maxcolour: num {num}: colour {colour}") + if num > 160 and colour == (0, 0, 0, 0): + logging.info(f"checkandsaveico:{icofile} mostly black so changing black to white") + im2.close() + im2 = changeblacktowhite(im) + im2.save(bmpfile) + + def extractico(kmxfile): """ Extract icon file from compiled kmx keyboard @@ -95,9 +95,9 @@ def extractico(kmxfile): # Read first two bytes to determine if icon is .bmp or .ico if bitmap.startswith(b'BM'): - imagefilename = imagefilename + ".bmp" + imagefilename = f"{imagefilename}.bmp" else: - imagefilename = imagefilename + ".ico" + imagefilename = f"{imagefilename}.ico" try: with open(imagefilename, mode='wb') as imagefile: diff --git a/linux/keyman-config/keyman_config/dconf_util.py b/linux/keyman-config/keyman_config/dconf_util.py index c28ec3fd19..a2775a45e1 100644 --- a/linux/keyman-config/keyman_config/dconf_util.py +++ b/linux/keyman-config/keyman_config/dconf_util.py @@ -15,7 +15,7 @@ def get_child_schema(info): if not path.endswith('/'): path += '/' path += info['packageID'] + '/' + info['keyboardID'] + '/' - return Gio.Settings(GSETTINGS_BASE + '.child', path) + return Gio.Settings(f'{GSETTINGS_BASE}.child', path) def get_option(info): @@ -51,11 +51,8 @@ def set_option(info, options): key and values to store """ if "packageID" in info and "keyboardID" in info and options: - # Convert dictionary of options into a list of comma-separated option strings - list_options = [] - for key, value in options.items(): - list_options.append(key + "=" + value) - + # Convert dictionary of options into a list of option strings + list_options = [f"{key}={value}" for key, value in options.items()] child_schema = get_child_schema(info) child_schema.set_strv("options", list_options) diff --git a/linux/keyman-config/run-tests.sh b/linux/keyman-config/run-tests.sh index b390ce613b..db62cda374 100755 --- a/linux/keyman-config/run-tests.sh +++ b/linux/keyman-config/run-tests.sh @@ -4,6 +4,10 @@ PYTHONPATH=.:$PYTHONPATH XDG_CONFIG_HOME=$(mktemp --directory) export XDG_CONFIG_HOME +if [ -f /usr/libexec/ibus-memconf ]; then + export GSETTINGS_BACKEND=keyfile +fi + if [ -n "$TEAMCITY_VERSION" ]; then if ! pip3 list --format=columns | grep -q teamcity-messages; then pip3 install teamcity-messages diff --git a/linux/keyman-config/tests/test_dconf_util.py b/linux/keyman-config/tests/test_dconf_util.py new file mode 100755 index 0000000000..9093f493e5 --- /dev/null +++ b/linux/keyman-config/tests/test_dconf_util.py @@ -0,0 +1,43 @@ +#!/usr/bin/python3 +import unittest +from gi.repository import Gio + +from keyman_config.dconf_util import get_option, set_option, GSETTINGS_BASE + + +class TestKeymanOptions(unittest.TestCase): + def setUp(self): + self.settings = Gio.Settings.new(GSETTINGS_BASE) + + def tearDown(self): + # Reset the GSettings to its original state + self.settings.reset("options") + + def test_get_option_no_info(self): + # Test getting options with invalid info + options = get_option({}) + self.assertEqual(options, {}) + + def test_get_option_invalid_info(self): + # Test getting options with invalid info + info = {"packageID": "", "keyboardID": ""} + options = get_option(info) + self.assertEqual(options, {}) + + def test_get_option_valid_info(self): + # Test getting options with valid info + info = {"packageID": "foo", "keyboardID": "bar"} + options = get_option(info) + self.assertIsInstance(options, dict) + + def test_set_option(self): + # Test setting options + info = {"packageID": "foo", "keyboardID": "bar"} + options = {"set_nfc": "1"} + set_option(info, options) + retrieved_options = get_option(info) + self.assertEqual(retrieved_options, options) + + +if __name__ == '__main__': + unittest.main() diff --git a/package-lock.json b/package-lock.json index 9538a2212b..658eb2d26c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -46,6 +46,9 @@ "ts-node": "^10.9.1", "tslib": "^2.5.2", "typescript": "^4.9.5" + }, + "engines": { + "node": "^18.x" } }, "common/models/templates": { diff --git a/package.json b/package.json index 787fe68e5a..c780b4199c 100644 --- a/package.json +++ b/package.json @@ -43,5 +43,8 @@ "@keymanapp/hextobin": "file:common/tools/hextobin", "@keymanapp/keyman-version": "file:common/web/keyman-version", "@keymanapp/ldml-keyboard-constants": "file:core/include/ldml" + }, + "engines": { + "node": "^18.x" } }