Created packages, testcases and better error handling

Created python packages and added first test cases. Added better error handling when api call returns None and created start of requirements function.
Moved rich_print_error() to console_output.py
This commit is contained in:
Jan-Luca Bogdan | BEL NET GmbH 2022-06-16 17:05:40 +02:00
parent 3943357569
commit 7f2404f0cd
12 changed files with 147 additions and 47 deletions

View File

@ -5,8 +5,9 @@
import os
try:
print("Installing Python packages and dependencies from requirements.txt...")
print("Installing Python packages and dependencies from requirements.txt...\n")
os.system('py -m pip install -r requirements.txt' if os.name=='nt' else 'pip install -r requirements.txt')
print("\nStart pluGET by launching the 'pluGET.py' file!")
except:
print("Requirements couldn't be installed. Check if file 'requirements.txt' is in the same folder and that Python3\
and pip is installed!")

View File

@ -7,12 +7,13 @@ import argparse
# check if folder 'src' is accessible with all modules needed and if not exit
try:
from src.handlers.handle_config import check_config, validate_config, config_value
from src.handlers.handle_config import check_config, validate_config
from src.utils.console_output import rename_console_title, clear_console, print_logo
from src.utils.utilities import rich_print_error, api_test_spiget
from src.utils.utilities import check_requirements, api_test_spiget
from src.handlers.handle_input import handle_input
except:
print("Folder 'src' not found in the directory or missing files detected! Please redownload the files from here: https://www.github.com/Neocky/pluGET")
print("Folder 'src' not found in the directory or missing files detected! \
\nPlease redownload the files from here: https://www.github.com/Neocky/pluGET")
sys.exit()
@ -20,9 +21,9 @@ if __name__ == "__main__":
check_config()
rename_console_title()
api_test_spiget()
#check_requirements()
check_requirements()
validate_config()
parser = argparse.ArgumentParser(description="Just an example",
parser = argparse.ArgumentParser(description="Arguments for pluGET",
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
#parser.add_argument("-a", "--archive", action="store_true", help="archive mode")
#parser.add_argument("--exclude", help="files to exclude")
@ -31,10 +32,10 @@ if __name__ == "__main__":
parser.add_argument("version", help="Version", nargs='?', default=None)
args = vars(parser.parse_args())
if args["mode"] is not None and args["object"] is not None:
# arguments were give and call the handle_input function to get the right function call
# arguments were used so call the handle_input function to get the right function call
handle_input(args["mode"], args["object"], args["version"], arguments_from_console=True)
else:
# no arguments were given so start pluGET console
# no arguments were used so start pluGET console
clear_console()
print_logo()
handle_input()

0
src/__init__.py Normal file
View File

0
src/handlers/__init__.py Normal file
View File

View File

@ -2,7 +2,7 @@
Handles the input through the pluGET command line
"""
from src.utils.utilities import rich_print_error
from src.utils.console_output import rich_print_error
from src.plugin.plugin_downloader import get_specific_plugin
@ -22,7 +22,7 @@ def handle_input(input_command=None, input_selected_object=None, input_parameter
Manages the correct function calling from the given input
"""
while True:
# when arguemnts were not passed from console
# when arguemnts were not passed from console ask for input
if arguments_from_console is False:
try:
input_command, input_selected_object, input_parameter = get_input()
@ -75,7 +75,7 @@ def handle_input(input_command=None, input_selected_object=None, input_parameter
rich_print_error("Error: Command not found. Please try again. :(")
rich_print_error("Use: 'help command' to get all available commands")
# return to break out of while loop
# return to break out of while loop if pluGET was started with arguments from console
if arguments_from_console:
return None

0
src/plugin/__init__.py Normal file
View File

View File

@ -9,8 +9,9 @@ from pathlib import Path
import rich
from src.utils.utilities import rich_print_error, convert_file_size_down, remove_temp_plugin_folder, create_temp_plugin_folder
from src.utils.utilities import convert_file_size_down, remove_temp_plugin_folder, create_temp_plugin_folder
from src.utils.utilities import api_do_request
from src.utils.console_output import rich_print_error
from src.handlers.handle_config import config_value
@ -41,12 +42,15 @@ def get_version_id(plugin_id, plugin_version) -> str:
if plugin_version == None or plugin_version == 'latest':
url = f"https://api.spiget.org/v2/resources/{plugin_id}/versions/latest"
response = api_do_request(url)
if response == None:
return None
version_id = response["id"]
return version_id
url = f"https://api.spiget.org/v2/resources/{plugin_id}/versions?size=100&sort=-name"
version_list = api_do_request(url)
if response == None:
return None
for plugins in version_list:
plugin_update = plugins["name"]
version_id = plugins["id"]
@ -55,32 +59,34 @@ def get_version_id(plugin_id, plugin_version) -> str:
return version_list[0]["id"]
def getVersionName(plugin_id, plugin_version_id) -> str:
def get_version_name(plugin_id, plugin_version_id) -> str:
"""
Returns the name of a specific version
"""
url = f"https://api.spiget.org/v2/resources/{plugin_id}/versions/{plugin_version_id}"
response = api_do_request(url)
if response == None:
return None
version_name = response["name"]
return version_name
def get_download_path() -> str:
def get_download_path(config_values) -> str:
"""
Reads the config and gets the path of the plugin folder
"""
config_values = config_value()
if config_values.connection == "local":
if config_values.local_seperate_download_path is True:
match (config_values.connection):
case "local":
match (config_values.local_seperate_download_path):
case True:
return config_values.local_path_to_seperate_download_path
else:
case _:
return config_values.path_to_plugin_folder
else:
if config_values.remote_seperate_download_path is True:
case _:
match (config_values.remote_seperate_download_path):
case True:
return config_values.remote_path_to_seperate_download_path
else:
case _:
return config_values.remote_plugin_folder_on_server
@ -136,10 +142,12 @@ def get_specific_plugin(plugin_id, plugin_version="latest") -> None:
if config_values.connection != "local":
download_path = create_temp_plugin_folder()
else:
download_path = get_download_path()
download_path = get_download_path(config_values)
url = f"https://api.spiget.org/v2/resources/{plugin_id}"
plugin_details = api_do_request(url)
if plugin_details == None:
return None
try:
plugin_name = plugin_details["name"]
except KeyError:
@ -148,7 +156,7 @@ def get_specific_plugin(plugin_id, plugin_version="latest") -> None:
return None
plugin_name = handle_regex_package_name(plugin_name)
plugin_version_id = get_version_id(plugin_id, plugin_version)
plugin_version_name = getVersionName(plugin_id, plugin_version_id)
plugin_version_name = get_version_name(plugin_id, plugin_version_id)
plugin_download_name = f"{plugin_name}-{plugin_version_name}.jar"
download_plugin_path = Path(f"{download_path}/{plugin_download_name}")
# set the plugin_version_id to None if a specific version wasn't given as parameter

0
src/tests/__init__.py Normal file
View File

View File

@ -0,0 +1,58 @@
import unittest
from src.plugin import plugin_downloader
from src.utils import utilities
class TestCases(unittest.TestCase):
def test_handle_regex_package_name(self):
plugin_name = "[1.13-5.49 ❤] >|> SUPERB Plugin <<💥| Now 150% OFF IN WINTER SALE IN SUMMER???"
plugin_name_cropped = "SUPERBPlugin"
result = plugin_downloader.handle_regex_package_name(plugin_name)
self.assertEqual(result, plugin_name_cropped)
def test_get_version_id(self):
# 1234 -> "AntiPickup" in Version 1.4.1
result = plugin_downloader.get_version_id("1234", "1.4.1")
self.assertEqual(result, 43779)
def test_get_version_name(self):
# 43779 -> "1.4.1" from AntiPickup
result = plugin_downloader.get_version_name("1234", 43779)
self.assertEqual(result, "1.4.1")
def test_get_download_path(self):
# local plugin folder
class config_values_local:
connection = "local"
local_seperate_download_path = True
local_path_to_seperate_download_path = "/local/path/plugins"
result=plugin_downloader.get_download_path(config_values_local)
self.assertEqual(result, config_values_local.local_path_to_seperate_download_path)
# plugin folder over sftp
class config_values_sftp:
connection = "sftp"
remote_seperate_download_path = True
remote_path_to_seperate_download_path = "/sftp/path/plugins"
result=plugin_downloader.get_download_path(config_values_sftp)
self.assertEqual(result, config_values_sftp.remote_path_to_seperate_download_path)
# plugin folder over ftp
class config_values_ftp:
connection = "ftp"
remote_seperate_download_path = True
remote_path_to_seperate_download_path = "/ftp/path/plugins"
result=plugin_downloader.get_download_path(config_values_ftp)
self.assertEqual(result, config_values_ftp.remote_path_to_seperate_download_path)
def test_convert_file_size_down(self):
result= utilities.convert_file_size_down(100000)
self.assertEqual(result, 97.66)
if __name__ == "__main__":
unittest.main()

0
src/utils/__init__.py Normal file
View File

View File

@ -6,11 +6,21 @@ import os
from rich.console import Console
def rich_print_error(error_message) -> None:
"""
Prints a formatted error message from rich
"""
console = Console()
console.print(error_message, style="bright_red")
return None
def rename_console_title() -> None:
"""
Renames the console title on first startup
"""
os.system("title " + "pluGET │ By Neocky")
return None
def clear_console() -> None:
@ -18,6 +28,7 @@ def clear_console() -> None:
Clears the console on first startup
"""
os.system('cls' if os.name=='nt' else 'clear')
return None
def print_logo() -> None:
@ -124,3 +135,4 @@ def print_logo() -> None:
# line 12
console.print(" └────────────────────────────────────┘", style="bright_black")
console.print(" ───────────────────────────────────────────────────")
return None

View File

@ -7,7 +7,9 @@ import sys
import requests
import shutil
from pathlib import Path
from rich.console import Console
from src.utils.console_output import rich_print_error
from src.handlers.handle_config import config_value
def api_do_request(url) -> list:
@ -19,7 +21,8 @@ def api_do_request(url) -> list:
response = requests.get(url, headers=webrequest_header)
except:
print("Couldn't create webrequest")
return
# return None to make functions quit
return None
api_json_data = response.json()
return api_json_data
@ -31,25 +34,14 @@ def api_test_spiget() -> None:
try:
r = requests.get('https://api.spiget.org/v2/status')
except (requests.exceptions.HTTPError, requests.exceptions.ConnectionError):
rich_print_error("Error: Couldn't make a connection to the API. Check you connection to the internet!", style="bright_red")
rich_print_error("Press any key + enter to exit...")
rich_print_error("Error: Couldn't make a connection to the API. Check you connection to the internet!")
sys.exit()
if r.status_code != 200:
rich_print_error("Error: Problems with the API detected. Plese try it again later!")
rich_print_error("Press any key + enter to exit...")
sys.exit()
return
def rich_print_error(error_message) -> None:
"""
Prints a formatted error message from rich
"""
console = Console()
console.print(error_message, style="bright_red")
return
def create_temp_plugin_folder() -> Path:
"""
Creates a temporary folder to store plugins inside
@ -64,7 +56,6 @@ def create_temp_plugin_folder() -> Path:
except OSError:
rich_print_error(f"Error: Creation of directory {path_temp_plugin_folder} failed")
rich_print_error(" Please check for missing permissions in folder tree!")
input("Press any key + enter to exit...")
sys.exit()
return path_temp_plugin_folder
@ -87,3 +78,32 @@ def convert_file_size_down(file_size) -> float:
converted_file_size = (int(file_size)) / 1024
converted_file_size = round(converted_file_size, 2)
return converted_file_size
def check_local_plugin_folder(config_values) -> None:
"""
Check if a local plugin folder exists and if not exit the programm
"""
if config_values.local_seperate_download_path:
plugin_folder_path = config_values.local_path_to_seperate_download_path
else:
plugin_folder_path = config_values.path_to_plugin_folder
if not os.path.isdir(plugin_folder_path):
rich_print_error(f"Error: Local plugin folder '{plugin_folder_path}' couldn't be found! \
\n Check the config and try again!")
sys.exit()
return None
def check_requirements() -> None:
"""
Check if the plugin folders are available
"""
config_values = config_value()
match config_values.connection:
case "local":
check_local_plugin_folder(config_values)
case "sftp":
print("Check sftp folder")
case "ftp":
print("check ftp folder")