19 Commits
Author SHA1 Message Date
Mikaël Capelle d38019a994 Move to VCPKG. (#7) 2025-05-29 11:03:34 +02:00
Mikaël Capelle af4c65d941 Bump dependencies and fix formatting. (#9) 2025-05-27 08:00:57 +02:00
Mikaël Capelle e510e1c3ed Update translations. (#8) 2024-07-21 16:43:51 +02:00
Mikaël Capelle f1b92a0f61 Install poetry in CI. (#6)
* Install poetry in CI.
* Force platform to Windows for pyright.
2024-06-09 14:20:10 +02:00
Mikaël Capelle 7f93d4f77b Update following uibase change for game features. (#5) 2024-06-09 12:26:22 +02:00
Mikaël Capelle 0f4f666c71 Change plugin requirement to use PyPi version. 2024-05-20 10:28:19 +02:00
Mikaël Capelle a0ca112ed0 Bump stubs. 2022-05-05 13:15:52 +02:00
Mikaël Capelle 7ef97f047c Merge pull request #4 from ModOrganizer2/update-cmake-common-qt6
Update cmake common qt6
2022-04-28 17:54:50 +02:00
Mikaël Capelle aff1cbb944 Fixes for Qt6. 2022-04-22 13:18:04 +02:00
Mikaël Capelle 6492f84eac Minor fixes. 2022-04-19 23:33:35 +02:00
Mikaël Capelle 7b3dc82f46 Update following cmake_common changes.
# Conflicts:
#	CMakeLists.txt
2022-04-19 22:03:11 +02:00
Jeremy Rimpo 76faacba19 Merge remote-tracking branch 'origin/master' into qt6 2022-04-17 20:17:40 -05:00
Jeremy Rimpo 3bfd181704 Installer image improvements
- Expand size of options / image row
- Resize image with correct aspect ratio
- Add maximize button to titlebar
2021-12-26 01:23:16 -06:00
Jeremy Rimpo bffeb8c05f More PyQt6 enum fixes 2021-12-26 01:16:42 -06:00
Jeremy Rimpo f7a9c95d5b Fix issues with PyQt6 2021-12-25 20:54:10 -06:00
Jeremy Rimpo 793ab6273b Reformat the translations 2021-12-09 19:39:50 -06:00
Jeremy Rimpo 7e5ec2d11a Fix pylupdate parsing 2021-12-06 23:50:35 -06:00
Jeremy Rimpo ca343602ec PyQt6 Compatibility 2021-12-06 05:25:26 -06:00
Jeremy Rimpo e2202073dc Changes to compile with Qt6 + Boost 1.77 2021-12-05 03:42:40 -06:00
21 changed files with 948 additions and 484 deletions
+6
View File
@@ -0,0 +1,6 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.py text eol=crlf
+39
View File
@@ -0,0 +1,39 @@
name: Build Installer Wizard Plugin
on:
push:
branches: [master]
pull_request:
types: [opened, synchronize, reopened]
jobs:
build:
runs-on: windows-2022
steps:
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Set environmental variables
shell: bash
run: |
echo "VCPKG_ROOT=$VCPKG_INSTALLATION_ROOT" >> $GITHUB_ENV
- uses: actions/checkout@v4
- name: Configure Installer Wizard Plugin build
shell: pwsh
run: |
cmake --preset vs2022-windows "-DCMAKE_INSTALL_PREFIX=install" "-DVCPKG_MANIFEST_FEATURES=standalone"
- name: Build Installer Wizard Plugin
run: cmake --build vsbuild --config RelWithDebInfo
- name: Install Installer Wizard Plugin
run: cmake --install vsbuild --config RelWithDebInfo
- name: Upload Installer Wizard Plugin artifact
uses: actions/upload-artifact@master
with:
name: installer_wizard
path: ./install/bin/plugins
+20 -12
View File
@@ -8,17 +8,25 @@ jobs:
strategy:
max-parallel: 4
matrix:
python-version: [3.8]
python-version: [3.12]
steps:
- uses: actions/checkout@v1
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install tox
- name: Test with tox
run: tox -e py38-lint
- uses: actions/checkout@v1
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- uses: abatilo/actions-poetry@v2
- name: Install package
run: poetry install
# generate UI file for linting
- name: Generate UI files
shell: pwsh
run: |
Get-ChildItem -Recurse -File -Include "*.ui" | ForEach-Object {
poetry run pyuic6 $_ -o ([io.path]::ChangeExtension($_.FullName, "py"))
}
- name: Lint
run: poetry run poe lint
+1
View File
@@ -7,6 +7,7 @@ src/ui/*.py
**/.mypy_cache
.tox
.vscode
venv
# MO2 build files:
vsbuild
+25
View File
@@ -0,0 +1,25 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-toml
- id: check-merge-conflict
- id: mixed-line-ending
args: [--fix=lf]
- id: check-case-conflict
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.11.7 # must match pyproject.toml
hooks:
- id: ruff
args: [--extend-select, I, --fix]
- id: ruff-format
ci:
autofix_commit_msg: "[pre-commit.ci] Auto fixes from pre-commit.com hooks."
autofix_prs: true
autoupdate_commit_msg: "[pre-commit.ci] Pre-commit autoupdate."
autoupdate_schedule: quarterly
submodules: false
+1 -7
View File
@@ -1,13 +1,7 @@
cmake_minimum_required(VERSION 3.16)
project(installer_wizard LANGUAGES NONE)
set(project_type python_module_plugin)
set(enable_warnings OFF)
if(DEFINED DEPENDENCIES_DIR)
include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/project.cmake)
else()
include(../cmake_common/project.cmake)
endif()
find_package(mo2-cmake CONFIG REQUIRED)
add_subdirectory(src)
+17
View File
@@ -0,0 +1,17 @@
{
"configurePresets": [
{
"binaryDir": "${sourceDir}/vsbuild",
"toolchainFile": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
"generator": "Visual Studio 17 2022",
"name": "vs2022-windows"
}
],
"buildPresets": [
{
"name": "vs2022-windows",
"configurePreset": "vs2022-windows"
}
],
"version": 4
}
+1 -1
View File
@@ -1 +1 @@
git+https://github.com/Holt59/bain-wizard-interpreter@v0.0.3
bain-wizard-interpreter==1.0.4
Generated
+294
View File
@@ -0,0 +1,294 @@
# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand.
[[package]]
name = "antlr4-python3-runtime"
version = "4.13.1"
description = "ANTLR 4.13.1 runtime for Python 3"
optional = false
python-versions = "*"
groups = ["main"]
files = [
{file = "antlr4-python3-runtime-4.13.1.tar.gz", hash = "sha256:3cd282f5ea7cfb841537fe01f143350fdb1c0b1ce7981443a2fa8513fddb6d1a"},
{file = "antlr4_python3_runtime-4.13.1-py3-none-any.whl", hash = "sha256:78ec57aad12c97ac039ca27403ad61cb98aaec8a3f9bb8144f889aa0fa28b943"},
]
[[package]]
name = "bain-wizard-interpreter"
version = "1.0.4"
description = "BAIN Wizard Interpreter based on wizparse."
optional = false
python-versions = "<4.0,>=3.11.1"
groups = ["main"]
files = [
{file = "bain_wizard_interpreter-1.0.4-py3-none-any.whl", hash = "sha256:c6a084349caa6fd80d8fbf222869fb63df8ede337edbb8774dff557ae2a981bc"},
{file = "bain_wizard_interpreter-1.0.4.tar.gz", hash = "sha256:4ebd36112690775bab6c921c90422c9e5432901ca90860f36c5ba0153bb82079"},
]
[package.dependencies]
antlr4-python3-runtime = ">=4.13.1,<5.0.0"
chardet = ">=5.2.0,<6.0.0"
[[package]]
name = "chardet"
version = "5.2.0"
description = "Universal encoding detector for Python 3"
optional = false
python-versions = ">=3.7"
groups = ["main"]
files = [
{file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"},
{file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"},
]
[[package]]
name = "mobase-stubs"
version = "2.5.2"
description = "PEP561 stub files for the mobase Python API."
optional = false
python-versions = "<4.0,>=3.12"
groups = ["dev"]
files = [
{file = "mobase_stubs-2.5.2-py3-none-any.whl", hash = "sha256:6a2c1c95494e7dc0d0f51d4f8f178423c0d9904f823f3c44845315bff304b948"},
{file = "mobase_stubs-2.5.2.tar.gz", hash = "sha256:70c15579828df3bce01746e51fee07176390cdc386facea2b156ea04b3de055c"},
]
[[package]]
name = "nodeenv"
version = "1.9.0"
description = "Node.js virtual environment builder"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
groups = ["dev"]
files = [
{file = "nodeenv-1.9.0-py2.py3-none-any.whl", hash = "sha256:508ecec98f9f3330b636d4448c0f1a56fc68017c68f1e7857ebc52acf0eb879a"},
{file = "nodeenv-1.9.0.tar.gz", hash = "sha256:07f144e90dae547bf0d4ee8da0ee42664a42a04e02ed68e06324348dafe4bdb1"},
]
[[package]]
name = "pastel"
version = "0.2.1"
description = "Bring colors to your terminal."
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
groups = ["dev"]
files = [
{file = "pastel-0.2.1-py2.py3-none-any.whl", hash = "sha256:4349225fcdf6c2bb34d483e523475de5bb04a5c10ef711263452cb37d7dd4364"},
{file = "pastel-0.2.1.tar.gz", hash = "sha256:e6581ac04e973cac858828c6202c1e1e81fee1dc7de7683f3e1ffe0bfd8a573d"},
]
[[package]]
name = "poethepoet"
version = "0.34.0"
description = "A task runner that works well with poetry."
optional = false
python-versions = ">=3.9"
groups = ["dev"]
files = [
{file = "poethepoet-0.34.0-py3-none-any.whl", hash = "sha256:c472d6f0fdb341b48d346f4ccd49779840c15b30dfd6bc6347a80d6274b5e34e"},
{file = "poethepoet-0.34.0.tar.gz", hash = "sha256:86203acce555bbfe45cb6ccac61ba8b16a5784264484195874da457ddabf5850"},
]
[package.dependencies]
pastel = ">=0.2.1,<0.3.0"
pyyaml = ">=6.0.2,<7.0"
[package.extras]
poetry-plugin = ["poetry (>=1.2.0,<3.0.0) ; python_version < \"4.0\""]
[[package]]
name = "pyqt6"
version = "6.7.1"
description = "Python bindings for the Qt cross platform application toolkit"
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
{file = "PyQt6-6.7.1-1-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:7f397f4b38b23b5588eb2c0933510deb953d96b1f0323a916c4839c2a66ccccc"},
{file = "PyQt6-6.7.1-1-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:c2f202b7941aa74e5c7e1463a6f27d9131dbc1e6cabe85571d7364f5b3de7397"},
{file = "PyQt6-6.7.1-cp38-abi3-macosx_11_0_universal2.whl", hash = "sha256:f053378e3aef6248fa612c8afddda17f942fb63f9fe8a9aeb2a6b6b4cbb0eba9"},
{file = "PyQt6-6.7.1-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:0adb7914c732ad1dee46d9cec838a98cb2b11bc38cc3b7b36fbd8701ae64bf47"},
{file = "PyQt6-6.7.1-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2d771fa0981514cb1ee937633dfa64f14caa902707d9afffab66677f3a73e3da"},
{file = "PyQt6-6.7.1-cp38-abi3-win_amd64.whl", hash = "sha256:fa3954698233fe286a8afc477b84d8517f0788eb46b74da69d3ccc0170d3714c"},
{file = "PyQt6-6.7.1.tar.gz", hash = "sha256:3672a82ccd3a62e99ab200a13903421e2928e399fda25ced98d140313ad59cb9"},
]
[package.dependencies]
PyQt6-Qt6 = ">=6.7.0,<6.8.0"
PyQt6-sip = ">=13.8,<14"
[[package]]
name = "pyqt6-qt6"
version = "6.7.1"
description = "The subset of a Qt installation needed by PyQt6."
optional = false
python-versions = "*"
groups = ["main"]
files = [
{file = "PyQt6_Qt6-6.7.1-py3-none-macosx_10_14_x86_64.whl", hash = "sha256:29622b5dd38740b4b6962e0c88d082d08fa10b64542ef5d911b04214aad70150"},
{file = "PyQt6_Qt6-6.7.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fbcfe66a57199c6a26542b8b9b2f2ee59d974db36293de335a1251f24c4fe917"},
{file = "PyQt6_Qt6-6.7.1-py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:9fbab2a96d72d77d16021e259ef86a1a3c87adb0e7eebcc92df0d39f3fdf7e27"},
{file = "PyQt6_Qt6-6.7.1-py3-none-win_amd64.whl", hash = "sha256:590a2f30d15892b5259e6a17ecc0a755675b1b49f553d964e195e90094b44120"},
]
[[package]]
name = "pyqt6-sip"
version = "13.10.2"
description = "The sip module support for PyQt6"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "pyqt6_sip-13.10.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8132ec1cbbecc69d23dcff23916ec07218f1a9bbbc243bf6f1df967117ce303e"},
{file = "pyqt6_sip-13.10.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07f77e89d93747dda71b60c3490b00d754451729fbcbcec840e42084bf061655"},
{file = "pyqt6_sip-13.10.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:4ffa71ddff6ef031d52cd4f88b8bba08b3516313c023c7e5825cf4a0ba598712"},
{file = "pyqt6_sip-13.10.2-cp310-cp310-win_amd64.whl", hash = "sha256:e907394795e61f1174134465c889177f584336a98d7a10beade2437bf5942244"},
{file = "pyqt6_sip-13.10.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1a6c2f168773af9e6c7ef5e52907f16297d4efd346e4c958eda54ea9135be18e"},
{file = "pyqt6_sip-13.10.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1d3cc9015a1bd8c8d3e86a009591e897d4d46b0c514aede7d2970a2208749cd"},
{file = "pyqt6_sip-13.10.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:ddd578a8d975bfb5fef83751829bf09a97a1355fa1de098e4fb4d1b74ee872fc"},
{file = "pyqt6_sip-13.10.2-cp311-cp311-win_amd64.whl", hash = "sha256:061d4a2eb60a603d8be7db6c7f27eb29d9cea97a09aa4533edc1662091ce4f03"},
{file = "pyqt6_sip-13.10.2-cp311-cp311-win_arm64.whl", hash = "sha256:45ac06f0380b7aa4fcffd89f9e8c00d1b575dc700c603446a9774fda2dcfc0de"},
{file = "pyqt6_sip-13.10.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:83e6a56d3e715f748557460600ec342cbd77af89ec89c4f2a68b185fa14ea46c"},
{file = "pyqt6_sip-13.10.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ccf197f8fa410e076936bee28ad9abadb450931d5be5625446fd20e0d8b27a6"},
{file = "pyqt6_sip-13.10.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:37af463dcce39285e686d49523d376994d8a2508b9acccb7616c4b117c9c4ed7"},
{file = "pyqt6_sip-13.10.2-cp312-cp312-win_amd64.whl", hash = "sha256:c7b34a495b92790c70eae690d9e816b53d3b625b45eeed6ae2c0fe24075a237e"},
{file = "pyqt6_sip-13.10.2-cp312-cp312-win_arm64.whl", hash = "sha256:c80cc059d772c632f5319632f183e7578cd0976b9498682833035b18a3483e92"},
{file = "pyqt6_sip-13.10.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8b5d06a0eac36038fa8734657d99b5fe92263ae7a0cd0a67be6acfe220a063e1"},
{file = "pyqt6_sip-13.10.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad376a6078da37b049fdf9d6637d71b52727e65c4496a80b753ddc8d27526aca"},
{file = "pyqt6_sip-13.10.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:3dde8024d055f496eba7d44061c5a1ba4eb72fc95e5a9d7a0dbc908317e0888b"},
{file = "pyqt6_sip-13.10.2-cp313-cp313-win_amd64.whl", hash = "sha256:0b097eb58b4df936c4a2a88a2f367c8bb5c20ff049a45a7917ad75d698e3b277"},
{file = "pyqt6_sip-13.10.2-cp313-cp313-win_arm64.whl", hash = "sha256:cc6a1dfdf324efaac6e7b890a608385205e652845c62130de919fd73a6326244"},
{file = "pyqt6_sip-13.10.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38b5823dca93377f8a4efac3cbfaa1d20229aa5b640c31cf6ebbe5c586333808"},
{file = "pyqt6_sip-13.10.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5506b9a795098df3b023cc7d0a37f93d3224a9c040c43804d4bc06e0b2b742b0"},
{file = "pyqt6_sip-13.10.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e455a181d45a28ee8d18d42243d4f470d269e6ccdee60f2546e6e71218e05bb4"},
{file = "pyqt6_sip-13.10.2-cp39-cp39-win_amd64.whl", hash = "sha256:9c67ed66e21b11e04ffabe0d93bc21df22e0a5d7e2e10ebc8c1d77d2f5042991"},
{file = "pyqt6_sip-13.10.2.tar.gz", hash = "sha256:464ad156bf526500ce6bd05cac7a82280af6309974d816739b4a9a627156fafe"},
]
[[package]]
name = "pyright"
version = "1.1.401"
description = "Command line wrapper for pyright"
optional = false
python-versions = ">=3.7"
groups = ["dev"]
files = [
{file = "pyright-1.1.401-py3-none-any.whl", hash = "sha256:6fde30492ba5b0d7667c16ecaf6c699fab8d7a1263f6a18549e0b00bf7724c06"},
{file = "pyright-1.1.401.tar.gz", hash = "sha256:788a82b6611fa5e34a326a921d86d898768cddf59edde8e93e56087d277cc6f1"},
]
[package.dependencies]
nodeenv = ">=1.6.0"
typing-extensions = ">=4.1"
[package.extras]
all = ["nodejs-wheel-binaries", "twine (>=3.4.1)"]
dev = ["twine (>=3.4.1)"]
nodejs = ["nodejs-wheel-binaries"]
[[package]]
name = "pyyaml"
version = "6.0.2"
description = "YAML parser and emitter for Python"
optional = false
python-versions = ">=3.8"
groups = ["dev"]
files = [
{file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"},
{file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"},
{file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"},
{file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"},
{file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"},
{file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"},
{file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"},
{file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"},
{file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"},
{file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"},
{file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"},
{file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"},
{file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"},
{file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"},
{file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"},
{file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"},
{file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"},
{file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"},
{file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"},
{file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"},
{file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"},
{file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"},
{file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"},
{file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"},
{file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"},
{file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"},
{file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"},
{file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"},
{file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"},
{file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"},
{file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"},
{file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"},
{file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"},
{file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"},
{file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"},
{file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"},
{file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"},
{file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"},
{file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"},
{file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"},
{file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"},
{file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"},
{file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"},
{file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"},
{file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"},
{file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"},
{file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"},
{file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"},
{file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"},
{file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"},
{file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"},
{file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"},
{file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"},
]
[[package]]
name = "ruff"
version = "0.11.11"
description = "An extremely fast Python linter and code formatter, written in Rust."
optional = false
python-versions = ">=3.7"
groups = ["dev"]
files = [
{file = "ruff-0.11.11-py3-none-linux_armv6l.whl", hash = "sha256:9924e5ae54125ed8958a4f7de320dab7380f6e9fa3195e3dc3b137c6842a0092"},
{file = "ruff-0.11.11-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:c8a93276393d91e952f790148eb226658dd275cddfde96c6ca304873f11d2ae4"},
{file = "ruff-0.11.11-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d6e333dbe2e6ae84cdedefa943dfd6434753ad321764fd937eef9d6b62022bcd"},
{file = "ruff-0.11.11-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7885d9a5e4c77b24e8c88aba8c80be9255fa22ab326019dac2356cff42089fc6"},
{file = "ruff-0.11.11-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1b5ab797fcc09121ed82e9b12b6f27e34859e4227080a42d090881be888755d4"},
{file = "ruff-0.11.11-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e231ff3132c1119ece836487a02785f099a43992b95c2f62847d29bace3c75ac"},
{file = "ruff-0.11.11-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:a97c9babe1d4081037a90289986925726b802d180cca784ac8da2bbbc335f709"},
{file = "ruff-0.11.11-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d8c4ddcbe8a19f59f57fd814b8b117d4fcea9bee7c0492e6cf5fdc22cfa563c8"},
{file = "ruff-0.11.11-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6224076c344a7694c6fbbb70d4f2a7b730f6d47d2a9dc1e7f9d9bb583faf390b"},
{file = "ruff-0.11.11-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:882821fcdf7ae8db7a951df1903d9cb032bbe838852e5fc3c2b6c3ab54e39875"},
{file = "ruff-0.11.11-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:dcec2d50756463d9df075a26a85a6affbc1b0148873da3997286caf1ce03cae1"},
{file = "ruff-0.11.11-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:99c28505ecbaeb6594701a74e395b187ee083ee26478c1a795d35084d53ebd81"},
{file = "ruff-0.11.11-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9263f9e5aa4ff1dec765e99810f1cc53f0c868c5329b69f13845f699fe74f639"},
{file = "ruff-0.11.11-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:64ac6f885e3ecb2fdbb71de2701d4e34526651f1e8503af8fb30d4915a3fe345"},
{file = "ruff-0.11.11-py3-none-win32.whl", hash = "sha256:1adcb9a18802268aaa891ffb67b1c94cd70578f126637118e8099b8e4adcf112"},
{file = "ruff-0.11.11-py3-none-win_amd64.whl", hash = "sha256:748b4bb245f11e91a04a4ff0f96e386711df0a30412b9fe0c74d5bdc0e4a531f"},
{file = "ruff-0.11.11-py3-none-win_arm64.whl", hash = "sha256:6c51f136c0364ab1b774767aa8b86331bd8e9d414e2d107db7a2189f35ea1f7b"},
{file = "ruff-0.11.11.tar.gz", hash = "sha256:7774173cc7c1980e6bf67569ebb7085989a78a103922fb83ef3dfe230cd0687d"},
]
[[package]]
name = "typing-extensions"
version = "4.13.2"
description = "Backported and Experimental Type Hints for Python 3.8+"
optional = false
python-versions = ">=3.8"
groups = ["dev"]
files = [
{file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"},
{file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"},
]
[metadata]
lock-version = "2.1"
python-versions = "^3.12"
content-hash = "32e576ced1cd9fd1078bf3656ed1726be6e76a63e31498a891a463e5c2078e60"
+65
View File
@@ -0,0 +1,65 @@
[project]
name = "installer-wizard"
version = "1.0.3"
description = ""
authors = [{ name = "Mikaël Capelle", email = "capelle.mikael@gmail.com" }]
license = "MIT"
readme = "README.md"
dynamic = ["dependencies"]
[tool.poetry]
package-mode = false
[tool.poetry.dependencies]
python = "^3.12"
pyqt6 = "6.7.1"
bain-wizard-interpreter = "1.0.4"
[tool.poetry.group.dev.dependencies]
pyright = "^1.1.401"
ruff = "^0.11.11"
poethepoet = "^0.34.0"
mobase-stubs = {version = "2.5.2", allow-prereleases = true}
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.poe.tasks]
format-imports = "ruff check --select I . --fix"
format-ruff = "ruff format ."
format.sequence = ["format-imports", "format-ruff"]
lint-ruff = "ruff check ."
lint-ruff-format = "ruff format --check ."
lint-pyright = "pyright ."
lint.sequence = ["lint-ruff", "lint-ruff-format", "lint-pyright"]
lint.ignore_fail = "return_non_zero"
[tool.ruff]
target-version = "py312"
[tool.ruff.lint]
extend-select = ["B", "Q", "I"]
[tool.ruff.lint.isort.sections]
mobase = ["mobase"]
wizard = ["wizard"]
[tool.ruff.lint.isort]
required-imports = ["from __future__ import annotations"]
section-order = [
"future",
"standard-library",
"third-party",
"first-party",
"wizard",
"mobase",
"local-folder",
]
[tool.pyright]
exclude = ["lib", "venv", "src/ui"]
typeCheckingMode = "strict"
reportMissingTypeStubs = true
reportMissingModuleSource = false
pythonPlatform = "Windows"
-7
View File
@@ -1,7 +0,0 @@
black
PyQt5
mypy
flake8
flake8-black
mobase-stubs
git+https://github.com/Holt59/bain-wizard-interpreter.git@v0.0.3
-45
View File
@@ -1,45 +0,0 @@
[flake8]
# Use black line length:
max-line-length = 88
extend-ignore =
# See https://github.com/PyCQA/pycodestyle/issues/373
E203,
exclude = lib,ui
[mypy]
warn_return_any = True
warn_unused_configs = True
namespace_packages = True
[mypy-antlr4.*]
ignore_missing_imports = True
[mypy-.ui.*]
ignore_missing_imports = True
[mypy-src.ui.*]
ignore_missing_imports = True
[mypy-wizard.antlr4.*]
ignore_errors = True
[mypy-pytest]
ignore_missing_imports = True
[tox:tox]
skipsdist = true
envlist = py38-lint
[testenv:py38-lint]
skip_install = true
deps =
black
mypy
flake8
flake8-black
mobase-stubs==2.4.0
git+https://github.com/Holt59/bain-wizard-interpreter@v0.0.3
commands =
black src --check --diff --exclude "lib" --exclude "ui"
flake8 src
mypy src
+2 -5
View File
@@ -1,7 +1,4 @@
cmake_minimum_required(VERSION 3.16)
if(DEFINED DEPENDENCIES_DIR)
include(${DEPENDENCIES_DIR}/modorganizer_super/cmake_common/src.cmake)
else()
include(../../cmake_common/src.cmake)
endif()
add_custom_target(installer_wizard ALL)
mo2_configure_python(installer_wizard MODULE)
+2 -2
View File
@@ -1,10 +1,10 @@
# -*- encoding: utf-8 -*-
"""
This file is the entry point of the module and must contain a createPlugin()
or createPlugins() function.
"""
from __future__ import annotations
import os
import site
+215 -156
View File
File diff suppressed because it is too large Load Diff
+89 -92
View File
@@ -1,18 +1,18 @@
# -*- encoding: utf-8 -*-
from __future__ import annotations
import os
import re
import sys
from collections import defaultdict
from pathlib import Path
from typing import Dict, List, Optional, Union
from typing import Dict, List, Optional, Sequence, Union, cast
from PyQt6 import QtWidgets
from PyQt6.QtWidgets import QApplication
from wizard.runner import WizardRunnerState
import mobase
from PyQt5 import QtWidgets
# MO2 ships with PyQt5, so you can use it in your plugins:
from PyQt5.QtWidgets import QApplication
from wizard.runner import WizardRunnerState
from .dialog import WizardInstallerDialog
from .runner import make_interpreter
@@ -20,7 +20,6 @@ from .utils import make_ini_tweaks, merge_ini_tweaks
class WizardInstaller(mobase.IPluginInstallerSimple):
"""
This is the actual plugin. MO2 has two types of installer plugin, this one is
"simple", i.e., it will work directly on the file-tree contained in the archive.
@@ -28,22 +27,19 @@ class WizardInstaller(mobase.IPluginInstallerSimple):
it is valid (for this installer) and then modify it if required before extraction.
"""
# Regex used to parse settings:
# regex used to parse settings
RE_DESCRIPTION = re.compile(r"select([0-9]+)-description")
RE_OPTION = re.compile(r"select([0-9]+)-option([0-9]+)")
_organizer: mobase.IOrganizer
# List of selected options:
# list of selected options
_installerOptions: Dict[str, List[str]]
_installerUsed: bool
def __init__(self):
super().__init__()
# Method for IPlugin - I will not details these here since those are quite
# self-explanatory and are common to all plugins:
def init(self, organizer: mobase.IOrganizer):
self._organizer = organizer
return True
@@ -52,13 +48,13 @@ class WizardInstaller(mobase.IPluginInstallerSimple):
return "BAIN Wizard Installer"
def localizedName(self) -> str:
return self.__tr("BAIN Wizard Installer")
return self.tr("BAIN Wizard Installer")
def author(self):
return "Holt59"
def description(self):
return self.__tr("Installer for BAIN archive containing wizard scripts.")
return self.tr("Installer for BAIN archive containing wizard scripts.")
def version(self):
return mobase.VersionInfo(1, 0, 2)
@@ -79,28 +75,31 @@ class WizardInstaller(mobase.IPluginInstallerSimple):
"prefer OMOD installer over this one when possible",
False,
),
# Above FOMOD:
# above FOMOD?
mobase.PluginSetting("priority", "priority of this installer", 120),
]
# Method for IPluginInstallerSimple:
# method for IPluginInstallerSimple
def priority(self):
return self._organizer.pluginSetting(self.name(), "priority")
def priority(self) -> int:
return cast(int, self._organizer.pluginSetting(self.name(), "priority"))
def isManualInstaller(self) -> bool:
return False
def onInstallationStart(
self, archive: str, reinstallation: bool, mod: Optional[mobase.IModInterface]
self,
archive: str,
reinstallation: bool,
current_mod: Optional[mobase.IModInterface],
):
self._installerUsed = False
self._installerOptions = {}
if mod:
settings = mod.pluginSettings(self.name())
if current_mod:
settings = current_mod.pluginSettings(self.name())
# First extract the description:
# first extract the description
descriptions: Dict[int, str] = {}
options: Dict[int, Dict[int, str]] = defaultdict(dict)
for setting, value in settings.items():
@@ -122,19 +121,23 @@ class WizardInstaller(mobase.IPluginInstallerSimple):
self._installerOptions[desc].append(options[kdesc][index])
def onInstallationEnd(
self, result: mobase.InstallResult, mod: Optional[mobase.IModInterface]
self, result: mobase.InstallResult, new_mod: Optional[mobase.IModInterface]
):
if result != mobase.InstallResult.SUCCESS or not self._installerUsed or not mod:
if (
result != mobase.InstallResult.SUCCESS
or not self._installerUsed
or not new_mod
):
return
mod.clearPluginSettings(self.name())
new_mod.clearPluginSettings(self.name())
for i, desc in enumerate(self._installerOptions):
mod.setPluginSetting(self.name(), f"select{i}-description", desc)
new_mod.setPluginSetting(self.name(), f"select{i}-description", desc)
for iopt, opt in enumerate(self._installerOptions[desc]):
mod.setPluginSetting(self.name(), f"select{i}-option{iopt}", opt)
new_mod.setPluginSetting(self.name(), f"select{i}-option{iopt}", opt)
def _hasFomodInstaller(self) -> bool:
# Do not consider the NCC installer.
# do not consider the NCC installer
return self._organizer.isPluginEnabled("Fomod Installer")
def _hasOmodInstaller(self) -> bool:
@@ -160,16 +163,16 @@ class WizardInstaller(mobase.IPluginInstallerSimple):
if entry:
return tree
if len(tree) == 1 and isinstance(tree[0], mobase.IFileTree):
return self._getWizardArchiveBase(tree[0], data_name, checker)
if len(tree) == 1 and isinstance((root := tree[0]), mobase.IFileTree):
return self._getWizardArchiveBase(root, data_name, checker)
return None
def _getEntriesToExtract(
self,
tree: mobase.IFileTree,
extensions: List[str] = ["png", "jpg", "jpeg", "gif", "bmp", "ini"],
) -> List[mobase.FileTreeEntry]:
extensions: Sequence[str] = ["png", "jpg", "jpeg", "gif", "bmp", "ini"],
) -> list[mobase.FileTreeEntry]:
"""
Retrieve all the entries to extract from the given tree.
@@ -180,7 +183,7 @@ class WizardInstaller(mobase.IPluginInstallerSimple):
Returns:
A list of entries corresponding to files with the given extensions.
"""
entries = []
entries: list[mobase.FileTreeEntry] = []
def fn(path: str, entry: mobase.FileTreeEntry):
if entry.isFile() and entry.hasSuffix(extensions):
@@ -203,21 +206,19 @@ class WizardInstaller(mobase.IPluginInstallerSimple):
True if the file-tree can be installed, false otherwise.
"""
# Retrieve the name of the "data" folder:
# retrieve the name of the "data" folder
data_name = self._organizer.managedGame().dataDirectory().dirName()
# Retrieve the mod-data-checker:
checker: mobase.ModDataChecker = self._organizer.managedGame().feature(
mobase.ModDataChecker # type: ignore
)
# retrieve the mod-data-checker
checker = self._organizer.gameFeatures().gameFeature(mobase.ModDataChecker)
# Retrieve the base:
# retrieve the base
base = self._getWizardArchiveBase(tree, data_name, checker)
if not base:
return False
# Check FOMOD:
# check FOMOD for priority
fomod = base.exists("fomod/ModuleConfig.xml")
if (
fomod
@@ -233,9 +234,9 @@ class WizardInstaller(mobase.IPluginInstallerSimple):
def install(
self,
name: mobase.GuessedString,
otree: mobase.IFileTree,
tree: mobase.IFileTree,
version: str,
modId: int,
nexus_id: int,
) -> Union[mobase.InstallResult, mobase.IFileTree]:
"""
Perform the actual installation.
@@ -243,9 +244,9 @@ class WizardInstaller(mobase.IPluginInstallerSimple):
Args:
name: The "name" of the mod. This can be updated to change the name of the
mod.
otree: The original archive tree.
tree: The original archive tree.
version: The original version of the mod.
modId: The original ID of the mod.
nexus_id: The original ID of the mod.
Returns: We either return the modified file-tree (if the installation was
successful), or a InstallResult otherwise.
@@ -255,16 +256,14 @@ class WizardInstaller(mobase.IPluginInstallerSimple):
of the mod, in case those were updated by the installer.
"""
# Retrieve the name of the "data" folder:
# retrieve the name of the "data" folder
data_name = self._organizer.managedGame().dataDirectory().dirName()
# Retrieve the mod-data-checker:
checker: mobase.ModDataChecker = self._organizer.managedGame().feature(
mobase.ModDataChecker # type: ignore
)
# retrieve the mod-data-checker
checker = self._organizer.gameFeatures().gameFeature(mobase.ModDataChecker)
# Retrive the "base" folder:
base = self._getWizardArchiveBase(otree, data_name, checker)
# retrieve the "base" folder
base = self._getWizardArchiveBase(tree, data_name, checker)
if not base or not checker:
return mobase.InstallResult.NOT_ATTEMPTED
@@ -272,9 +271,9 @@ class WizardInstaller(mobase.IPluginInstallerSimple):
if wizard is None:
return mobase.InstallResult.NOT_ATTEMPTED
to_extract = self._getEntriesToExtract(otree)
to_extract = self._getEntriesToExtract(tree)
# Extract the script:
# extract the script
paths = self._manager().extractFiles([wizard] + to_extract, silent=False)
if len(paths) != len(to_extract) + 1:
return mobase.InstallResult.FAILED
@@ -290,29 +289,30 @@ class WizardInstaller(mobase.IPluginInstallerSimple):
name,
{
Path(entry.path()): Path(path)
for entry, path in zip(to_extract, paths[1:])
for entry, path in zip(to_extract, paths[1:], strict=True)
if not path.endswith(".ini")
},
self._installerOptions,
self._parentWidget(),
)
dialog.scriptButtonClicked.connect(lambda: os.startfile(script)) # type: ignore
dialog.scriptButtonClicked.connect( # pyright: ignore[reportUnknownMemberType, reportAttributeAccessIssue]
lambda: os.startfile(script)
)
# Note: Unlike the official installer, we do not have a "silent" setting,
# but it is really simple to add it.
if dialog.exec() == QtWidgets.QDialog.Accepted:
# We update the name with the user specified one:
# unlike the official installer, we do not have a "silent" setting, but it is
# really simple to add it
if dialog.exec() == QtWidgets.QDialog.DialogCode.Accepted:
# we update the name with the user specified one
name.update(dialog.name(), mobase.GuessQuality.USER)
# Create the tree with all the sub-packages:
tree = otree.createOrphanTree()
# create the tree with all the sub-packages
new_tree = tree.createOrphanTree()
for subpackage in dialog.subpackages():
entry = base.find(subpackage)
# Should never happens since we fetch the subpackage for the archive:
# should never happens since we fetch the subpackage for the archive
if not entry or not isinstance(entry, mobase.IFileTree):
print(
f"SubPackage {subpackage} not found in the archive.",
@@ -320,50 +320,48 @@ class WizardInstaller(mobase.IPluginInstallerSimple):
)
continue
tree.merge(entry)
new_tree.merge(entry)
# Handle renames:
# handle renames
for original, new in dialog.renames().items():
# Entry should be at the root:
entry = tree.find(original)
# entry should be at the root
entry = new_tree.find(original)
if not entry:
print(f"Plugin {original} not found, cannot rename.")
continue
tree.move(entry, new)
new_tree.move(entry, new)
# Move not selected plugins to optional:
# move not selected plugins to optional
for plugin, enabled in dialog.plugins().items():
if not enabled:
entry = tree.find(plugin)
entry = new_tree.find(plugin)
if not entry:
continue # silently fail since the plugin should be disabled
tree.addDirectory("optional").insert(entry)
new_tree.addDirectory("optional").insert(entry)
# TODO: INI Tweaks:
alltweaks = dialog.tweaks()
for filename, tweaks in alltweaks.items():
# Find the original file (if any):
o_entry = tree.find(filename)
# find the original file (if any)
o_entry = new_tree.find(filename)
o_filename: Optional[str] = None
if o_entry:
# Find the filepath from the list of extracted files:
# find the filepath from the list of extracted files
index = to_extract.index(o_entry)
# +1 because the first one is the script.
# +1 because the first one is the script
o_filename = paths[index + 1]
# If the file existed before, we keep the new one at the same
# place:
# if the file existed before, we keep the new one at the same place
if o_entry or Path(filename).parts[0].lower() == "ini tweaks":
entry = tree.addFile(filename, replace_if_exists=True)
entry = new_tree.addFile(filename, replace_if_exists=True)
# Otherwise we create it in INI Tweaks
# otherwise we create it in INI Tweaks
else:
entry = tree.addFile(
entry = new_tree.addFile(
os.path.join("INI Tweaks", filename), replace_if_exists=True
)
@@ -377,24 +375,23 @@ class WizardInstaller(mobase.IPluginInstallerSimple):
with open(filepath, "w") as fp:
fp.write(data)
# Mark stuff for saving:
# mark stuff for saving
self._installerUsed = True
self._installerOptions = dict(dialog.selectedOptions())
# Return the tree:
return tree
return new_tree
# If user requested a manual installation, we update the name (to keep it
# in the manual installation dialog) and just notify the installation manager:
# if user requested a manual installation, we update the name (to keep it
# in the manual installation dialog) and just notify the installation manager
elif dialog.isManualRequested():
name.update(dialog.name(), mobase.GuessQuality.USER)
return mobase.InstallResult.MANUAL_REQUESTED
# If user canceled, we simply notify the installation manager:
# if user canceled, we simply notify the installation manager
else:
return mobase.InstallResult.CANCELED
def __tr(self, str) -> str:
# We need this to translate string in Python. Check the common documentation
# for more details:
return QApplication.translate("WizardInstaller", str)
def tr(self, value: str) -> str:
# we need this to translate string in Python. Check the common documentation
# for more details
return QApplication.translate("WizardInstaller", value)
+95 -92
View File
@@ -1,153 +1,156 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS><TS version="2.0">
<context>
<!DOCTYPE TS>
<TS version="2.1">
<context>
<name>WizardInstaller</name>
<message>
<location filename="installer.py" line="61"/>
<source>Installer for BAIN archive containing wizard scripts.</source>
<translation type="unfinished"></translation>
<location filename="installer.py" line="52" />
<source>BAIN Wizard Installer</source>
<translation type="unfinished" />
</message>
<message>
<location filename="installer.py" line="55"/>
<source>BAIN Wizard Installer</source>
<translation type="unfinished"></translation>
<location filename="installer.py" line="58" />
<source>Installer for BAIN archive containing wizard scripts.</source>
<translation type="unfinished" />
</message>
</context>
<context>
</context>
<context>
<name>WizardInstallerComplete</name>
<message>
<location filename="ui/wizardinstallercomplete.ui" line="40"/>
<source>The installer script has finished. The following sub-packages and plugins will be installed.</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallercomplete.ui" line="0" />
<source>The installer script has finished. The following sub-packages and plugins will be installed.</source>
<translation type="unfinished" />
</message>
<message>
<location filename="ui/wizardinstallercomplete.ui" line="111"/>
<source>Sub-Packages:</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallercomplete.ui" line="0" />
<source>Sub-Packages:</source>
<translation type="unfinished" />
</message>
<message>
<location filename="ui/wizardinstallercomplete.ui" line="128"/>
<source>Plugins:</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallercomplete.ui" line="0" />
<source>Plugins:</source>
<translation type="unfinished" />
</message>
<message>
<location filename="ui/wizardinstallercomplete.ui" line="180"/>
<source>INI Tweaks:</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallercomplete.ui" line="0" />
<source>INI Tweaks:</source>
<translation type="unfinished" />
</message>
<message>
<location filename="ui/wizardinstallercomplete.ui" line="236"/>
<source>Notes:</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallercomplete.ui" line="0" />
<source>Notes:</source>
<translation type="unfinished" />
</message>
</context>
<context>
</context>
<context>
<name>WizardInstallerDialog</name>
<message>
<location filename="ui/wizardinstallerdialog.ui" line="102"/>
<source>Next</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallerdialog.ui" line="0" />
<location filename="dialog.py" line="688" />
<source>Next</source>
<translation type="unfinished" />
</message>
<message>
<location filename="dialog.py" line="635"/>
<source>Install anyway</source>
<translation type="unfinished"></translation>
<location filename="dialog.py" line="690" />
<source>Install anyway</source>
<translation type="unfinished" />
</message>
<message>
<location filename="dialog.py" line="639"/>
<source>Install</source>
<translation type="unfinished"></translation>
<location filename="dialog.py" line="694" />
<source>Install</source>
<translation type="unfinished" />
</message>
<message>
<location filename="ui/wizardinstallerdialog.ui" line="14"/>
<source>BAIN Wizard Installer</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallerdialog.ui" line="0" />
<source>BAIN Wizard Installer</source>
<translation type="unfinished" />
</message>
<message>
<location filename="ui/wizardinstallerdialog.ui" line="25"/>
<source>Name</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallerdialog.ui" line="0" />
<source>Name</source>
<translation type="unfinished" />
</message>
<message>
<location filename="ui/wizardinstallerdialog.ui" line="56"/>
<source>Manual</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallerdialog.ui" line="0" />
<source>Manual</source>
<translation type="unfinished" />
</message>
<message>
<location filename="ui/wizardinstallerdialog.ui" line="66"/>
<source>Script</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallerdialog.ui" line="0" />
<source>Script</source>
<translation type="unfinished" />
</message>
<message>
<location filename="ui/wizardinstallerdialog.ui" line="92"/>
<source>Back</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallerdialog.ui" line="0" />
<source>Back</source>
<translation type="unfinished" />
</message>
<message>
<location filename="ui/wizardinstallerdialog.ui" line="109"/>
<source>Cancel</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallerdialog.ui" line="0" />
<source>Cancel</source>
<translation type="unfinished" />
</message>
</context>
<context>
</context>
<context>
<name>WizardInstallerPage</name>
<message>
<location filename="ui/wizardinstallerpage.ui" line="114"/>
<source>Options:</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallerpage.ui" line="0" />
<source>Options:</source>
<translation type="unfinished" />
</message>
<message>
<location filename="ui/wizardinstallerpage.ui" line="148"/>
<source>Description:</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallerpage.ui" line="0" />
<source>Description:</source>
<translation type="unfinished" />
</message>
</context>
<context>
</context>
<context>
<name>WizardInstallerRequires</name>
<message>
<location filename="ui/wizardinstallerrequires.ui" line="34"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Warning:&lt;/span&gt; The following version requirements are not met for using this installer.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallerrequires.ui" line="0" />
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=" font-weight:600;"&gt;Warning:&lt;/span&gt; The following version requirements are not met for using this installer.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished" />
</message>
<message>
<location filename="ui/wizardinstallerrequires.ui" line="44"/>
<source>Requirements</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallerrequires.ui" line="0" />
<source>Requirements</source>
<translation type="unfinished" />
</message>
<message>
<location filename="ui/wizardinstallerrequires.ui" line="52"/>
<source>Graphics Extender</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallerrequires.ui" line="0" />
<source>Graphics Extender</source>
<translation type="unfinished" />
</message>
<message>
<location filename="ui/wizardinstallerrequires.ui" line="76"/>
<source>Wrye Bash</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallerrequires.ui" line="0" />
<source>Wrye Bash</source>
<translation type="unfinished" />
</message>
<message>
<location filename="ui/wizardinstallerrequires.ui" line="86"/>
<source>Need</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallerrequires.ui" line="0" />
<source>Need</source>
<translation type="unfinished" />
</message>
<message>
<location filename="ui/wizardinstallerrequires.ui" line="103"/>
<source>Game</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallerrequires.ui" line="0" />
<source>Game</source>
<translation type="unfinished" />
</message>
<message>
<location filename="ui/wizardinstallerrequires.ui" line="151"/>
<source>N/A</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallerrequires.ui" line="0" />
<location filename="ui\wizardinstallerrequires.ui" line="0" />
<source>N/A</source>
<translation type="unfinished" />
</message>
<message>
<location filename="ui/wizardinstallerrequires.ui" line="141"/>
<source>Have</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallerrequires.ui" line="0" />
<source>Have</source>
<translation type="unfinished" />
</message>
<message>
<location filename="ui/wizardinstallerrequires.ui" line="165"/>
<source>Script Extender</source>
<translation type="unfinished"></translation>
<location filename="ui\wizardinstallerrequires.ui" line="0" />
<source>Script Extender</source>
<translation type="unfinished" />
</message>
</context>
</context>
</TS>
+28 -35
View File
@@ -1,19 +1,19 @@
# -*- encoding: utf-8 -*-
from __future__ import annotations
import sys
from pathlib import Path
from typing import Iterable, List, Optional
from typing import Any, Iterable, List, Optional
import mobase
from wizard.interpreter import WizardInterpreter
from wizard.manager import ManagerModInterface
from wizard.severity import SeverityContext
from wizard.utils import make_runner_context_factory
from wizard.value import SubPackage, SubPackages
import mobase
class MO2SubPackage(SubPackage):
_tree: mobase.IFileTree
_files: List[str]
@@ -21,12 +21,11 @@ class MO2SubPackage(SubPackage):
super().__init__(tree.name())
self._tree = tree
# We cannot perform lazy iteration on the tree in a Python way so we
# have to list the files:
# we cannot perform lazy iteration on the tree in a Python way so we
# have to list the files
self._files = []
def fn(folder, entry) -> mobase.IFileTree.WalkReturn:
def fn(folder: str, entry: mobase.FileTreeEntry) -> mobase.IFileTree.WalkReturn:
self._files.append(entry.path())
return mobase.IFileTree.CONTINUE
@@ -38,7 +37,6 @@ class MO2SubPackage(SubPackage):
class MO2SeverityContext(SeverityContext):
_organizer: mobase.IOrganizer
def __init__(self, organizer: mobase.IOrganizer):
@@ -50,21 +48,17 @@ class MO2SeverityContext(SeverityContext):
class MO2ManagerModInterface(ManagerModInterface):
_organizer: mobase.IOrganizer
_game: mobase.IPluginGame
_subpackages: SubPackages
def __init__(self, tree: mobase.IFileTree, organizer: mobase.IOrganizer):
self._organizer = organizer
self._game = organizer.managedGame()
checker: mobase.ModDataChecker = self._game.feature(
mobase.ModDataChecker # type: ignore
)
checker = self._organizer.gameFeatures().gameFeature(mobase.ModDataChecker)
# Read the subpackages:
# read the sub-packages
self._subpackages = SubPackages()
for entry in tree:
if isinstance(entry, mobase.IFileTree):
@@ -73,12 +67,12 @@ class MO2ManagerModInterface(ManagerModInterface):
self._subpackages.append(MO2SubPackage(entry))
continue
# Add entry with INI tweaks:
# add entry with INI tweaks
if entry.exists("INI Tweaks") or entry.exists("INI"):
self._subpackages.append(MO2SubPackage(entry))
continue
# We add folder with format "XXX Docs" where "XXX" is a number.
# we add folder with format "XXX Docs" where "XXX" is a number
parts = entry.name().split()
if (
len(parts) >= 2
@@ -102,7 +96,7 @@ class MO2ManagerModInterface(ManagerModInterface):
return 0
def compareSEVersion(self, version: str) -> int:
se = self._game.feature(mobase.ScriptExtender) # type: ignore
se = self._organizer.gameFeatures().gameFeature(mobase.ScriptExtender)
if not se:
return 1
v1 = mobase.VersionInfo(version)
@@ -115,11 +109,11 @@ class MO2ManagerModInterface(ManagerModInterface):
return 0
def compareGEVersion(self, version: str) -> int:
# Cannot do th is in MO2.
# cannot do th is in MO2
return 1
def compareWBVersion(self, version: str) -> int:
# Cannot do this in MO2.
# cannot do this in MO2
return 1
def _resolve(self, filepath: str) -> Optional[Path]:
@@ -133,8 +127,8 @@ class MO2ManagerModInterface(ManagerModInterface):
The path to the given file on the disk, or one of the file mapping
to it in the VFS, or None if the file does not exists.
"""
# TODO: This does not handle weird path that go back (..) and
# then in data again, e.g. ../data/xxx.esp.
# TODO: This does not handle weird path that go back (..) and then in data
# again, e.g. ../data/xxx.esp.
path: Optional[Path]
if filepath.startswith(".."):
path = Path(self._game.dataDirectory().absoluteFilePath(filepath))
@@ -160,7 +154,7 @@ class MO2ManagerModInterface(ManagerModInterface):
def getPluginLoadOrder(self, filename: str, fallback: int = -1) -> int:
return self._organizer.pluginList().loadOrder(filename)
def getPluginStatus(self, filename) -> int:
def getPluginStatus(self, filename: str) -> int:
state = self._organizer.pluginList().state(filename)
if state == mobase.PluginState.ACTIVE:
@@ -169,25 +163,24 @@ class MO2ManagerModInterface(ManagerModInterface):
return 0 # Or 1?
return -1
def getFilename(self, filepath: str) -> str:
path = self._resolve(filepath)
if path:
if path.is_file():
return path.name
def getFilename(self, path: str) -> str:
path_ = self._resolve(path)
if path_:
if path_.is_file():
return path_.name
return ""
def getFolder(self, filepath: str) -> str:
path = self._resolve(filepath)
if path:
if path.is_dir():
return path.name
def getFolder(self, path: str) -> str:
path_ = self._resolve(path)
if path_:
if path_.is_dir():
return path_.name
return ""
def make_interpreter(
base: mobase.IFileTree, organizer: mobase.IOrganizer
) -> WizardInterpreter:
) -> WizardInterpreter[Any]:
manager = MO2ManagerModInterface(base, organizer)
severity = MO2SeverityContext(organizer)
+5 -2
View File
@@ -27,7 +27,7 @@
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,1,0,1">
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,2,0,1">
<property name="spacing">
<number>6</number>
</property>
@@ -136,7 +136,10 @@
<string/>
</property>
<property name="scaledContents">
<bool>true</bool>
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
+26 -28
View File
@@ -1,15 +1,15 @@
# -*- encoding: utf-8 -*-
from __future__ import annotations
import re
from collections.abc import Sequence
from pathlib import Path
from typing import Dict, List, Mapping
from typing import cast
from wizard.tweaks import WizardINISetting, WizardINISettingEdit
def make_obscript_ini_tweaks(tweaks: List[WizardINISetting]) -> str:
lines = []
def make_obscript_ini_tweaks(tweaks: Sequence[WizardINISetting]) -> str:
lines: list[str] = []
for tweak in tweaks:
if not isinstance(tweak, WizardINISettingEdit):
@@ -23,14 +23,13 @@ def make_obscript_ini_tweaks(tweaks: List[WizardINISetting]) -> str:
return "\n".join(["; Generated by Mod Organizer 2 via Wizard"] + sorted(lines))
def make_standard_ini_tweaks(tweaks: List[WizardINISetting]) -> str:
# Group Tweaks per section:
sections: Mapping[str, List[WizardINISetting]] = {m.section: [] for m in tweaks}
def make_standard_ini_tweaks(tweaks: Sequence[WizardINISetting]) -> str:
# group Tweaks per section
sections: dict[str, list[WizardINISetting]] = {m.section: [] for m in tweaks}
for m in tweaks:
sections[m.section].append(m)
lines = []
lines: list[str] = []
for k in sorted(sections):
s_tweaks = sorted(sections[k], key=lambda m: m.setting)
@@ -48,16 +47,15 @@ def make_standard_ini_tweaks(tweaks: List[WizardINISetting]) -> str:
return "\n".join(lines[:-1])
def merge_standard_ini_tweaks(tweaks: List[WizardINISetting], file: Path) -> str:
def merge_standard_ini_tweaks(tweaks: Sequence[WizardINISetting], file: Path) -> str:
import sys
print(f"Cannot merge INI Tweaks for {file.name}.", file=sys.stderr)
return make_standard_ini_tweaks(tweaks)
def merge_obscript_ini_tweaks(tweaks: List[WizardINISetting], file: Path) -> str:
# This is from Wrye Bash (and the function is inspired from Wrye Bash):
def merge_obscript_ini_tweaks(tweaks: Sequence[WizardINISetting], file: Path) -> str:
# this is from Wrye Bash (and the function is inspired from Wrye Bash)
reComment = re.compile(";.*", re.U)
reDeleted = re.compile("" r";-(\w.*?)$", re.U)
reSet = re.compile("" r"\s*set\s+(.+?)\s+to\s+(.*)", re.I | re.U)
@@ -70,20 +68,20 @@ def merge_obscript_ini_tweaks(tweaks: List[WizardINISetting], file: Path) -> str
(reSetNGS, "setnumericgamesetting", "SetNumericGameSetting {} {}"),
)
def _parse_obse_line(line):
def _parse_obse_line(line: str):
for regex, sectionKey, format_string in _regex_tuples:
match = regex.match(line)
if match:
return match, sectionKey, format_string
return None, None, None
# Read the original file:
# read the original file
with open(file, "r") as fp:
olines = fp.readlines()
# Map setting name to value:
settings: Dict[str, Dict[str, WizardINISettingEdit]] = {}
deleted: Dict[str, Dict[str, WizardINISetting]] = {}
# map setting name to value
settings: dict[str, dict[str, WizardINISettingEdit]] = {}
deleted: dict[str, dict[str, WizardINISetting]] = {}
for tweak in tweaks:
if isinstance(tweak, WizardINISettingEdit):
if tweak.section not in settings:
@@ -94,8 +92,8 @@ def merge_obscript_ini_tweaks(tweaks: List[WizardINISetting], file: Path) -> str
deleted[tweak.section.lower()] = {}
deleted[tweak.section.lower()][tweak.setting] = tweak
# Create the lines:
lines = []
# create the lines
lines: list[str] = []
for line in olines:
line = line.rstrip()
maDeleted = reDeleted.match(line)
@@ -108,13 +106,14 @@ def merge_obscript_ini_tweaks(tweaks: List[WizardINISetting], file: Path) -> str
match, section_key, format_string = _parse_obse_line(stripped)
if match:
assert format_string is not None
setting = match.group(1)
if section_key in settings and setting in settings[section_key]:
value = settings[section_key][setting].value
line = format_string.format(setting, value)
comment = ""
if settings[section_key][setting].comment:
comment = settings[section_key][setting].comment # type: ignore
comment = cast(str, settings[section_key][setting].comment)
comment += " "
comment += f"(set by MO2 via Wizard, was {match.group(2)})"
line = f"{line} ; {comment}"
@@ -129,6 +128,7 @@ def merge_obscript_ini_tweaks(tweaks: List[WizardINISetting], file: Path) -> str
lines.append(line)
for section in settings.values():
line = ""
for setting in section.values():
if setting.section.lower() == "set":
line = f"{setting.section} {setting.setting} to {setting.value}"
@@ -146,26 +146,24 @@ def merge_obscript_ini_tweaks(tweaks: List[WizardINISetting], file: Path) -> str
return "\n".join(lines)
def make_ini_tweaks(tweaks: List[WizardINISetting]) -> str:
def make_ini_tweaks(tweaks: Sequence[WizardINISetting]) -> str:
is_set = [
tw.section.lower() in ("set", "setgs", "setnumericgamesetting") for tw in tweaks
]
# Assume there is no mix.
# assume there is no mix
if all(is_set):
return make_obscript_ini_tweaks(tweaks)
else:
return make_standard_ini_tweaks(tweaks)
def merge_ini_tweaks(tweaks: List[WizardINISetting], file: Path) -> str:
def merge_ini_tweaks(tweaks: Sequence[WizardINISetting], file: Path) -> str:
is_set = [
tw.section.lower() in ("set", "setgs", "setnumericgamesetting") for tw in tweaks
]
# Assume there is no mix.
# assume there is no mix
if all(is_set):
return merge_obscript_ini_tweaks(tweaks, file)
else:

Some files were not shown because too many files have changed in this diff Show More