From 43394b17ffcf908b3747e1985075755dca002872 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 7 Dec 2021 15:27:33 +0000 Subject: [PATCH 01/13] Initial work on auto-generating WiX Component list * We'll be generating EDMarketConnector.wxs, so remove it from git and add to .gitignore * Initial work on using `lxml` to parse in wix/components.wxs, generated by heat.exe, to pick out what we need, modify it, and eventually stitch into a generated EDMarketConnector.wxs --- .gitignore | 1 + EDMarketConnector.wxs | 724 ------------------------------------------ setup.py | 63 ++++ 3 files changed, 64 insertions(+), 724 deletions(-) delete mode 100644 EDMarketConnector.wxs diff --git a/.gitignore b/.gitignore index 7474987d..49459783 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ venv htmlcov/ .ignored .coverage +EDMarketConnector.wxs diff --git a/EDMarketConnector.wxs b/EDMarketConnector.wxs deleted file mode 100644 index 621aafa2..00000000 --- a/EDMarketConnector.wxs +++ /dev/null @@ -1,724 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - WIX_UPGRADE_DETECTED AND ARPINSTALLLOCATION - - - - - WIX_UPGRADE_DETECTED AND ARPINSTALLLOCATION - - - - - - - - - NOT Installed - - - - - - - - - - NOT Installed AND LAUNCH ~= "yes" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/setup.py b/setup.py index 52be2c78..a87773f6 100755 --- a/setup.py +++ b/setup.py @@ -9,6 +9,7 @@ Script to build to .exe and .msi package. import codecs import os +import pathlib import platform import re import shutil @@ -18,6 +19,8 @@ from os.path import exists, isdir, join from tempfile import gettempdir from typing import Any, Generator, Set +from lxml import etree + from config import ( appcmdname, applongname, appname, appversion, appversion_nobuild, copyright, git_shorthash_from_head, update_feed, update_interval @@ -283,6 +286,66 @@ if sys.platform == 'darwin': os.system(f'cd {dist_dir}; ditto -ck --keepParent --sequesterRsrc {appname}.app ../{package_filename}; cd ..') elif sys.platform == 'win32': + header_file = pathlib.Path('wix/header.wxs') + components_file = pathlib.Path('wix/components.wxs') + components_transformed_file = pathlib.Path(r'wix/components_transformed.wxs') + + header_tree = etree.parse(header_file) + # Use heat.exe to generate the Component for all files inside dist.win32 + os.system(rf'"{WIXPATH}\heat.exe" dir {dist_dir}\ -ag -sfrag -srid -suid -out {components_file}') + + component_tree = etree.parse(components_file) + # 1. Change the element: + # + # + # + # to: + # + # + win32 = component_tree.find('.//{*}Directory[@Id="dist.win32"][@Name="dist.win32"]') + if not win32: + raise ValueError(f'{components_file}: Expected Directory with Id="dist.win32"') + + win32.set('Id', 'INSTALLDIR') + win32.set('Name', '$(var.PRODUCTNAME)') + # 2. Change: + # + # + # + # + # + # to: + # + # + # + # + # + main_executable = win32.find('.//{*}Component[@Id="EDMarketConnector.exe"]') + if not main_executable: + raise ValueError(f'{components_file}: Expected Component with Id="EDMarketConnector.exe"') + + main_executable.set('Id', 'MainExecutable') + main_executable.set('Guid', '{D33BB66E-9664-4AB6-A044-3004B50A09B0}') + shortcut = etree.SubElement( + main_executable, + 'Shortcut', + nsmap=main_executable.nsmap, + attrib={ + 'Id': 'MainExeShortcut', + 'Directory': 'ProgramMenuFolder', + 'Name': '$(var.PRODUCTLONGNAME)', + 'Description': 'Downloads station data from Elite: Dangerous', + 'WorkingDirectory': 'INSTALLDIR', + 'Icon': 'EDMarketConnector.exe', + 'IconIndex': '0', + 'Advertise': 'yes' + } + ) + + # Append the Feature/ComponentRef listing to match + # Concatenate our header, this middle, and our footer. os.system(rf'"{WIXPATH}\candle.exe" -out {dist_dir}\ {appname}.wxs') if not exists(f'{dist_dir}/{appname}.wixobj'): From 6ed64c9d6b5e0202b27101e92c7fc04478d9bf0b Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 7 Dec 2021 15:51:38 +0000 Subject: [PATCH 02/13] WiX: .gitignore components.wxs & add template.wxs Also renamed header.wxs to template.wxs in setup.py, as we're going to insert into the middle of its content, not use it as a simple concatenated header. --- .gitignore | 1 + setup.py | 8 +-- wix/template.wxs | 126 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 wix/template.wxs diff --git a/.gitignore b/.gitignore index 49459783..9bea3d5a 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,4 @@ htmlcov/ .ignored .coverage EDMarketConnector.wxs +wix/components.wxs diff --git a/setup.py b/setup.py index a87773f6..afb4233c 100755 --- a/setup.py +++ b/setup.py @@ -286,11 +286,10 @@ if sys.platform == 'darwin': os.system(f'cd {dist_dir}; ditto -ck --keepParent --sequesterRsrc {appname}.app ../{package_filename}; cd ..') elif sys.platform == 'win32': - header_file = pathlib.Path('wix/header.wxs') + template_file = pathlib.Path('wix/template.wxs') components_file = pathlib.Path('wix/components.wxs') components_transformed_file = pathlib.Path(r'wix/components_transformed.wxs') - header_tree = etree.parse(header_file) # Use heat.exe to generate the Component for all files inside dist.win32 os.system(rf'"{WIXPATH}\heat.exe" dir {dist_dir}\ -ag -sfrag -srid -suid -out {components_file}') @@ -345,7 +344,10 @@ elif sys.platform == 'win32': ) # Append the Feature/ComponentRef listing to match - # Concatenate our header, this middle, and our footer. + + template_tree = etree.parse(template_file) + # Insert what we now have into the template and write it out + os.system(rf'"{WIXPATH}\candle.exe" -out {dist_dir}\ {appname}.wxs') if not exists(f'{dist_dir}/{appname}.wixobj'): diff --git a/wix/template.wxs b/wix/template.wxs new file mode 100644 index 00000000..0d365919 --- /dev/null +++ b/wix/template.wxs @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + WIX_UPGRADE_DETECTED AND ARPINSTALLLOCATION + + + + + WIX_UPGRADE_DETECTED AND ARPINSTALLLOCATION + + + + + + + + + NOT Installed + + + + + + + + + + NOT Installed AND LAUNCH ~= "yes" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From ff32c299cf4053e79fb3e524144fe60fc159a04f Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 7 Dec 2021 16:16:27 +0000 Subject: [PATCH 03/13] WiX: Insertion of heat.exe produced Components now working --- setup.py | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/setup.py b/setup.py index afb4233c..e829b74d 100755 --- a/setup.py +++ b/setup.py @@ -288,12 +288,12 @@ if sys.platform == 'darwin': elif sys.platform == 'win32': template_file = pathlib.Path('wix/template.wxs') components_file = pathlib.Path('wix/components.wxs') - components_transformed_file = pathlib.Path(r'wix/components_transformed.wxs') + final_wxs_file = pathlib.Path('wix/final.wxs') # Use heat.exe to generate the Component for all files inside dist.win32 os.system(rf'"{WIXPATH}\heat.exe" dir {dist_dir}\ -ag -sfrag -srid -suid -out {components_file}') - component_tree = etree.parse(components_file) + component_tree = etree.parse(str(components_file)) # 1. Change the element: # # @@ -301,12 +301,12 @@ elif sys.platform == 'win32': # to: # # - win32 = component_tree.find('.//{*}Directory[@Id="dist.win32"][@Name="dist.win32"]') - if not win32: + directory_win32 = component_tree.find('.//{*}Directory[@Id="dist.win32"][@Name="dist.win32"]') + if directory_win32 is None: raise ValueError(f'{components_file}: Expected Directory with Id="dist.win32"') - win32.set('Id', 'INSTALLDIR') - win32.set('Name', '$(var.PRODUCTNAME)') + directory_win32.set('Id', 'INSTALLDIR') + directory_win32.set('Name', '$(var.PRODUCTNAME)') # 2. Change: # # @@ -321,8 +321,8 @@ elif sys.platform == 'win32': # Description="Downloads station data from Elite: Dangerous" WorkingDirectory="INSTALLDIR" # Icon="EDMarketConnector.exe" IconIndex="0" Advertise="yes" /> # - main_executable = win32.find('.//{*}Component[@Id="EDMarketConnector.exe"]') - if not main_executable: + main_executable = directory_win32.find('.//{*}Component[@Id="EDMarketConnector.exe"]') + if main_executable is None: raise ValueError(f'{components_file}: Expected Component with Id="EDMarketConnector.exe"') main_executable.set('Id', 'MainExecutable') @@ -342,11 +342,22 @@ elif sys.platform == 'win32': 'Advertise': 'yes' } ) + # Now insert the appropriate parts as a child of the ProgramFilesFolder part + # of the template. + template_tree = etree.parse(str(template_file)) + program_files_folder = template_tree.find('.//{*}Directory[@Id="ProgramFilesFolder"]') + if program_files_folder is None: + raise ValueError(f'{template_file}: Expected Directory with Id="ProgramFilesFolder"') + program_files_folder.insert(0, directory_win32) # Append the Feature/ComponentRef listing to match - template_tree = etree.parse(template_file) # Insert what we now have into the template and write it out + template_tree.write( + str(final_wxs_file), encoding='utf-8', + pretty_print=True, + xml_declaration=True + ) os.system(rf'"{WIXPATH}\candle.exe" -out {dist_dir}\ {appname}.wxs') From 931740f6401bc6948816e7117b8cfeb8112e47a3 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 7 Dec 2021 16:17:38 +0000 Subject: [PATCH 04/13] WiX: Re-add the hard-coded EDMarketConnector.wxs inside wix/ folder So that it's around for reference. --- .gitignore | 1 - wix/EDMarketConnector.wxs | 724 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 724 insertions(+), 1 deletion(-) create mode 100644 wix/EDMarketConnector.wxs diff --git a/.gitignore b/.gitignore index 9bea3d5a..989d6405 100644 --- a/.gitignore +++ b/.gitignore @@ -23,5 +23,4 @@ venv htmlcov/ .ignored .coverage -EDMarketConnector.wxs wix/components.wxs diff --git a/wix/EDMarketConnector.wxs b/wix/EDMarketConnector.wxs new file mode 100644 index 00000000..d19dfa67 --- /dev/null +++ b/wix/EDMarketConnector.wxs @@ -0,0 +1,724 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + WIX_UPGRADE_DETECTED AND ARPINSTALLLOCATION + + + + + WIX_UPGRADE_DETECTED AND ARPINSTALLLOCATION + + + + + + + + + NOT Installed + + + + + + + + + + NOT Installed AND LAUNCH ~= "yes" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 0af2af344deba8d2e8af2248e65e80749bbbae3c Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 7 Dec 2021 16:18:26 +0000 Subject: [PATCH 05/13] WiX: Output to final .wxs to expected filename for next stages --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index e829b74d..bfab647d 100755 --- a/setup.py +++ b/setup.py @@ -288,7 +288,7 @@ if sys.platform == 'darwin': elif sys.platform == 'win32': template_file = pathlib.Path('wix/template.wxs') components_file = pathlib.Path('wix/components.wxs') - final_wxs_file = pathlib.Path('wix/final.wxs') + final_wxs_file = pathlib.Path('EDMarketConnector.wxs') # Use heat.exe to generate the Component for all files inside dist.win32 os.system(rf'"{WIXPATH}\heat.exe" dir {dist_dir}\ -ag -sfrag -srid -suid -out {components_file}') From a196bfe1722dfd9f9ee368ffdabd03a148b30ba7 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 7 Dec 2021 16:48:11 +0000 Subject: [PATCH 06/13] WiX: Autogeneration of EDMarketConnector.wxs fully working * Changed config version to 5.3.0-beta2 to be sure during testing. * Fixed the case on ChangeLog.md in setup.py py2exe config. * Replaced all TABs with <4 spaces> in wix/template.wxs. * Now generating the correct Feature tree in the output file. NB: The 'RegistryEntries' isn't part of the file Components but still needs to be referenced inside . --- config.py | 2 +- setup.py | 26 ++++++- wix/template.wxs | 194 +++++++++++++++++++++++------------------------ 3 files changed, 123 insertions(+), 99 deletions(-) diff --git a/config.py b/config.py index 7df3e218..ff0b7fed 100644 --- a/config.py +++ b/config.py @@ -33,7 +33,7 @@ appcmdname = 'EDMC' # # Major.Minor.Patch(-prerelease)(+buildmetadata) # NB: Do *not* import this, use the functions appversion() and appversion_nobuild() -_static_appversion = '5.3.0-beta1' +_static_appversion = '5.3.0-beta2' _cached_version: Optional[semantic_version.Version] = None copyright = '© 2015-2019 Jonathan Harris, 2020-2021 EDCD' diff --git a/setup.py b/setup.py index bfab647d..ba88ce7c 100755 --- a/setup.py +++ b/setup.py @@ -212,7 +212,7 @@ elif sys.platform == 'win32': 'WinSparkle.dll', 'WinSparkle.pdb', # For debugging - don't include in package 'EUROCAPS.TTF', - 'Changelog.md', + 'ChangeLog.md', 'commodity.csv', 'rare_commodity.csv', 'snd_good.wav', @@ -351,6 +351,30 @@ elif sys.platform == 'win32': program_files_folder.insert(0, directory_win32) # Append the Feature/ComponentRef listing to match + feature = template_tree.find('.//{*}Feature[@Id="Complete"][@Level="1"]') + if feature is None: + raise ValueError(f'{template_file}: Expected Feature element with Id="Complete" Level="1"') + + # This isn't part of the components + feature.append( + etree.Element( + 'ComponentRef', + attrib={ + 'Id': 'RegistryEntries' + }, + nsmap=directory_win32.nsmap + ) + ) + for c in directory_win32.findall('.//{*}Component'): + feature.append( + etree.Element( + 'ComponentRef', + attrib={ + 'Id': c.get('Id') + }, + nsmap=directory_win32.nsmap + ) + ) # Insert what we now have into the template and write it out template_tree.write( diff --git a/wix/template.wxs b/wix/template.wxs index 0d365919..7e4409a4 100644 --- a/wix/template.wxs +++ b/wix/template.wxs @@ -6,119 +6,119 @@ - + - - - + + + - - - + + + - + - + - - - - + + + + - - - - - - - - - WIX_UPGRADE_DETECTED AND ARPINSTALLLOCATION - - - - - WIX_UPGRADE_DETECTED AND ARPINSTALLLOCATION - - + + + + + + + + + WIX_UPGRADE_DETECTED AND ARPINSTALLLOCATION + + + + + WIX_UPGRADE_DETECTED AND ARPINSTALLLOCATION + + - - - - - - NOT Installed - - + + + + + + NOT Installed + + - - - - - - - NOT Installed AND LAUNCH ~= "yes" - - + + + + + + + NOT Installed AND LAUNCH ~= "yes" + + - + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - + - - + + - + From 97f025e1b96f1092a38f1c944b2007ad49fd2895 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 7 Dec 2021 17:08:58 +0000 Subject: [PATCH 07/13] requirements-dev: Add lxml, used for Windows packaging --- requirements-dev.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/requirements-dev.txt b/requirements-dev.txt index afc11caf..221b5997 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -27,6 +27,8 @@ autopep8==1.6.0 grip==4.5.2 # Packaging +# Used to put together a WiX configuration from template/auto-gen +lxml==4.6.4 # We only need py2exe on windows. py2exe==0.11.0.1; sys_platform == 'win32' From ee66b9deb1b3396d1522cf6e1ca7beb822be2016 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 7 Dec 2021 17:16:21 +0000 Subject: [PATCH 08/13] WiX: Move EDMarketConnector.wixobj to root directory * Don't specify its generation inside dist.win32/ * Specify `-b dist.win32\` to light.exe invocation Tested with installing resultant .msi over 5.2.3. --- setup.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index ba88ce7c..8bb8fb30 100755 --- a/setup.py +++ b/setup.py @@ -383,13 +383,13 @@ elif sys.platform == 'win32': xml_declaration=True ) - os.system(rf'"{WIXPATH}\candle.exe" -out {dist_dir}\ {appname}.wxs') + os.system(rf'"{WIXPATH}\candle.exe" {appname}.wxs') - if not exists(f'{dist_dir}/{appname}.wixobj'): - raise AssertionError(f'No {dist_dir}/{appname}.wixobj: candle.exe failed?') + if not exists(f'{appname}.wixobj'): + raise AssertionError(f'No {appname}.wixobj: candle.exe failed?') package_filename = f'{appname}_win_{appversion_nobuild()}.msi' - os.system(rf'"{WIXPATH}\light.exe" -sacl -spdb -sw1076 {dist_dir}\{appname}.wixobj -out {package_filename}') + os.system(rf'"{WIXPATH}\light.exe" -b {dist_dir}\ -sacl -spdb -sw1076 {appname}.wixobj -out {package_filename}') if not exists(package_filename): raise AssertionError(f'light.exe failed, no {package_filename}') From 6737ab932292d4b60ebbf72e7dfb92a453782c70 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 7 Dec 2021 17:20:44 +0000 Subject: [PATCH 09/13] WiX: Rename to wix/static-EDMarketConnector.wxs and .gitignore generated --- .gitignore | 1 + wix/{EDMarketConnector.wxs => static-EDMarketConnector.wxs} | 0 2 files changed, 1 insertion(+) rename wix/{EDMarketConnector.wxs => static-EDMarketConnector.wxs} (100%) diff --git a/.gitignore b/.gitignore index 989d6405..9bea3d5a 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,5 @@ venv htmlcov/ .ignored .coverage +EDMarketConnector.wxs wix/components.wxs diff --git a/wix/EDMarketConnector.wxs b/wix/static-EDMarketConnector.wxs similarity index 100% rename from wix/EDMarketConnector.wxs rename to wix/static-EDMarketConnector.wxs From 43d98bff1c847e56811408003ce327f3e07f88f7 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 7 Dec 2021 17:36:51 +0000 Subject: [PATCH 10/13] WiX: Add/update comments in template.wxs about auto-generation We *are* now using auto GUIDs. It worked for a 5.2.3 -> 5.3.0-beta2 upgrade install. I suspect that specifying 'MajorUpgrade' means the GUIDs mostly don't even matter. They're there for if you try to patch so as to patch the correct files? --- wix/template.wxs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/wix/template.wxs b/wix/template.wxs index 7e4409a4..a15e0fc1 100644 --- a/wix/template.wxs +++ b/wix/template.wxs @@ -104,9 +104,7 @@ - - - + @@ -115,6 +113,7 @@ + From 381c156fb9c2fa793fb91584d34c5767ab1eae6b Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 11 Dec 2021 10:53:31 +0000 Subject: [PATCH 11/13] l10n: Change _Locale.preferred_languages() to use a common return var This is the first step before putting any necessary "difference between OneSky and system names for languages" translations in. --- l10n.py | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/l10n.py b/l10n.py index 7ffed54b..b1ff2672 100755 --- a/l10n.py +++ b/l10n.py @@ -309,7 +309,7 @@ class _Locale: return None - def preferred_languages(self) -> Iterable[str]: + def preferred_languages(self) -> Iterable[str]: # noqa: CCR001 """ Return a list of preferred language codes. @@ -320,34 +320,41 @@ class _Locale: :return: The preferred language list """ + languages: Iterable[str] if platform == 'darwin': - return NSLocale.preferredLanguages() + languages = NSLocale.preferredLanguages() elif platform != 'win32': # POSIX lang = locale.getlocale()[0] - return lang and [lang.replace('_', '-')] or [] + languages = lang and [lang.replace('_', '-')] or [] - def wszarray_to_list(array): - offset = 0 - while offset < len(array): - sz = ctypes.wstring_at(ctypes.addressof(array) + offset*2) - if sz: - yield sz - offset += len(sz)+1 + else: + def wszarray_to_list(array): + offset = 0 + while offset < len(array): + sz = ctypes.wstring_at(ctypes.addressof(array) + offset*2) + if sz: + yield sz + offset += len(sz)+1 - else: - break + else: + break - num = ctypes.c_ulong() - size = ctypes.c_ulong(0) - if GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, ctypes.byref(num), None, ctypes.byref(size)) and size.value: - buf = ctypes.create_unicode_buffer(size.value) + num = ctypes.c_ulong() + size = ctypes.c_ulong(0) + languages = [] + if GetUserPreferredUILanguages( + MUI_LANGUAGE_NAME, ctypes.byref(num), None, ctypes.byref(size) + ) and size.value: + buf = ctypes.create_unicode_buffer(size.value) - if GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, ctypes.byref(num), ctypes.byref(buf), ctypes.byref(size)): - return wszarray_to_list(buf) + if GetUserPreferredUILanguages( + MUI_LANGUAGE_NAME, ctypes.byref(num), ctypes.byref(buf), ctypes.byref(size) + ): + languages = wszarray_to_list(buf) - return [] + return languages # singletons From 72fc78048fb7e4fefc76d0bf26eb6eb1bf95aefb Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 11 Dec 2021 10:59:43 +0000 Subject: [PATCH 12/13] l10n: Change zh-CN to zh-Hans in preferred_languages(). --- l10n.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/l10n.py b/l10n.py index b1ff2672..2771f46a 100755 --- a/l10n.py +++ b/l10n.py @@ -354,6 +354,10 @@ class _Locale: ): languages = wszarray_to_list(buf) + # OneSky calls "Chinese Simplified" "zh-Hans" in the name of the file, + # but that will be zh-CN in terms of locale. So map zh-CN -> zh-Hans + languages = ['zh-Hans' if lang == 'zh-CN' else lang for lang in languages] + return languages From fc3a7b32a3d6e1d9327b5d9747973df383c1b480 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 11 Dec 2021 14:15:30 +0000 Subject: [PATCH 13/13] l10n: Make the zh-CN -> zh-Hans comment a HACK --- l10n.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/l10n.py b/l10n.py index 2771f46a..b77c07de 100755 --- a/l10n.py +++ b/l10n.py @@ -354,8 +354,9 @@ class _Locale: ): languages = wszarray_to_list(buf) - # OneSky calls "Chinese Simplified" "zh-Hans" in the name of the file, - # but that will be zh-CN in terms of locale. So map zh-CN -> zh-Hans + # HACK: | 2021-12-11: OneSky calls "Chinese Simplified" "zh-Hans" + # in the name of the file, but that will be zh-CN in terms of + # locale. So map zh-CN -> zh-Hans languages = ['zh-Hans' if lang == 'zh-CN' else lang for lang in languages] return languages