From bdf7ed181e1ce8855e2161383f0249922d4aa85c Mon Sep 17 00:00:00 2001 From: "Steven R. Loomis" Date: Tue, 13 Jun 2023 11:09:43 -0500 Subject: [PATCH 01/10] chore: add engine clause to package.json - will warn if used in node !18 --- package-lock.json | 3 +++ package.json | 3 +++ 2 files changed, 6 insertions(+) diff --git a/package-lock.json b/package-lock.json index 3e9ca6fe45..56390704a3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,6 +43,9 @@ "mocha-teamcity-reporter": "^4.0.0", "ts-node": "^10.9.1", "typescript": "^4.9.5" + }, + "engines": { + "node": "^18.x" } }, "common/models/templates": { diff --git a/package.json b/package.json index 7a2b53d50d..c181dd3dc5 100644 --- a/package.json +++ b/package.json @@ -40,5 +40,8 @@ "@keymanapp/common-types": "file:common/web/types", "@keymanapp/ldml-keyboard-constants": "file:core/include/ldml", "@keymanapp/developer-test-helpers": "file:developer/src/common/web/test-helpers" + }, + "engines": { + "node": "^18.x" } } From 049b8c0a86fb34859734dfbdf7d61711f4f2f170 Mon Sep 17 00:00:00 2001 From: "Steven R. Loomis" Date: Tue, 4 Jul 2023 15:49:19 -0500 Subject: [PATCH 02/10] chore(common): update docs around Node.js --- docs/build/linux-ubuntu.md | 4 ++++ docs/build/macos.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/build/linux-ubuntu.md b/docs/build/linux-ubuntu.md index 5b576a6ce8..64ba3f4663 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 the core build. + ## Keyman for Linux All dependencies are already installed if you followed the instructions under [Prerequisites](#Prerequisites). diff --git a/docs/build/macos.md b/docs/build/macos.md index d8e4f61696..bf1b64eaef 100644 --- a/docs/build/macos.md +++ b/docs/build/macos.md @@ -66,7 +66,7 @@ These dependencies are also listed below if you'd prefer to install manually. PATH="$HOMEBREW_PREFIX/opt/coreutils/libexec/gnubin:$PATH" ``` -* Web: node.js, emscripten, openjdk 8 +* Web: node.js ≥v18, emscripten, openjdk 8 ```shell brew install node emscripten openjdk@8 From 74643d39eda30d4b947e6182c6ac1c1c1aeb39f2 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Thu, 6 Jul 2023 17:06:19 +0200 Subject: [PATCH 03/10] chore(linux): Add unit tests for dconf_util.py Tests were generated by ChatGPT (although it didn't get it quite right - was missing the parameter in `self.settings.reset`). --- .../keyman-config/keyman_config/dconf_util.py | 9 ++--- linux/keyman-config/tests/test_dconf_util.py | 38 +++++++++++++++++++ 2 files changed, 41 insertions(+), 6 deletions(-) create mode 100755 linux/keyman-config/tests/test_dconf_util.py 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/tests/test_dconf_util.py b/linux/keyman-config/tests/test_dconf_util.py new file mode 100755 index 0000000000..5b68d7dfa2 --- /dev/null +++ b/linux/keyman-config/tests/test_dconf_util.py @@ -0,0 +1,38 @@ +#!/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_invalid_info(self): + # Test getting options with invalid info + info = {"packageID": "invalid", "keyboardID": "invalid"} + options = get_option(info) + self.assertEqual(options, {}) + + def test_get_option_valid_info(self): + # Test getting options with valid info + info = {"packageID": "sil_cipher_music", "keyboardID": "sil_cipher_music"} + options = get_option(info) + self.assertIsInstance(options, dict) + + def test_set_option(self): + # Test setting options + info = {"packageID": "sil_cipher_music", "keyboardID": "sil_cipher_music"} + options = {"set_nfc": "1"} + set_option(info, options) + retrieved_options = get_option(info) + self.assertEqual(retrieved_options, options) + + +if __name__ == '__main__': + unittest.main() From eedf7545c8691497b624d04b60e90545eac7f42d Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 11 Jul 2023 12:13:45 +0200 Subject: [PATCH 04/10] refactor(linux): Refactor some code --- .../keyman-config/keyman_config/convertico.py | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/linux/keyman-config/keyman_config/convertico.py b/linux/keyman-config/keyman_config/convertico.py index 1a836f9610..13c651887a 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.ANTIALIAS) 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: From 3cc9f09d820c01e3bdf728f98dca3fbad881063c Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 11 Jul 2023 12:14:26 +0200 Subject: [PATCH 05/10] fix(linux): Replace deprecated `Image.ANTIALIAS` Fixes #9244. --- linux/keyman-config/keyman_config/convertico.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/keyman-config/keyman_config/convertico.py b/linux/keyman-config/keyman_config/convertico.py index 13c651887a..fa6f7b39ab 100755 --- a/linux/keyman-config/keyman_config/convertico.py +++ b/linux/keyman-config/keyman_config/convertico.py @@ -38,7 +38,7 @@ def checkandsaveico(icofile): _convert_ico_to_bmp(icofile, bmpfile) try: with Image.open(bmpfile) as im3: - with im3.resize((64, 64), Image.ANTIALIAS) as im4: + 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): From 8b9f3eb2c5abbf9d5f13a6d896503aed49b68ead Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 11 Jul 2023 17:33:46 +0200 Subject: [PATCH 06/10] chore(linux): Add another test --- linux/keyman-config/tests/test_dconf_util.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/linux/keyman-config/tests/test_dconf_util.py b/linux/keyman-config/tests/test_dconf_util.py index 5b68d7dfa2..9093f493e5 100755 --- a/linux/keyman-config/tests/test_dconf_util.py +++ b/linux/keyman-config/tests/test_dconf_util.py @@ -13,21 +13,26 @@ class TestKeymanOptions(unittest.TestCase): # 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": "invalid", "keyboardID": "invalid"} + 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": "sil_cipher_music", "keyboardID": "sil_cipher_music"} + info = {"packageID": "foo", "keyboardID": "bar"} options = get_option(info) self.assertIsInstance(options, dict) def test_set_option(self): # Test setting options - info = {"packageID": "sil_cipher_music", "keyboardID": "sil_cipher_music"} + info = {"packageID": "foo", "keyboardID": "bar"} options = {"set_nfc": "1"} set_option(info, options) retrieved_options = get_option(info) From 87ccb6e9450d078941e62fd7878c40bd60d15635 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 11 Jul 2023 17:36:22 +0200 Subject: [PATCH 07/10] chore(linux): Use different backend for unit tests --- linux/keyman-config/run-tests.sh | 4 ++++ 1 file changed, 4 insertions(+) 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 From f3bfef0cc34f1cdf72ae8bd467d97281eedba54e Mon Sep 17 00:00:00 2001 From: "Steven R. Loomis" Date: Wed, 12 Jul 2023 16:44:07 -0500 Subject: [PATCH 08/10] =?UTF-8?q?fix(common):=20set=20variables=20need=20t?= =?UTF-8?q?o=20serialize=20elementstring=20=F0=9F=99=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - populate the 'elem' field of set variables - this will be needed for mapFrom/mapTo For: #7375 --- common/web/types/src/kmx/kmx-plus-builder/build-vars.ts | 6 ++++-- .../web/types/src/kmx/kmx-plus-builder/kmx-plus-builder.ts | 2 +- developer/src/kmc-ldml/test/fixtures/basic.txt | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) 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 41111f7cf6..7f80ae66d5 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 @@ -2,13 +2,14 @@ import { constants } from "@keymanapp/ldml-keyboard-constants"; import { KMXPlusData } from "../kmx-plus.js"; import { build_strs_index, BUILDER_STRS } from "./build-strs.js"; import { BUILDER_SECTION } from "./builder-section.js"; +import { build_elem_index, BUILDER_ELEM } from "./build-elem.js"; interface BUILDER_VARS_ITEM { type: number; id: number; // str value: number; // str - elem?: number; // elem, TODO-LDML + elem?: number; // elem }; export interface BUILDER_VARS extends BUILDER_SECTION { @@ -20,7 +21,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; } @@ -34,6 +35,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), + 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 641868908b..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); + 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 From 91cb4468a092d52d8be57b7f53e5223000dca9c4 Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Thu, 13 Jul 2023 14:02:40 -0400 Subject: [PATCH 09/10] auto: increment master version to 17.0.140 --- HISTORY.md | 6 ++++++ VERSION.md | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) 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 From 10acdb5c5b8461ce3aaef72cb08c32d1b0fff5b6 Mon Sep 17 00:00:00 2001 From: "Steven R. Loomis" Date: Thu, 13 Jul 2023 20:24:44 -0500 Subject: [PATCH 10/10] Update docs/build/linux-ubuntu.md Co-authored-by: Marc Durdin --- docs/build/linux-ubuntu.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/build/linux-ubuntu.md b/docs/build/linux-ubuntu.md index 64ba3f4663..47afd77605 100644 --- a/docs/build/linux-ubuntu.md +++ b/docs/build/linux-ubuntu.md @@ -51,7 +51,7 @@ sudo mk-build-deps --install linux/debian/control ### Node.js -Node.js v18 is required for the core build. +Node.js v18 is required for Core build, Web tests, and Developer command line tools. ## Keyman for Linux