From b720041e8bce7cc487b956abc3a1fe19e600db01 Mon Sep 17 00:00:00 2001 From: Tygo Everts Date: Mon, 20 Nov 2023 22:07:18 +0100 Subject: [PATCH 1/9] Drastically increase efficiency parsing java maven --- src/common/__init__.py | 0 src/common/maven_coords.py | 65 ++++++++++++++++++++++++++++++++++++++ src/install/_types.py | 4 +-- src/install/modloaders.py | 45 ++++---------------------- 4 files changed, 74 insertions(+), 40 deletions(-) create mode 100644 src/common/__init__.py create mode 100644 src/common/maven_coords.py diff --git a/src/common/__init__.py b/src/common/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/common/maven_coords.py b/src/common/maven_coords.py new file mode 100644 index 0000000..7dcff5b --- /dev/null +++ b/src/common/maven_coords.py @@ -0,0 +1,65 @@ +from os import path + + +def maven_parse(arg: str) -> tuple[str, str]: + """ + Parse java maven coords to a folder and a file. + + Example: + ```txt + de.oceanlabs.mcp:mcp_config:1.20.1-20230612.114412@zip + - folder: de/oceanlabs/mcp/mcp_config/1.20.1-20230612.114412/ + - file: mcp_config-1.20.1-20230612.114412.zip + ``` + maven_""" + + # Split the file extension + if '@' in arg: + arg, ext = arg.split('@', 1) + else: + ext = 'jar' + + # Until the third colon, replace + # ':' with path.sep. Until the + # first, also replace '.' with it + colons = 0 + folder = '' + for char in arg: + if colons == 3: + folder += path.sep + break + if char == ':': + colons += 1 + char = path.sep + elif char == '.' and colons == 0: + char = path.sep + folder += char + + # Select everything from the first + # colon and replace ':' with '-' + file = '' + for char in arg[arg.find(':')+1:]: + if char == ':': + char = '-' + file += char + + # Add the file extension + file += '.' + ext + + return folder, file + + +def maven_to_file(*paths: str) -> str: + """ + Create a file path from a maven coord. + The last argument should be `arg` + """ + return path.join(*paths[:-1], *maven_parse(paths[-1])) + + +def maven_to_url(base: str, arg: str) -> str: + """Create a url from a maven coord""" + if not base[-1] == '/': + base += '/' + + return ''.join((base, *maven_parse(arg))) diff --git a/src/install/_types.py b/src/install/_types.py index dc42d10..155883f 100644 --- a/src/install/_types.py +++ b/src/install/_types.py @@ -19,11 +19,11 @@ Generic, NotRequired, Optional ) -# --- install/filesize.py --- # +# --- filesize.py --- # SizeSystem = list[tuple[int, str | tuple[str, str]]] -# --- install --- # +# --- common --- # Client = Literal['client'] Server = Literal['server'] Side = Literal['client', 'server'] diff --git a/src/install/modloaders.py b/src/install/modloaders.py index d0e584b..4522d4f 100644 --- a/src/install/modloaders.py +++ b/src/install/modloaders.py @@ -27,6 +27,8 @@ from .urls import forge as forge_urls, fabric as fabric_urls from .loadingbar import loadingbar +from ..common.maven_coords import maven_to_file + from ._types import ( Client, Server, Side, Modloader, MinecraftJson, VersionJson, @@ -169,54 +171,21 @@ def replace_arg_vars(self, arg: str, data: dict[str, str]) -> str: # in the arg string with **data arg = arg.format(**data) - # Extract when paths ends with '.lzma' - if path.normpath(arg).endswith('.lzma'): + # Extract when a path ends with '.lzma' + if arg.endswith('.lzma'): with ZipFile(self.installer, 'r') as archive: archive.extract(arg[1:], self.temp_dir) return path.join(self.temp_dir, path.normpath(arg[1:])) - # Return arg if it isn't "[something]" + # Return arg when it isn't "[something]" if arg[0] != '[' and arg[-1] != ']': return arg # Remove the brackets - arg = arg.replace('[', '').replace(']', '') - - # Split the file extension - if '@' in arg: - arg, file_extension = arg.split('@', 1) - else: - file_extension = 'jar' - - # Create the file and folder path - folder = ( - # Until the first colon, replace - # ':' and '.' with path.sep - arg[:arg.find(':')] - .replace(':', '.') - .replace('.', path.sep) + - - # Then, do the same - # until the third colon - (arg[arg.find(':'):] - if arg.count(':') != 3 - else arg[arg.find(':'): - arg.rfind(':')] - ).replace(':', path.sep) - ) - - file = ( - # Select everything from - # the first colon and - # replace ':' with '-' - arg[arg.find(':')+1:] - .replace(':', '-') + - - # Add the file extension - '.' + file_extension) + arg = arg[1:-1] # Return the full path - return path.join(self.launcher_dir, 'libraries', folder, file) + return maven_to_file(self.launcher_dir, 'libraries', arg) def download_jar_files(self) -> None: """Download the jar files""" From 484152ea847383d929c7f84fe9b8020023a23dc2 Mon Sep 17 00:00:00 2001 From: Tygo Everts Date: Mon, 20 Nov 2023 22:08:15 +0100 Subject: [PATCH 2/9] Added copyright notice in maven_coords.py --- src/common/maven_coords.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/common/maven_coords.py b/src/common/maven_coords.py index 7dcff5b..26bf848 100644 --- a/src/common/maven_coords.py +++ b/src/common/maven_coords.py @@ -1,3 +1,19 @@ +# MCM-Manager: Minecraft Modpack Manager +# Copyright (C) 2023 Tygo Everts +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + from os import path From 0638ab79ac546d4b678a0b316f43c28f2bf7072a Mon Sep 17 00:00:00 2001 From: Tygo Everts Date: Tue, 21 Nov 2023 11:24:07 +0100 Subject: [PATCH 3/9] Changed maven_coords to consist of a class --- src/common/maven_coords.py | 107 +++++++++++++++++++------------------ src/install/modloaders.py | 4 +- 2 files changed, 58 insertions(+), 53 deletions(-) diff --git a/src/common/maven_coords.py b/src/common/maven_coords.py index 26bf848..658cda5 100644 --- a/src/common/maven_coords.py +++ b/src/common/maven_coords.py @@ -17,65 +17,70 @@ from os import path -def maven_parse(arg: str) -> tuple[str, str]: - """ - Parse java maven coords to a folder and a file. +class maven_parse: + def __init__(self, arg: str) -> None: + """ + Parse java maven coords to a folder and a file. - Example: - ```txt - de.oceanlabs.mcp:mcp_config:1.20.1-20230612.114412@zip - - folder: de/oceanlabs/mcp/mcp_config/1.20.1-20230612.114412/ - - file: mcp_config-1.20.1-20230612.114412.zip - ``` - maven_""" + Example: + ```txt + de.oceanlabs.mcp:mcp_config:1.20.1-20230612.114412@zip + - folder: de/oceanlabs/mcp/mcp_config/1.20.1-20230612.114412/ + - file: mcp_config-1.20.1-20230612.114412.zip + ``` - # Split the file extension - if '@' in arg: - arg, ext = arg.split('@', 1) - else: - ext = 'jar' + You can get a file path using `.maven_to_file()` + or an url using `.maven_to_url` + """ - # Until the third colon, replace - # ':' with path.sep. Until the - # first, also replace '.' with it - colons = 0 - folder = '' - for char in arg: - if colons == 3: - folder += path.sep - break - if char == ':': - colons += 1 - char = path.sep - elif char == '.' and colons == 0: - char = path.sep - folder += char + self.parsed = self._parse(arg) - # Select everything from the first - # colon and replace ':' with '-' - file = '' - for char in arg[arg.find(':')+1:]: - if char == ':': - char = '-' - file += char + def _parse(self, arg: str) -> tuple[str, str]: + # Split the file extension + if '@' in arg: + arg, ext = arg.split('@', 1) + else: + ext = 'jar' - # Add the file extension - file += '.' + ext + # Until the third colon, replace + # ':' with path.sep. Until the + # first, also replace '.' with it + colons = 0 + folder = '' + for char in arg: + if colons == 3: + folder += path.sep + break + if char == ':': + colons += 1 + char = path.sep + elif char == '.' and colons == 0: + char = path.sep + folder += char - return folder, file + # Select everything from the first + # colon and replace ':' with '-' + file = '' + for char in arg[arg.find(':')+1:]: + if char == ':': + char = '-' + file += char + # Add the file extension + file += '.' + ext -def maven_to_file(*paths: str) -> str: - """ - Create a file path from a maven coord. - The last argument should be `arg` - """ - return path.join(*paths[:-1], *maven_parse(paths[-1])) + return folder, file + def to_file(self, *paths: str) -> str: + """ + Create a file path from the maven coord. This calls + a `path.join()` with all paths plus `self.parsed` + """ + return path.join(*paths, *self.parsed) -def maven_to_url(base: str, arg: str) -> str: - """Create a url from a maven coord""" - if not base[-1] == '/': - base += '/' + def to_url(self, base: str) -> str: + """Create a url from the maven coord""" + if not base[-1] == '/': + base += '/' - return ''.join((base, *maven_parse(arg))) + return ''.join((base, *self.parsed)) diff --git a/src/install/modloaders.py b/src/install/modloaders.py index 4522d4f..e081e31 100644 --- a/src/install/modloaders.py +++ b/src/install/modloaders.py @@ -27,7 +27,7 @@ from .urls import forge as forge_urls, fabric as fabric_urls from .loadingbar import loadingbar -from ..common.maven_coords import maven_to_file +from ..common.maven_coords import maven_parse from ._types import ( Client, Server, Side, Modloader, @@ -185,7 +185,7 @@ def replace_arg_vars(self, arg: str, data: dict[str, str]) -> str: arg = arg[1:-1] # Return the full path - return maven_to_file(self.launcher_dir, 'libraries', arg) + return maven_parse(arg).to_file(self.launcher_dir, 'libraries') def download_jar_files(self) -> None: """Download the jar files""" From 4d6b146d8215700c24454bb22558942d580e1e8c Mon Sep 17 00:00:00 2001 From: Tygo Everts Date: Tue, 21 Nov 2023 11:24:22 +0100 Subject: [PATCH 4/9] Added a debug configuration --- .vscode/launch.json | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..a4bb107 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,20 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Install", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal", + "justMyCode": true, + "args": [ + "install", + "-y" + ] + } + ] +} \ No newline at end of file From d33d7c613a7b68b3258bf28ae9fbd14d855e9cd7 Mon Sep 17 00:00:00 2001 From: Tygo Everts Date: Tue, 21 Nov 2023 15:20:44 +0100 Subject: [PATCH 5/9] Fixed case where folder doesn't have a trailing / --- src/common/maven_coords.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/common/maven_coords.py b/src/common/maven_coords.py index 658cda5..1a73508 100644 --- a/src/common/maven_coords.py +++ b/src/common/maven_coords.py @@ -49,7 +49,6 @@ def _parse(self, arg: str) -> tuple[str, str]: folder = '' for char in arg: if colons == 3: - folder += path.sep break if char == ':': colons += 1 @@ -58,6 +57,9 @@ def _parse(self, arg: str) -> tuple[str, str]: char = path.sep folder += char + if not folder[-1] == '/': + folder += '/' + # Select everything from the first # colon and replace ':' with '-' file = '' From afbbe6bfb6e2b8a16f1df86031cb839d0c0a4d00 Mon Sep 17 00:00:00 2001 From: Tygo Everts Date: Tue, 21 Nov 2023 15:24:07 +0100 Subject: [PATCH 6/9] Add more detailed description to maven coords --- src/common/maven_coords.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/common/maven_coords.py b/src/common/maven_coords.py index 1a73508..f2374b9 100644 --- a/src/common/maven_coords.py +++ b/src/common/maven_coords.py @@ -30,7 +30,10 @@ def __init__(self, arg: str) -> None: ``` You can get a file path using `.maven_to_file()` - or an url using `.maven_to_url` + or an url using `.maven_to_url`. + + To directly access the parsed result, + use the variable `.parsed` """ self.parsed = self._parse(arg) From b14b6d886544d6798a03867bd77fb86dc0ad974e Mon Sep 17 00:00:00 2001 From: Tygo Everts Date: Tue, 21 Nov 2023 18:56:48 +0100 Subject: [PATCH 7/9] Improved tests structure --- tests/__init__.py | 50 -------------------------- tests/assets/launcher_profiles.json | 17 +++++++++ tests/common/__init__.py | 0 tests/common/test_maven_coords.py | 55 +++++++++++++++++++++++++++++ tests/config.py | 27 ++++++++++++++ tests/globalfuncs.py | 32 +++++++++++++++++ tests/install/setup.py | 44 +++++++++++++++++++++++ tests/install/test_loadingbar.py | 2 +- tests/install/test_media.py | 52 +++++++++++++++------------ tests/install/test_modloaders.py | 27 +++++++------- tests/install/test_urls.py | 16 +++++---- tests/vars.py | 47 ------------------------ 12 files changed, 231 insertions(+), 138 deletions(-) create mode 100644 tests/assets/launcher_profiles.json create mode 100644 tests/common/__init__.py create mode 100644 tests/common/test_maven_coords.py create mode 100644 tests/config.py create mode 100644 tests/globalfuncs.py create mode 100644 tests/install/setup.py delete mode 100644 tests/vars.py diff --git a/tests/__init__.py b/tests/__init__.py index 6080c6b..e69de29 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,50 +0,0 @@ -# MCM-Manager: Minecraft Modpack Manager -# Copyright (C) 2023 Tygo Everts -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -from os import path, mkdir -from json import dump -from .vars import install_dir, launcher_dir - -# Create the install dir -if not path.isdir(install_dir): - mkdir(install_dir) - -# Create the launcher dir and example-manifest.json -if not path.isdir(launcher_dir): - mkdir(launcher_dir) - -launcher_profiles = { - "profiles": {}, - "settings": { - "crashAssistance": True, - "enableAdvanced": False, - "enableAnalytics": True, - "enableHistorical": False, - "enableReleases": True, - "enableSnapshots": False, - "keepLauncherOpen": False, - "profileSorting": "ByLastPlayed", - "showGameLog": False, - "showMenu": False, - "soundOn": False - }, - "version": 3 -} - -with open(path.join(launcher_dir, 'launcher_profiles.json'), 'w') as fp: - dump(launcher_profiles, fp, indent=4) - -del path, mkdir, dump, install_dir, launcher_dir, launcher_profiles, fp diff --git a/tests/assets/launcher_profiles.json b/tests/assets/launcher_profiles.json new file mode 100644 index 0000000..be99c01 --- /dev/null +++ b/tests/assets/launcher_profiles.json @@ -0,0 +1,17 @@ +{ + "profiles": {}, + "settings": { + "crashAssistance": true, + "enableAdvanced": false, + "enableAnalytics": true, + "enableHistorical": false, + "enableReleases": true, + "enableSnapshots": false, + "keepLauncherOpen": false, + "profileSorting": "ByLastPlayed", + "showGameLog": false, + "showMenu": false, + "soundOn": false + }, + "version": 3 +} \ No newline at end of file diff --git a/tests/common/__init__.py b/tests/common/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/common/test_maven_coords.py b/tests/common/test_maven_coords.py new file mode 100644 index 0000000..6e806a8 --- /dev/null +++ b/tests/common/test_maven_coords.py @@ -0,0 +1,55 @@ +import unittest + +from src.common.maven_coords import maven_parse + + +class Common(unittest.TestCase): + def test_maven_coords(self): + cases: list[tuple[str, tuple[str, str], str, str]] = [ + ( # With three parts + 'net.fabricmc:fabric-loader:0.14.22', ( + 'net/fabricmc/fabric-loader/0.14.22/', + 'fabric-loader-0.14.22.jar' + ), + 'libraries/net/fabricmc/fabric-loader/0.14.22/' + 'fabric-loader-0.14.22.jar', + 'https://example.com/net/fabricmc/fabric-loader' + '/0.14.22/fabric-loader-0.14.22.jar' + ), + ( # With four parts + 'net.minecraft:client:1.20.1-20230612.114412:slim', ( + 'net/minecraft/client/1.20.1-20230612.114412/', + 'client-1.20.1-20230612.114412-slim.jar' + ), + 'libraries/net/minecraft/client/1.20.1-20230612.114412/' + 'client-1.20.1-20230612.114412-slim.jar', + 'https://example.com/net/minecraft/client/' + '1.20.1-20230612.114412/client-1.20.1-20230612.114412-slim.jar' + ), + ( # With three parts and a file extension + 'de.oceanlabs.mcp:mcp_config:1.20.1-20230612.114412@zip', ( + 'de/oceanlabs/mcp/mcp_config/1.20.1-20230612.114412/', + 'mcp_config-1.20.1-20230612.114412.zip' + ), + 'libraries/de/oceanlabs/mcp/mcp_config/1.20.1-20230612.114412/' + 'mcp_config-1.20.1-20230612.114412.zip', + 'https://example.com/de/oceanlabs/mcp/mcp_config/' + '1.20.1-20230612.114412/mcp_config-1.20.1-20230612.114412.zip' + ), + ( # With four parts and a file extension + 'de.oceanlabs.mcp:mcp_config:1.20.1-20230612.114412:mappings@txt', ( + 'de/oceanlabs/mcp/mcp_config/1.20.1-20230612.114412/', + 'mcp_config-1.20.1-20230612.114412-mappings.txt' + ), + 'libraries/de/oceanlabs/mcp/mcp_config/1.20.1-20230612.114412/' + 'mcp_config-1.20.1-20230612.114412-mappings.txt', + 'https://example.com/de/oceanlabs/mcp/mcp_config/' + '1.20.1-20230612.114412/mcp_config-1.20.1-20230612.114412-mappings.txt' + ) + ] + + for i in cases: + maven = maven_parse(i[0]) + self.assertEqual(maven.parsed, i[1]) + self.assertEqual(maven.to_file('libraries'), i[2]) + self.assertEqual(maven.to_url('https://example.com'), i[3]) diff --git a/tests/config.py b/tests/config.py new file mode 100644 index 0000000..b415905 --- /dev/null +++ b/tests/config.py @@ -0,0 +1,27 @@ +# MCM-Manager: Minecraft Modpack Manager +# Copyright (C) 2023 Tygo Everts +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from os import path + +CURDIR = path.dirname(path.realpath(__file__)) + +TMPDIR = path.join(CURDIR, 'temp') +LAUNDIR = path.join(TMPDIR, '.minecraft') +INSTDIR = path.join(TMPDIR, 'gamedir') + +ASSETDIR = path.join(CURDIR, 'assets') +MANIFEST = path.join(ASSETDIR, 'manifest.json') +LAUNPROF = path.join(ASSETDIR, 'launcher_profiles.json') diff --git a/tests/globalfuncs.py b/tests/globalfuncs.py new file mode 100644 index 0000000..f944e25 --- /dev/null +++ b/tests/globalfuncs.py @@ -0,0 +1,32 @@ +from contextlib import redirect_stdout +from typing import Any, Callable +from os import path, remove, walk +from shutil import rmtree + +from .config import TMPDIR + + +def empty_dir(directory: str): + "Empty a directory" + for root, dirs, files in walk(directory): + for f in files: + remove(path.join(root, f)) + for d in dirs: + rmtree(path.join(root, d)) + + +def quiet(func: Callable[..., Any]) -> Callable[..., Any]: + "A simple decorator function that supresses stdout" + def wrapper(*args: Any, **kwargs: Any): + with redirect_stdout(None): + result = func(*args, **kwargs) + return result + return wrapper + + +def cleanup(func: Callable[..., Any]) -> Callable[..., Any]: + "A function that removes the temp directory after completion" + def wrapper(*args: Any, **kwargs: Any): + func(*args, **kwargs) + empty_dir(TMPDIR) + return wrapper diff --git a/tests/install/setup.py b/tests/install/setup.py new file mode 100644 index 0000000..ca4de34 --- /dev/null +++ b/tests/install/setup.py @@ -0,0 +1,44 @@ +# MCM-Manager: Minecraft Modpack Manager +# Copyright (C) 2023 Tygo Everts +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from os import mkdir, path +from shutil import copy +from ..config import INSTDIR, LAUNDIR, LAUNPROF, TMPDIR + + +def maketemp(): + """Make a temp directory""" + + if not path.isdir(TMPDIR): + mkdir(TMPDIR) + + +def setup_dirs() -> None: + """Setup necesarry directories""" + + # Make a temp directory + maketemp() + + # Create the install dir + if not path.isdir(INSTDIR): + mkdir(INSTDIR) + + # Create the launcher dir and example-manifest.json + if not path.isdir(LAUNDIR): + mkdir(LAUNDIR) + + # Copy the launcher profiles + copy(LAUNPROF, path.join(LAUNDIR, 'launcher_profiles.json')) diff --git a/tests/install/test_loadingbar.py b/tests/install/test_loadingbar.py index 6153a2f..a1f968e 100644 --- a/tests/install/test_loadingbar.py +++ b/tests/install/test_loadingbar.py @@ -15,7 +15,7 @@ # along with this program. If not, see . import unittest -from ..vars import quiet +from ..globalfuncs import quiet from typing import Iterator from src.install.loadingbar import loadingbar diff --git a/tests/install/test_media.py b/tests/install/test_media.py index 782e201..2b1c38a 100644 --- a/tests/install/test_media.py +++ b/tests/install/test_media.py @@ -15,48 +15,56 @@ # along with this program. If not, see . import unittest -from ..vars import quiet, empty_dir, current_dir, install_dir +from ..config import CURDIR, INSTDIR +from ..globalfuncs import cleanup, quiet +from .setup import setup_dirs from src.install.media import prepare, download_files from os import path -unittest.TestLoader.sortTestMethodsUsing = None # type: ignore -manifest_file = path.join(current_dir, 'assets', 'manifest.json') +manifest_file = path.join(CURDIR, 'assets', 'manifest.json') class Install(unittest.TestCase): # These tests need some serious improvement def test_media(self): - self._test_prepare() - self._test_download() + # Create the manifest + self.manifest = prepare.load_manifest(manifest_file) - @quiet - def _test_prepare(self): - manifest = prepare.load_manifest(manifest_file) + # Run all sub tests in order + self._test_prepare_client() + self._test_prepare_server() + self._test_download_client() + self._test_download_server() - empty_dir(install_dir) + @quiet + @cleanup + def _test_prepare_client(self): + setup_dirs() self.total_size_client = prepare( - install_dir, 'client', manifest).total_size + INSTDIR, 'client', self.manifest).total_size self.assertIsInstance(self.total_size_client, int) - empty_dir(install_dir) + @quiet + @cleanup + def _test_prepare_server(self): + setup_dirs() self.total_size_server = prepare( - install_dir, 'server', manifest).total_size + INSTDIR, 'server', self.manifest).total_size self.assertIsInstance(self.total_size_server, int) @quiet - def _test_download(self): - manifest = prepare.load_manifest(manifest_file) - - empty_dir(install_dir) + @cleanup + def _test_download_client(self): + setup_dirs() download_files(self.total_size_client, - install_dir, 'client', manifest) + INSTDIR, 'client', self.manifest) - empty_dir(install_dir) + @quiet + @cleanup + def _test_download_server(self): + setup_dirs() download_files(self.total_size_server, - install_dir, 'server', manifest) - - def tearDown(self): - empty_dir(install_dir) + INSTDIR, 'server', self.manifest) diff --git a/tests/install/test_modloaders.py b/tests/install/test_modloaders.py index 68bf6f5..37bf2eb 100644 --- a/tests/install/test_modloaders.py +++ b/tests/install/test_modloaders.py @@ -15,33 +15,36 @@ # along with this program. If not, see . import unittest -from ..vars import quiet, empty_dir, install_dir, launcher_dir +from ..config import INSTDIR, LAUNDIR +from ..globalfuncs import cleanup, quiet +from .setup import setup_dirs from src.install.modloaders import forge, fabric class Install(unittest.TestCase): @quiet + @cleanup def test_forge_client(self): - empty_dir(install_dir) - forge('1.20.1', '47.1.0', 'client', install_dir, launcher_dir) + setup_dirs() + forge('1.20.1', '47.1.0', 'client', INSTDIR, LAUNDIR) @quiet + @cleanup def test_forge_server(self): - empty_dir(install_dir) - forge('1.20.1', '47.1.0', 'server', install_dir) - - def tearDown(self): - empty_dir(install_dir, launcher_dir) + setup_dirs() + forge('1.20.1', '47.1.0', 'server', INSTDIR) if False: # Tests of unfinished features @quiet + @cleanup def test_fabric_client(self): - empty_dir(install_dir) - fabric('1.20.1', '0.14.22', 'client', install_dir) + setup_dirs() + fabric('1.20.1', '0.14.22', 'client', INSTDIR) @quiet + @cleanup def test_fabric_server(self): - empty_dir(install_dir) - fabric('1.20.1', '0.14.22', 'server', install_dir) + setup_dirs() + fabric('1.20.1', '0.14.22', 'server', INSTDIR) diff --git a/tests/install/test_urls.py b/tests/install/test_urls.py index c01f21a..adb5686 100644 --- a/tests/install/test_urls.py +++ b/tests/install/test_urls.py @@ -15,6 +15,7 @@ # along with this program. If not, see . import unittest + from src.install.urls import media_url, forge from src.install._types import Media @@ -62,7 +63,8 @@ def test_urls(self): "info": { "title": "Essential", "icon": "https://static.essential.gg/icon/256x256.png", - "description": "Essential is a quality of life mod that boosts Minecraft Java to the next level." + "description": "Essential is a quality of life mod that " + "boosts Minecraft Java to the next level." }, "sides": [ "client", @@ -72,10 +74,11 @@ def test_urls(self): # Test if they assert equal cases = { - media_url(cf_media): 'https://mediafilez.forgecdn.net/files/4586/218/worldedit-mod-7.2.15.jar', - media_url(pm_media): 'https://static.planetminecraft.com/files/resource_media/texture/unique-spawn-eggs-v1-5.zip', - media_url(mr_media): 'https://cdn-raw.modrinth.com/data/AANobbMI/versions/' + - 'OkwCNtFH/sodium-fabric-mc1.20.1-0.5.1.jar', + media_url(cf_media): "https://mediafilez.forgecdn.net/files/4586/218/worldedit-mod-7.2.15.jar", + media_url(pm_media): "https://static.planetminecraft.com/files/resource_media/" + "texture/unique-spawn-eggs-v1-5.zip", + media_url(mr_media): "https://cdn-raw.modrinth.com/data/AANobbMI/versions/" + "OkwCNtFH/sodium-fabric-mc1.20.1-0.5.1.jar", media_url(url_media): url_media['url'] } @@ -90,5 +93,6 @@ def test_urls(self): self.assertEqual( forge.forge_installer_url('1.20.1', '47.1.0'), - "https://maven.minecraftforge.net/net/minecraftforge/forge/1.20.1-47.1.0/forge-1.20.1-47.1.0-installer.jar" + "https://maven.minecraftforge.net/net/minecraftforge/forge/" + "1.20.1-47.1.0/forge-1.20.1-47.1.0-installer.jar" ) diff --git a/tests/vars.py b/tests/vars.py deleted file mode 100644 index 0e688f0..0000000 --- a/tests/vars.py +++ /dev/null @@ -1,47 +0,0 @@ -# MCM-Manager: Minecraft Modpack Manager -# Copyright (C) 2023 Tygo Everts -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -from contextlib import redirect_stdout -from typing import Callable, Any -from os import path, walk, remove -from shutil import rmtree - - -def quiet(func: Callable[..., Any]) -> Callable[..., Any]: - "A simple decorator function that supresses stdout" - def wrapper(*args: Any, **kwargs: Any): - with redirect_stdout(None): - result = func(*args, **kwargs) - return result - return wrapper - - -def empty_dir(*directories: str): - for directory in directories: - for root, dirs, files in walk(directory): - for f in files: - remove(path.join(root, f)) - for d in dirs: - rmtree(path.join(root, d)) - - -launcher_dir = path.realpath( - path.join(path.dirname(path.realpath(__file__)), '.minecraft')) - -install_dir = path.realpath(path.join(path.dirname( - path.realpath(__file__)), 'gamedir')) - -current_dir = path.dirname(path.realpath(__file__)) From f2e078d8ca4ba11a7196e51ff27653bf326e9f15 Mon Sep 17 00:00:00 2001 From: Tygo Everts Date: Tue, 21 Nov 2023 19:03:25 +0100 Subject: [PATCH 8/9] Renamed some tests --- tests/common/test_maven_coords.py | 2 +- tests/install/test_loadingbar.py | 2 +- tests/install/test_media.py | 2 +- tests/install/test_modloaders.py | 2 +- tests/install/test_urls.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/common/test_maven_coords.py b/tests/common/test_maven_coords.py index 6e806a8..78adf3b 100644 --- a/tests/common/test_maven_coords.py +++ b/tests/common/test_maven_coords.py @@ -3,7 +3,7 @@ from src.common.maven_coords import maven_parse -class Common(unittest.TestCase): +class MavenParse(unittest.TestCase): def test_maven_coords(self): cases: list[tuple[str, tuple[str, str], str, str]] = [ ( # With three parts diff --git a/tests/install/test_loadingbar.py b/tests/install/test_loadingbar.py index a1f968e..de38111 100644 --- a/tests/install/test_loadingbar.py +++ b/tests/install/test_loadingbar.py @@ -21,7 +21,7 @@ from src.install.loadingbar import loadingbar -class LoadingBar(unittest.TestCase): +class Loadingbar(unittest.TestCase): @quiet def test_bar(self): # Iterating diff --git a/tests/install/test_media.py b/tests/install/test_media.py index 2b1c38a..8b4d972 100644 --- a/tests/install/test_media.py +++ b/tests/install/test_media.py @@ -25,7 +25,7 @@ manifest_file = path.join(CURDIR, 'assets', 'manifest.json') -class Install(unittest.TestCase): +class Media(unittest.TestCase): # These tests need some serious improvement def test_media(self): # Create the manifest diff --git a/tests/install/test_modloaders.py b/tests/install/test_modloaders.py index 37bf2eb..d7cd927 100644 --- a/tests/install/test_modloaders.py +++ b/tests/install/test_modloaders.py @@ -22,7 +22,7 @@ from src.install.modloaders import forge, fabric -class Install(unittest.TestCase): +class Modloaders(unittest.TestCase): @quiet @cleanup def test_forge_client(self): diff --git a/tests/install/test_urls.py b/tests/install/test_urls.py index adb5686..79ae68f 100644 --- a/tests/install/test_urls.py +++ b/tests/install/test_urls.py @@ -20,7 +20,7 @@ from src.install._types import Media -class Install(unittest.TestCase): +class Urls(unittest.TestCase): def test_urls(self): # Define different media types cf_media: Media = { From eb46d6de68b68071f80c414d6076216b03fec451 Mon Sep 17 00:00:00 2001 From: Tygo Everts Date: Tue, 21 Nov 2023 19:09:46 +0100 Subject: [PATCH 9/9] Added copyright notices before merging to main --- src/runner.py | 16 ++++++++++++++++ tests/common/test_maven_coords.py | 16 ++++++++++++++++ tests/globalfuncs.py | 16 ++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/src/runner.py b/src/runner.py index f17a5e5..324e50e 100644 --- a/src/runner.py +++ b/src/runner.py @@ -1,3 +1,19 @@ +# MCM-Manager: Minecraft Modpack Manager +# Copyright (C) 2023 Tygo Everts +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + from argparse import ArgumentParser from dataclasses import dataclass, fields from os import path, makedirs diff --git a/tests/common/test_maven_coords.py b/tests/common/test_maven_coords.py index 78adf3b..c22c313 100644 --- a/tests/common/test_maven_coords.py +++ b/tests/common/test_maven_coords.py @@ -1,3 +1,19 @@ +# MCM-Manager: Minecraft Modpack Manager +# Copyright (C) 2023 Tygo Everts +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + import unittest from src.common.maven_coords import maven_parse diff --git a/tests/globalfuncs.py b/tests/globalfuncs.py index f944e25..e299dcd 100644 --- a/tests/globalfuncs.py +++ b/tests/globalfuncs.py @@ -1,3 +1,19 @@ +# MCM-Manager: Minecraft Modpack Manager +# Copyright (C) 2023 Tygo Everts +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + from contextlib import redirect_stdout from typing import Any, Callable from os import path, remove, walk