From 67b8c01fadfeb2649cb4e671e8f033e6a40d5f11 Mon Sep 17 00:00:00 2001 From: osfanbuff63 Date: Mon, 17 Apr 2023 15:37:39 -0400 Subject: [PATCH 1/7] feat(unsupported warnings): begin work on downgrade warnings BREAKING CHANGE: The format of the version file has been updated, and it will no longer work with older versions of Vanilla Installer. Fixes #80 --- pyproject.toml | 2 +- vanilla_installer/assets/versions.json | 73 ++++++++++++++-- vanilla_installer/gui.py | 1 - vanilla_installer/log.py | 18 ++-- vanilla_installer/main.py | 111 +++++++++++++++++++------ 5 files changed, 165 insertions(+), 40 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4a3099f..54c0b30 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ description = "An installer of Fabulously Optimized for the vanilla launcher." authors = [ "osfanbuff63 ", "nsde ", - "Kichura " + "Kichura " ] documentation = "https://fabulously-optimized.gitbook.io/vanilla-installer" homepage = "https://fabulously-optimized.gitbook.io/vanilla-installer" diff --git a/vanilla_installer/assets/versions.json b/vanilla_installer/assets/versions.json index 83e8e8e..b2f6769 100644 --- a/vanilla_installer/assets/versions.json +++ b/vanilla_installer/assets/versions.json @@ -1,6 +1,69 @@ { - "1.19.4": "https://raw.githubusercontent.com/Fabulously-Optimized/fabulously-optimized/main/Packwiz/1.19.4/pack.toml", - "1.18.2": "https://raw.githubusercontent.com/Fabulously-Optimized/fabulously-optimized/main/Packwiz/1.18.2/pack.toml", - "1.17.1": "https://raw.githubusercontent.com/Fabulously-Optimized/fabulously-optimized/main/Packwiz/1.17.1/pack.toml", - "1.16.5": "https://raw.githubusercontent.com/Fabulously-Optimized/fabulously-optimized/main/Packwiz/1.16.5/pack.toml" -} + "format_version": 2, + "versions": { + "1.19.4": { + "packwiz": "https://raw.githubusercontent.com/Fabulously-Optimized/fabulously-optimized/main/Packwiz/1.19.4/pack.toml", + "major_version": 4, + "enabled": true + }, + "1.19.3": { + "major_version": 4, + "enabled": false + }, + "1.19.2": { + "major_version": 4, + "enabled": false + }, + "1.19.1": { + "major_version": 4, + "enabled": false + }, + "1.19": { + "major_version": 4, + "enabled": false + }, + "1.18.2": { + "packwiz": "https://raw.githubusercontent.com/Fabulously-Optimized/fabulously-optimized/main/Packwiz/1.18.2/pack.toml", + "major_version": 3, + "enabled": true + }, + "1.18.1": { + "major_version": 3, + "enabled": false + }, + "1.18": { + "major_version": 3, + "enabled": false + }, + "1.17.1": { + "packwiz": "https://raw.githubusercontent.com/Fabulously-Optimized/fabulously-optimized/main/Packwiz/1.17.1/pack.toml", + "major_version": 2, + "enabled": true + }, + "1.17": { + "major_version": 2, + "enabled": false + }, + "1.16.5": { + "packwiz": "https://raw.githubusercontent.com/Fabulously-Optimized/fabulously-optimized/main/Packwiz/1.16.5/pack.toml", + "major_version": 1, + "enabled": true + }, + "1.16.4": { + "major_version": 1, + "enabled": false + }, + "1.16.3": { + "major_version": 1, + "enabled": false + }, + "1.16.2": { + "major_version": 1, + "enabled": false + }, + "1.16.1": { + "major_version": 1, + "enabled": false + } + } +} \ No newline at end of file diff --git a/vanilla_installer/gui.py b/vanilla_installer/gui.py index e4361e2..87c4289 100644 --- a/vanilla_installer/gui.py +++ b/vanilla_installer/gui.py @@ -203,7 +203,6 @@ def setupUi(self, MainWindow: QMainWindow) -> None: Ui_MainWindow.getAsset("settings.svg"), self.settingsButton ) self.settingsButtonIcon.setGeometry(70, 0, 24, 24) - self.windowIcon = Ui_MainWindow.getAsset("icon.png") MainWindow.setWindowIcon(QIcon(self.windowIcon)) diff --git a/vanilla_installer/log.py b/vanilla_installer/log.py index ee3a641..cfd1781 100644 --- a/vanilla_installer/log.py +++ b/vanilla_installer/log.py @@ -6,8 +6,8 @@ import logging import logging.handlers # pylance moment -from pathlib import Path import sys +from pathlib import Path class LoggerWriter: @@ -16,9 +16,9 @@ def __init__(self, logfct): self.buf = [] def write(self, msg): - if msg.endswith('\n'): - self.buf.append(msg.removesuffix('\n')) - self.logfct(''.join(self.buf)) + if msg.endswith("\n"): + self.buf.append(msg.removesuffix("\n")) + self.logfct("".join(self.buf)) self.buf = [] else: self.buf.append(msg) @@ -35,11 +35,11 @@ def flush(self): with logfile_path as file: open(file, "x", encoding="utf-8").write("") handler = logging.handlers.RotatingFileHandler( - filename=logfile_path, - encoding="utf-8", - maxBytes=32 * 1024 * 1024, # 32 MiB - backupCount=5, # Rotate through 5 files - ) + filename=logfile_path, + encoding="utf-8", + maxBytes=32 * 1024 * 1024, # 32 MiB + backupCount=5, # Rotate through 5 files +) dt_fmt = "%Y-%m-%d %H:%M:%S" formatter = logging.Formatter( diff --git a/vanilla_installer/main.py b/vanilla_installer/main.py index effcb14..02d78af 100644 --- a/vanilla_installer/main.py +++ b/vanilla_installer/main.py @@ -13,7 +13,7 @@ import subprocess import zipfile from pathlib import Path -from typing import Optional +from typing import Optional, Union import click import minecraft_launcher_lib as mll @@ -28,6 +28,12 @@ FOLDER_LOC = "" +class UnsupportedFormatVersion(Exception): + """The format version is not supported by this program version.""" + + pass + + def set_dir(path: str = mll.utils.get_minecraft_directory()) -> str | None: """ Sets the Minecraft game directory. @@ -376,34 +382,79 @@ def create_profile(mc_dir: str, version_id: str) -> None: launcher_profiles_path.write_text(profiles_json) -def get_pack_mc_versions() -> dict: +def log_installed_version( + version: Union[str, int, float], install_dir: Union[str, bytes, os.PathLike] +) -> None: + """Log the version of Minecraft that FO has been installed for. Used to find out later + + Args: + version (Union[str, int, float]): The version to log. + install_dir (Union[str, bytes, os.PathLike]): The directory that FO was installed to. """ - Gets a list of all the versions FO currently supports. + dir_path = Path(install_dir).resolve() / ".fabulously-optimized" + dir_path.mkdir(exist_ok=True) + file_path = dir_path / "mc_version.txt" + if file_path.exists() is False: + file_path.touch() + with file_path.open("w") as file: + file.write(str(version)) + + +def read_versions() -> dict: + """Reads the versions.json file, either over the Internet, or locally. + + Returns: + dict: The JSON file, formatted as a dictionary. """ + SUPPORTED_FORMAT_VERSION = 2 - return_value = dict() try: + response = requests.get( + "https://raw.githubusercontent.com/Fabulously-Optimized/vanilla-installer/main/vanilla_installer/assets/versions.json" + ).json() + format_version = response["format_version"] + if response["format_version"] != SUPPORTED_FORMAT_VERSION: + raise UnsupportedFormatVersion( + f"Format version {format_version} is not supported by this version." + ) + except requests.exceptions.RequestException or response.status_code != "200": + # This should never happen unless a) there's no internet connection, b) the file was deleted or is missing in a development case. + # In this case, fall back to a local file. + logger.warning("GitHub failed, falling back to local...") try: - response = requests.get( - "https://raw.githubusercontent.com/Fabulously-Optimized/vanilla-installer/main/vanilla_installer/assets/versions.json" - ).json() - except requests.exceptions.RequestException or response.status_code != "200": - # This should never happen unless a) there's no internet connection, b) the file was deleted or is missing in a development case. - # In this case, fall back to a local file since in the latter you'll likely have the whole repo cloned. - # For this to work, you need to be in the root directory of the repository running this, otherwise the files will not be found. - logger.warning("GitHub failed, falling back to local...") - try: - local_path = ( - Path("vanilla_installer/assets").resolve() / "versions.json" - ) - except: - local_path = Path("assets").resolve() / "versions.json" - response = json.loads(local_path.read_bytes()) + local_path = Path("vanilla_installer/assets").resolve() / "versions.json" + except: + local_path = Path("assets").resolve() / "versions.json" + response = json.loads(local_path.read_bytes()) + except UnsupportedFormatVersion: + logger.exception( + "Format version was not supported - using local file. Update Vanilla Installer to fix this." + ) + try: + local_path = Path("vanilla_installer/assets").resolve() / "versions.json" + except: + local_path = Path("assets").resolve() / "versions.json" + response = json.loads(local_path.read_bytes()) + return dict(response) - return_value = dict(response) - return return_value - except requests.exceptions.RequestException as e: - logger.exception(f"Couldn't get minecraft versions: {e}") + +def get_pack_mc_versions() -> dict: + """ + Gets a list of all the versions FO currently supports. + """ + return_value = dict() + raw_dict = read_versions() + for version in raw_dict["versions"]: + raw_version = raw_dict["versions"][version] + if raw_version["enabled"] is True or raw_version["enabled"] == "true": + return_value[version] = raw_version + for key in return_value.keys(): + try: + if key["packwiz"] != "": + pass + except KeyError: + return_value.pop(key) + return return_value def convert_version(input_mcver: str) -> str: @@ -414,7 +465,7 @@ def convert_version(input_mcver: str) -> str: input_mcver (str): The Minecraft version to find. Returns: - str: The converted version as a direct JSDelivr URL. + str: The converted version as a URL. """ versions = get_pack_mc_versions() return_value = versions.get(input_mcver) @@ -424,6 +475,18 @@ def convert_version(input_mcver: str) -> str: return return_value +def downgrade_check(version: Union[str, int, float]) -> bool: + """Checks whether the given version is a downgrade from the one currently installed. + + Args: + version (Union[str, int, float]): _description_ + + Returns: + bool: Whether this is a downgrade. + """ + version_dict = read_versions() + + def run( mc_dir: str = mll.utils.get_minecraft_directory(), version: Optional[str] = None, From 5808e2b6a99fc766c9c309bea833d1969b30c4ea Mon Sep 17 00:00:00 2001 From: osfanbuff63 Date: Mon, 17 Apr 2023 18:57:44 -0400 Subject: [PATCH 2/7] Merge branch 'main' into 'feat/unsupported-warning-2' --- .github/workflows/ci.yml | 4 +- poetry.lock | 2 +- .../assets/{ => fonts}/Inter-Regular.otf | Bin .../assets/fonts/LICENSE-Inter.txt | 94 ++++++++++++++++++ .../assets/fonts/LICENSE-OpenDyslexic.txt | 94 ++++++++++++++++++ .../{ => fonts}/OpenDyslexic-Regular.otf | Bin .../assets/{ => fonts}/fonts.qrc | 0 vanilla_installer/assets/lang/en_us.json | 9 ++ vanilla_installer/cli.py | 4 +- vanilla_installer/config.py | 4 +- vanilla_installer/gui.py | 38 +++++-- vanilla_installer/i18n.py | 29 ++++++ vanilla_installer/log.py | 4 +- vanilla_installer/main.py | 5 +- vanilla_installer/theme.py | 4 +- 15 files changed, 269 insertions(+), 22 deletions(-) rename vanilla_installer/assets/{ => fonts}/Inter-Regular.otf (100%) create mode 100644 vanilla_installer/assets/fonts/LICENSE-Inter.txt create mode 100644 vanilla_installer/assets/fonts/LICENSE-OpenDyslexic.txt rename vanilla_installer/assets/{ => fonts}/OpenDyslexic-Regular.otf (100%) rename vanilla_installer/assets/{ => fonts}/fonts.qrc (100%) create mode 100644 vanilla_installer/assets/lang/en_us.json create mode 100644 vanilla_installer/i18n.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 310b430..73aaca2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,7 +72,7 @@ jobs: run: | source .venv/bin/activate pip install pyside6 - pyside6-rcc vanilla_installer/assets/fonts.qrc -o vanilla_installer/fonts.py + pyside6-rcc vanilla_installer/assets/fonts/fonts.qrc -o vanilla_installer/fonts.py pipx run poetry build --no-interaction - name: Get normalized branch name run: | @@ -126,7 +126,7 @@ jobs: ./.venv/Scripts/activate.ps1 # pip install nuitka minecraft_launcher_lib PySide6 click tomli darkdetect echo '__version__ = "${{ env.BRANCH }}+${{ steps.short-sha.outputs.sha }}"' | Out-File vanilla_installer/__init__.py - pyside6-rcc vanilla_installer/assets/fonts.qrc -o vanilla_installer/fonts.py + pyside6-rcc vanilla_installer/assets/fonts/fonts.qrc -o vanilla_installer/fonts.py python -m nuitka --standalone --onefile --windows-icon-from-ico=media/icon.ico --output-dir=build --include-package=minecraft_launcher_lib,PySide6,click,tomli,darkdetect -o "Vanilla Installer-GUI ${{ env.BRANCH }}+${{ steps.short-sha.outputs.sha }}.exe" --enable-plugin=pyside6 --include-data-dir=vanilla_installer/assets=assets/ --disable-console --nofollow-import-to=PySide6.examples vanilla_installer/gui.py --assume-yes-for-downloads - name: Upload built executable uses: actions/upload-artifact@v3 diff --git a/poetry.lock b/poetry.lock index ec35e5d..d8b4a2a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry and should not be changed by hand. +# This file is automatically @generated by Poetry 1.4.1 and should not be changed by hand. [[package]] name = "anyio" diff --git a/vanilla_installer/assets/Inter-Regular.otf b/vanilla_installer/assets/fonts/Inter-Regular.otf similarity index 100% rename from vanilla_installer/assets/Inter-Regular.otf rename to vanilla_installer/assets/fonts/Inter-Regular.otf diff --git a/vanilla_installer/assets/fonts/LICENSE-Inter.txt b/vanilla_installer/assets/fonts/LICENSE-Inter.txt new file mode 100644 index 0000000..ff80f8c --- /dev/null +++ b/vanilla_installer/assets/fonts/LICENSE-Inter.txt @@ -0,0 +1,94 @@ +Copyright (c) 2016-2020 The Inter Project Authors. +"Inter" is trademark of Rasmus Andersson. +https://github.com/rsms/inter + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION AND CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/vanilla_installer/assets/fonts/LICENSE-OpenDyslexic.txt b/vanilla_installer/assets/fonts/LICENSE-OpenDyslexic.txt new file mode 100644 index 0000000..bb86782 --- /dev/null +++ b/vanilla_installer/assets/fonts/LICENSE-OpenDyslexic.txt @@ -0,0 +1,94 @@ +Copyright (c) 2019-07-29, Abbie Gonzalez (https://abbiecod.es|support@abbiecod.es), +with Reserved Font Name OpenDyslexic. +Copyright (c) 12/2012 - 2019 +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/vanilla_installer/assets/OpenDyslexic-Regular.otf b/vanilla_installer/assets/fonts/OpenDyslexic-Regular.otf similarity index 100% rename from vanilla_installer/assets/OpenDyslexic-Regular.otf rename to vanilla_installer/assets/fonts/OpenDyslexic-Regular.otf diff --git a/vanilla_installer/assets/fonts.qrc b/vanilla_installer/assets/fonts/fonts.qrc similarity index 100% rename from vanilla_installer/assets/fonts.qrc rename to vanilla_installer/assets/fonts/fonts.qrc diff --git a/vanilla_installer/assets/lang/en_us.json b/vanilla_installer/assets/lang/en_us.json new file mode 100644 index 0000000..420c467 --- /dev/null +++ b/vanilla_installer/assets/lang/en_us.json @@ -0,0 +1,9 @@ +{ + "vanilla_installer.gui.subtitle": "Vanilla Installer", + "vanilla_installer.gui.install_button": "Install", + "vanilla_installer.gui.mc_version": "Minecraft version:", + "vanilla_installer.gui.location": "Location:", + "vanilla_installer.gui.issues_button": "Report bugs", + "vanilla_installer.gui.theme_toggle": "Toggle theme", + "vanilla_installer.gui.settings": "Settings" +} \ No newline at end of file diff --git a/vanilla_installer/cli.py b/vanilla_installer/cli.py index 2b30900..ad522ed 100644 --- a/vanilla_installer/cli.py +++ b/vanilla_installer/cli.py @@ -7,7 +7,7 @@ ## Imports import asyncio -import logging +# import logging import sys import webbrowser @@ -22,7 +22,7 @@ pass from vanilla_installer import main -logging.getLogger("asyncio").setLevel(logging.DEBUG) +# logging.getLogger("asyncio").setLevel(logging.DEBUG) @click.group( diff --git a/vanilla_installer/config.py b/vanilla_installer/config.py index 0f41bf8..c61ea88 100644 --- a/vanilla_installer/config.py +++ b/vanilla_installer/config.py @@ -3,7 +3,7 @@ """ The Configuration System for Vanilla Installer. """ - +import logging import os import platform from pathlib import Path @@ -12,7 +12,7 @@ import tomlkit from tomlkit import toml_file -from vanilla_installer.log import logger +logger = logging.getLogger(__name__) FILE_PATH = str(Path("vanilla_installer.toml").resolve()) diff --git a/vanilla_installer/gui.py b/vanilla_installer/gui.py index 87c4289..357e081 100644 --- a/vanilla_installer/gui.py +++ b/vanilla_installer/gui.py @@ -5,6 +5,7 @@ """ # IMPORTS +import logging import pathlib import platform import sys @@ -31,8 +32,9 @@ ) # LOCAL -from vanilla_installer import config, main, theme -from vanilla_installer.log import logger +from vanilla_installer import config, i18n, main, theme + +logger = logging.getLogger(__name__) def run() -> None: @@ -48,7 +50,7 @@ def run() -> None: from vanilla_installer import fonts except: logger.exception( - "resource file for fonts isn't generated!\nrun `pyside6-rcc vanilla_installer/assets/fonts.qrc -o vanilla_installer/fonts.py` in the root directory of the project to generate them. you might need to source the venv.\nignore this if you are running on a compiled version." + "resource file for fonts isn't generated!\nrun `pyside6-rcc vanilla_installer/assets/fonts/fonts.qrc -o vanilla_installer/fonts.py` in the root directory of the project to generate them. you might need to source the venv.\nignore this if you are running on a compiled version." ) app = QApplication(sys.argv) @@ -218,6 +220,8 @@ def retranslateUi(self, MainWindow: QMainWindow) -> None: Args: MainWindow (QMainWindow): The main window. """ + # This is currently hardcoded as the actual i18n support isn't here, just the backend changes needed + i18n_strings = i18n.get_i18n_values("en_us") MainWindow.setWindowTitle( QCoreApplication.translate("MainWindow", "Vanilla Installer", None) ) @@ -225,32 +229,46 @@ def retranslateUi(self, MainWindow: QMainWindow) -> None: QCoreApplication.translate("MainWindow", "Fabulously Optimized", None) ) self.subtitle.setText( - QCoreApplication.translate("MainWindow", "Vanilla Installer", None) + QCoreApplication.translate( + "MainWindow", i18n_strings["vanilla_installer.gui.subtitle"], None + ) ) self.installButton.setText( - QCoreApplication.translate("MainWindow", "Install", None) + QCoreApplication.translate( + "MainWindow", i18n_strings["vanilla_installer.gui.install_button"], None + ) ) self.versionLabel.setText( - QCoreApplication.translate("MainWindow", "Minecraft version:", None) + QCoreApplication.translate( + "MainWindow", i18n_strings["vanilla_installer.gui.mc_version"], None + ) ) self.locationLabel.setText( - QCoreApplication.translate("MainWindow", "Location:", None) + QCoreApplication.translate( + "MainWindow", i18n_strings["vanilla_installer.gui.location"], None + ) ) self.infoButton.setText( QCoreApplication.translate("MainWindow", "GitHub", None) ) self.issuesButton.setText( - QCoreApplication.translate("MainWindow", "Report bugs", None) + QCoreApplication.translate( + "MainWindow", i18n_strings["vanilla_installer.gui.issues_button"], None + ) ) self.themeToggle.setText( - QCoreApplication.translate("MainWindow", "Toggle theme", None) + QCoreApplication.translate( + "MainWindow", i18n_strings["vanilla_installer.gui.theme_toggle"], None + ) ) self.versionHelpString = "Vanilla Installer allows easy installation of all supported versions of Fabulously Optimized. \nFor legacy versions, download the respective MultiMC version from CurseForge and unpack it manually." self.versionHelp.setToolTip( QCoreApplication.translate("MainWindow", self.versionHelpString, None) ) self.settingsButton.setText( - QCoreApplication.translate("MainWindow", "Settings", None) + QCoreApplication.translate( + "MainWindow", i18n_strings["vanilla_installer.gui.settings"], None + ) ) def reloadTheme(self) -> None: diff --git a/vanilla_installer/i18n.py b/vanilla_installer/i18n.py new file mode 100644 index 0000000..1998d3a --- /dev/null +++ b/vanilla_installer/i18n.py @@ -0,0 +1,29 @@ +"""Provides internationalization (i18n) services to the Vanilla Installer.""" +import json +import logging +from pathlib import Path + +logger = logging.getLogger(__name__) + +if Path("vanilla_installer").exists(): + # This is a development environment, being run from the root directory + lang_file_placeholder = "vanilla_installer/assets/lang/{}.json" +else: + lang_file_placeholder = "assets/lang/{}.json" + + +def get_i18n_values(language_code: str = "en_us") -> dict: + """Get the strings in the language requested. + + Args: + language (str, optional): The language code to get the strings for. Defaults to en_us, and falls back to en_us if the code given is invalid. + + Returns: + dict: The dictionary of strings for that language. + """ + lang_file = Path(lang_file_placeholder.format(language_code)).resolve() + if lang_file.exists() is False: + logger.warning("Non-existant i18n code passed, falling back to en_us.") + lang_file = Path(lang_file_placeholder.format("en_us")).resolve() + lang_json = json.load(open(lang_file)) + return lang_json diff --git a/vanilla_installer/log.py b/vanilla_installer/log.py index cfd1781..f574f4c 100644 --- a/vanilla_installer/log.py +++ b/vanilla_installer/log.py @@ -27,7 +27,7 @@ def flush(self): pass -logger = logging.getLogger() +logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) logfile_path = Path("./logs").resolve() / "vanilla_installer.log" if logfile_path.exists() is False: @@ -53,4 +53,4 @@ def flush(self): sys.stderr = LoggerWriter(logger.error) logging.info("Starting Vanilla Installer") -logger = logging.getLogger("Vanilla Installer") +logger = logging.getLogger(__name__) diff --git a/vanilla_installer/main.py b/vanilla_installer/main.py index 02d78af..3e2b2cc 100644 --- a/vanilla_installer/main.py +++ b/vanilla_installer/main.py @@ -8,6 +8,7 @@ import base64 import io import json +import logging import os import platform import subprocess @@ -21,9 +22,9 @@ import tomlkit as toml # Local -from vanilla_installer import __version__, config, log +from vanilla_installer import __version__, config -logger = log.logger +logger = logging.getLogger(__name__) FOLDER_LOC = "" diff --git a/vanilla_installer/theme.py b/vanilla_installer/theme.py index d5c5d88..9b6ede9 100644 --- a/vanilla_installer/theme.py +++ b/vanilla_installer/theme.py @@ -4,13 +4,15 @@ Theme & design of the PySide6 GUI. """ +import logging import pathlib from typing import Optional import darkdetect from vanilla_installer import config -from vanilla_installer.log import logger + +logger = logging.getLogger(__name__) FILE = str(pathlib.Path("data/theme.txt").resolve()) From d0f811a2bb9c75bbce8187e8ae7d81a7c7aef6c2 Mon Sep 17 00:00:00 2001 From: osfanbuff63 Date: Thu, 4 May 2023 09:03:31 -0400 Subject: [PATCH 3/7] downgrade detection done, beginning on the big scary warning --- poetry.lock | 10 ++--- vanilla_installer/main.py | 87 ++++++++++++++++++++++++++------------- 2 files changed, 64 insertions(+), 33 deletions(-) diff --git a/poetry.lock b/poetry.lock index d1fe8a1..ba8a222 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.4.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. [[package]] name = "anyio" @@ -368,14 +368,14 @@ files = [ [[package]] name = "imageio" -version = "2.28.1" +version = "2.28.0" description = "Library for reading and writing a wide range of image, video, scientific, and volumetric data formats." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "imageio-2.28.1-py3-none-any.whl", hash = "sha256:b9b456146aab459e648cde633b81bf487eb45248948f79c033e55af3bf1e6d70"}, - {file = "imageio-2.28.1.tar.gz", hash = "sha256:5db5087be5c814ecf7e2c7d30a1a15c97eca97d8c26f31ddc54d767d4a43bce8"}, + {file = "imageio-2.28.0-py3-none-any.whl", hash = "sha256:889d9eca66ac9f664d480b78447db1774e7f386bd3b0a06be7e32362d5390f4c"}, + {file = "imageio-2.28.0.tar.gz", hash = "sha256:467763bdb6e614d1ea8b4565e42c53fb2eb2fd4307a4601e97102a958c09812a"}, ] [package.dependencies] @@ -1063,7 +1063,7 @@ cffi = {version = ">=1.11", markers = "platform_python_implementation == \"PyPy\ cffi = ["cffi (>=1.11)"] [extras] -gui = ["pyside6", "darkdetect"] +gui = ["darkdetect", "pyside6"] [metadata] lock-version = "2.0" diff --git a/vanilla_installer/main.py b/vanilla_installer/main.py index 0a4f7d4..caac327 100644 --- a/vanilla_installer/main.py +++ b/vanilla_installer/main.py @@ -336,29 +336,32 @@ def create_profile(mc_dir: str, version_id: str) -> None: def log_installed_version( version: Union[str, int, float], install_dir: Union[str, bytes, os.PathLike] ) -> None: - """Log the version of Minecraft that FO has been installed for. Used to find out later + """Log the version of Minecraft that FO has been installed for. + This is used to find out later whether this is a downgrade. Args: version (Union[str, int, float]): The version to log. install_dir (Union[str, bytes, os.PathLike]): The directory that FO was installed to. """ - dir_path = Path(install_dir).resolve() / ".fabulously-optimized" + dir_path = Path(install_dir).resolve() / ".fovi" dir_path.mkdir(exist_ok=True) file_path = dir_path / "mc_version.txt" if file_path.exists() is False: file_path.touch() with file_path.open("w") as file: - file.write(str(version)) + file.write(version) -def read_versions() -> dict: +def read_versions(force_local: bool = False) -> dict: """Reads the versions.json file, either over the Internet, or locally. Returns: dict: The JSON file, formatted as a dictionary. """ + if force_local is True: + response = _get_versions_local() + return dict(response) SUPPORTED_FORMAT_VERSION = 2 - try: response = requests.get( "https://raw.githubusercontent.com/Fabulously-Optimized/vanilla-installer/main/vanilla_installer/assets/versions.json" @@ -368,42 +371,42 @@ def read_versions() -> dict: raise UnsupportedFormatVersion( f"Format version {format_version} is not supported by this version." ) - except requests.exceptions.RequestException or response.status_code != "200": - # This should never happen unless a) there's no internet connection, b) the file was deleted or is missing in a development case. - # In this case, fall back to a local file. - logger.warning("GitHub failed, falling back to local...") - try: - local_path = Path("vanilla_installer/assets").resolve() / "versions.json" - except: - local_path = Path("assets").resolve() / "versions.json" - response = json.loads(local_path.read_bytes()) - except UnsupportedFormatVersion: - logger.exception( - "Format version was not supported - using local file. Update Vanilla Installer to fix this." - ) - try: - local_path = Path("vanilla_installer/assets").resolve() / "versions.json" - except: - local_path = Path("assets").resolve() / "versions.json" - response = json.loads(local_path.read_bytes()) + except Exception as e: + if e is UnsupportedFormatVersion: + logger.exception( + "Format version was not supported - falling back to a local file. Update Vanilla Installer to fix this." + ) + else: + logger.warning("GitHub failed, falling back to local...") + response = _get_versions_local() return dict(response) +def _get_versions_local(): + try: + local_path = Path("vanilla_installer/assets").resolve() / "versions.json" + except: + local_path = Path("assets").resolve() / "versions.json" + return json.loads(local_path.read_bytes()) + + def get_pack_mc_versions() -> dict: """ Gets a list of all the versions FO currently supports. """ return_value = dict() + all_versions = dict() raw_dict = read_versions() for version in raw_dict["versions"]: raw_version = raw_dict["versions"][version] if raw_version["enabled"] is True or raw_version["enabled"] == "true": - return_value[version] = raw_version - for key in return_value.keys(): + all_versions[version] = raw_version + return_value = all_versions + for key in all_versions.keys(): try: - if key["packwiz"] != "": + if all_versions[key]["packwiz"] != "": pass - except KeyError: + except (KeyError, TypeError): return_value.pop(key) return return_value @@ -426,7 +429,9 @@ def convert_version(input_mcver: str) -> str: return return_value -def downgrade_check(version: Union[str, int, float]) -> bool: +def downgrade_check( + version: Union[str, int, float], install_dir: Union[str, bytes, os.PathLike] +) -> bool: """Checks whether the given version is a downgrade from the one currently installed. Args: @@ -436,6 +441,32 @@ def downgrade_check(version: Union[str, int, float]) -> bool: bool: Whether this is a downgrade. """ version_dict = read_versions() + installed_version_file = Path(install_dir).resolve() / ".fovi" / "mc_version.txt" + try: + with installed_version_file.open("r") as file: + current_version_file = file.read() + except FileNotFoundError: + logger.exception("No version file found. Assuming this is not a downgrade") + downgrade = False + try: + current_version = float(version_dict[current_version_file]) + if float(version) < current_version: + downgrade = True + else: + downgrade = False + except KeyError: + logger.exception("Invalid or unknown version installed, making extra checks.") + install_dir_path = Path(install_dir).resolve() + install_dir_path.mods = install_dir_path / "mods" + install_dir_path.config = install_dir_path / "config" + install_dir_path.saves = install_dir_path / "saves" + if install_dir_path.mods.exists() is False and install_dir_path.config.exists() is False and install_dir_path.saves.exists() is False: + logger.info("No mods, config, or saves directory found, this cannot be a downgrade.") + downgrade = False + elif not any(install_dir_path.mods.iterdir()) and not any(install_dir_path.config.iterdir()) and not any(install_dir_path.saves.iterdir()): + logger.info("Mods, config, and saves directories were empty, this cannot be a downgrade.") + downgrade = False + return downgrade def run( From b5728a32f0d390992d6fb43d010b80e97362f4d7 Mon Sep 17 00:00:00 2001 From: osfanbuff63 Date: Thu, 4 May 2023 09:04:31 -0400 Subject: [PATCH 4/7] ...take 2 on that commit --- .gitignore | 3 + vanilla_installer/assets/lang/en_us.json | 7 +- vanilla_installer/gui.py | 107 ++++++++++++++++++++++- vanilla_installer/log.py | 12 ++- vanilla_installer/main.py | 62 ++++++++----- 5 files changed, 161 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index 7a549dc..b23ad58 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,9 @@ *.jar data/ temp/ +config/ +data/ +resourcepacks/ # tests/ %USERPROFILE% logs/ diff --git a/vanilla_installer/assets/lang/en_us.json b/vanilla_installer/assets/lang/en_us.json index 420c467..e11ece2 100644 --- a/vanilla_installer/assets/lang/en_us.json +++ b/vanilla_installer/assets/lang/en_us.json @@ -5,5 +5,10 @@ "vanilla_installer.gui.location": "Location:", "vanilla_installer.gui.issues_button": "Report bugs", "vanilla_installer.gui.theme_toggle": "Toggle theme", - "vanilla_installer.gui.settings": "Settings" + "vanilla_installer.gui.settings": "Settings", + "vanilla_installer.gui.downgrade": "Downgrade Warning", + "vanilla_installer.gui.downgrade.text": "You are attempting to downgrade the Minecraft version. This is NOT SUPPORTED by Mojang or Fabulously Optimized and it may cause world corruption or crashes. \nIf you want to do this safely, you should backup mods, config and saves folders to a different location and delete them from your .minecraft folder.", + "vanilla_installer.gui.downgrade.install_checkbox": "I agree that downgrades are unsupported by Mojang and Fabulously Optimized, but I want to do this anyway.", + "vanilla_installer.gui.warnings.open_folder": "Open .minecraft", + "vanilla_installer.gui.warnings.install_anyway": "Install anyway" } \ No newline at end of file diff --git a/vanilla_installer/gui.py b/vanilla_installer/gui.py index 1f36175..1b1c488 100644 --- a/vanilla_installer/gui.py +++ b/vanilla_installer/gui.py @@ -5,7 +5,6 @@ """ # IMPORTS -import logging import pathlib import platform import sys @@ -26,9 +25,11 @@ QGraphicsColorizeEffect, QLabel, QMainWindow, + QMessageBox, QPushButton, QTextEdit, QWidget, + QAbstractButton, ) # LOCAL @@ -68,12 +69,14 @@ def run() -> None: def setFont(opendyslexic: bool): global global_font if opendyslexic: + logger.debug("Set font to OpenDyslexic") global_font = "OpenDyslexic" else: # For some reason the Inter font on Linux is called `Inter` and on Windows it's called `Inter Regular` # And thus, this is a janky solution # I'm not sure what it's called on MacOS so hopefully it's the same as linux cause i can't test it # Either way it would be a better idea to move to a font that doesn't have this issue + logger.debug("Set font to Inter") inter_name = "Inter" if platform.system() == "Windows": inter_name = "Inter Regular" @@ -419,6 +422,18 @@ def startInstall(self) -> None: ) version = self.versionSelector.itemText(self.versionSelector.currentIndex()) location = self.selectedLocation.toPlainText() + if main.downgrade_check(version, location) is True: + logger.warning("Downgrade detected, opening downgrade warning.") + continue_on_downgrade = False + response = DowngradeWarning(self).exec() + if response == DowngradeWarning.cancelButton: + pass + if continue_on_downgrade is False: + return + else: + logger.warning( + "User chose to continue on a version downgrade, anything past this is UNSUPPORTED." + ) self.installing = True if version.startswith("1.16"): java_ver = 8 @@ -441,9 +456,6 @@ def startInstall(self) -> None: class SettingsDialog(QDialog): """ The settings dialog. - - Args: - QDialog (QDialog): The dialog. """ parentWindow: Ui_MainWindow @@ -540,6 +552,93 @@ def changeFont(self, state) -> None: self.parentWindow.reloadTheme() +class DowngradeWarning(QMessageBox): + parentWindow: Ui_MainWindow + + def __init__(self, parent) -> None: + self.parentWindow = parent + super().__init__(self.parentWindow.centralwidget) + self.setupUi() + + def setupUi(self) -> None: + """Setup the UI for the downgrade warning.""" + if not self.objectName(): + self.setObjectName("Warning") + self.setIcon(QMessageBox.Icon.Warning) + self.openFolderButton = self.addButton( + "Open .minecraft", + QMessageBox.ButtonRole.ActionRole, + ) + self.installAnywayButton = self.addButton( + "Install anyway", + QMessageBox.ButtonRole.ActionRole, + ) + self.installAnywayButton.setDisabled(True) + self.cancelButton = self.addButton(QMessageBox.Cancel) + self.installCheckbox = QCheckBox() + self.setCheckBox(self.installCheckbox) + self.setDefaultButton(QMessageBox.Cancel) + self.retranslateUi(self) + self.reloadTheme() + + def retranslateUi(self, Warning) -> None: + """ + Retranslate UI for the set dialog. + + Args: + Warning: The dialog. + """ + i18n_strings = i18n.get_i18n_values("en_us") + Warning.setWindowTitle( + QCoreApplication.translate( + "Warning", i18n_strings["vanilla_installer.gui.downgrade"], None + ) + ) + self.openFolderButton.setText( + QCoreApplication.translate( + "Warning", + i18n_strings["vanilla_installer.gui.warnings.open_folder"], + None, + ) + ) + self.installAnywayButton.setText( + QCoreApplication.translate( + "Warning", + i18n_strings["vanilla_installer.gui.warnings.install_anyway"], + None, + ) + ) + self.installCheckbox.setText( + QCoreApplication.translate( + "Warning", + i18n_strings["vanilla_installer.gui.downgrade.install_checkbox"], + None, + ) + ) + + def reloadTheme(self) -> None: + """ + Reload the theme. + """ + loaded_theme = theme.load() + self.setStyleSheet( + f'[objectName^="Warning"] {{ background-color: {loaded_theme.get("base")}}}' + ) + self.openFolderButton.setStyleSheet( + f'QPushButton {{ border: none; background-color: { loaded_theme.get("button") } ; color: {loaded_theme.get("text")}; padding: 8px; border-radius: 5px; font-family: "{global_font}"}}' + f'QPushButton:hover {{ background-color: { loaded_theme.get("buttonhovered") }}}' + f'QPushButton:hover {{ background-color: { loaded_theme.get("buttonpressed") }}}' + ) + self.installAnywayButton.setStyleSheet( + f'QPushButton {{ border: none; background-color: { loaded_theme.get("button") } ; color: {loaded_theme.get("text")}; padding: 8px; border-radius: 5px; font-family: "{global_font}"}}' + f'QPushButton:hover {{ background-color: { loaded_theme.get("buttonhovered") }}}' + f'QPushButton:hover {{ background-color: { loaded_theme.get("buttonpressed") }}}' + ) + self.installCheckbox.setStyleSheet( + f'color: {loaded_theme.get("label")}; font-family: "{global_font}"' + ) + + class Worker(QRunnable): def __init__(self, fn) -> None: super(Worker, self).__init__() diff --git a/vanilla_installer/log.py b/vanilla_installer/log.py index 8970749..12143fe 100644 --- a/vanilla_installer/log.py +++ b/vanilla_installer/log.py @@ -27,8 +27,12 @@ def flush(self): pass -def setup_logging() -> logging.Logger: - logger = logging.getLogger(__name__) +logger = logging.getLogger(__name__) +try: + if log_setup != bool: + pass +except: + log_setup = False logger.setLevel(logging.DEBUG) logfile_path = Path("./logs").resolve() / "vanilla_installer.log" if logfile_path.exists() is False: @@ -52,4 +56,8 @@ def setup_logging() -> logging.Logger: # To access the original stdout/stderr, use sys.__stdout__/sys.__stderr__ sys.stdout = LoggerWriter(logger.info) sys.stderr = LoggerWriter(logger.error) + log_setup = True + + +def setup_logging() -> logging.Logger: return logger diff --git a/vanilla_installer/main.py b/vanilla_installer/main.py index caac327..a5af1c3 100644 --- a/vanilla_installer/main.py +++ b/vanilla_installer/main.py @@ -25,7 +25,7 @@ from vanilla_installer import __version__, config, log logger = log.setup_logging() -logger.info("Starting Vanilla Installer") + FOLDER_LOC = "" @@ -55,7 +55,6 @@ def get_dir() -> str: Returns: str: Path """ - path = config.read() return path["config"]["path"] @@ -276,10 +275,10 @@ def install_pack( java_ver (float): The Java version to use. Defaults to 17.3 """ logger.debug("Installing the pack now.") - os.chdir(mc_dir) - os.makedirs(f"{get_dir()}/", exist_ok=True) pack_toml = convert_version(mc_version) try: + os.chdir(mc_dir) + os.makedirs(f"{get_dir()}/", exist_ok=True) command( f"{get_java(java_ver)} -jar {packwiz_installer_bootstrap} {pack_toml} --timeout 0" ) @@ -422,7 +421,7 @@ def convert_version(input_mcver: str) -> str: str: The converted version as a URL. """ versions = get_pack_mc_versions() - return_value = versions.get(input_mcver) + return_value = versions[input_mcver]["packwiz"] if return_value is None: raise TypeError("Invalid or unsupported Minecraft version.") else: @@ -440,6 +439,7 @@ def downgrade_check( Returns: bool: Whether this is a downgrade. """ + downgrade = True version_dict = read_versions() installed_version_file = Path(install_dir).resolve() / ".fovi" / "mc_version.txt" try: @@ -448,24 +448,39 @@ def downgrade_check( except FileNotFoundError: logger.exception("No version file found. Assuming this is not a downgrade") downgrade = False - try: - current_version = float(version_dict[current_version_file]) - if float(version) < current_version: - downgrade = True - else: - downgrade = False - except KeyError: - logger.exception("Invalid or unknown version installed, making extra checks.") - install_dir_path = Path(install_dir).resolve() - install_dir_path.mods = install_dir_path / "mods" - install_dir_path.config = install_dir_path / "config" - install_dir_path.saves = install_dir_path / "saves" - if install_dir_path.mods.exists() is False and install_dir_path.config.exists() is False and install_dir_path.saves.exists() is False: - logger.info("No mods, config, or saves directory found, this cannot be a downgrade.") - downgrade = False - elif not any(install_dir_path.mods.iterdir()) and not any(install_dir_path.config.iterdir()) and not any(install_dir_path.saves.iterdir()): - logger.info("Mods, config, and saves directories were empty, this cannot be a downgrade.") - downgrade = False + if downgrade is not False: + try: + current_version = float(version_dict[current_version_file]) + if float(version) < current_version: + downgrade = True + else: + downgrade = False + except KeyError: + logger.exception( + "Invalid or unknown version installed, making extra checks." + ) + install_dir_path = Path(install_dir).resolve() + install_dir_path_mods = install_dir_path / "mods" + install_dir_path_config = install_dir_path / "config" + install_dir_path_saves = install_dir_path / "saves" + if ( + install_dir_path_mods.exists() is False + and install_dir_path_config.exists() is False + and install_dir_path_saves.exists() is False + ): + logger.info( + "No mods, config, or saves directory found, this cannot be a downgrade." + ) + downgrade = False + elif ( + not any(install_dir_path_mods.iterdir()) + and not any(install_dir_path_config.iterdir()) + and not any(install_dir_path_saves.iterdir()) + ): + logger.info( + "Mods, config, and saves directories were empty, this cannot be a downgrade." + ) + downgrade = False return downgrade @@ -522,3 +537,4 @@ def run( create_profile(mc_dir, fabric_version) text_update("Complete!", widget, "info", interface) logger.info("Success!") + log_installed_version(version, mc_dir) From c9593a353ef85247b27bb6abd7fd1848f1482426 Mon Sep 17 00:00:00 2001 From: osfanbuff63 Date: Thu, 4 May 2023 09:07:03 -0400 Subject: [PATCH 5/7] does this fix flake8 --- vanilla_installer/log.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/vanilla_installer/log.py b/vanilla_installer/log.py index 12143fe..d002d2a 100644 --- a/vanilla_installer/log.py +++ b/vanilla_installer/log.py @@ -29,9 +29,21 @@ def flush(self): logger = logging.getLogger(__name__) try: - if log_setup != bool: - pass -except: + if log_setup is not True: + log_setup = False + logger.setLevel(logging.DEBUG) + logfile_path = Path("./logs").resolve() / "vanilla_installer.log" + if logfile_path.exists() is False: + Path("./logs").resolve().mkdir(exist_ok=True) + with logfile_path as file: + open(file, "x", encoding="utf-8").write("") + handler = logging.handlers.RotatingFileHandler( + filename=logfile_path, + encoding="utf-8", + maxBytes=32 * 1024 * 1024, # 32 MiB + backupCount=5, # Rotate through 5 files + ) +except UnboundLocalError: log_setup = False logger.setLevel(logging.DEBUG) logfile_path = Path("./logs").resolve() / "vanilla_installer.log" From 5d795eaa6027d8c507c391707bb13a60d3c11664 Mon Sep 17 00:00:00 2001 From: osfanbuff63 Date: Thu, 4 May 2023 09:10:09 -0400 Subject: [PATCH 6/7] ignore that error as it's handled --- vanilla_installer/log.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vanilla_installer/log.py b/vanilla_installer/log.py index d002d2a..2789ec5 100644 --- a/vanilla_installer/log.py +++ b/vanilla_installer/log.py @@ -29,7 +29,7 @@ def flush(self): logger = logging.getLogger(__name__) try: - if log_setup is not True: + if log_setup is not True: # noqa: F821 log_setup = False logger.setLevel(logging.DEBUG) logfile_path = Path("./logs").resolve() / "vanilla_installer.log" From c76ec3b84363774678a1b96a491581cf9be6e24c Mon Sep 17 00:00:00 2001 From: osfanbuff63 Date: Thu, 4 May 2023 09:15:57 -0400 Subject: [PATCH 7/7] ... --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index ba8a222..84ef816 100644 --- a/poetry.lock +++ b/poetry.lock @@ -368,14 +368,14 @@ files = [ [[package]] name = "imageio" -version = "2.28.0" +version = "2.28.1" description = "Library for reading and writing a wide range of image, video, scientific, and volumetric data formats." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "imageio-2.28.0-py3-none-any.whl", hash = "sha256:889d9eca66ac9f664d480b78447db1774e7f386bd3b0a06be7e32362d5390f4c"}, - {file = "imageio-2.28.0.tar.gz", hash = "sha256:467763bdb6e614d1ea8b4565e42c53fb2eb2fd4307a4601e97102a958c09812a"}, + {file = "imageio-2.28.1-py3-none-any.whl", hash = "sha256:b9b456146aab459e648cde633b81bf487eb45248948f79c033e55af3bf1e6d70"}, + {file = "imageio-2.28.1.tar.gz", hash = "sha256:5db5087be5c814ecf7e2c7d30a1a15c97eca97d8c26f31ddc54d767d4a43bce8"}, ] [package.dependencies]