Skip to content
This repository has been archived by the owner on Oct 27, 2024. It is now read-only.

Commit

Permalink
Merge pull request #12 from tygoee/dev
Browse files Browse the repository at this point in the history
Improve loadingbar types and merge all types in one file
  • Loading branch information
tygoee authored Nov 22, 2023
2 parents 5786d53 + 56f8089 commit 940410f
Show file tree
Hide file tree
Showing 9 changed files with 216 additions and 117 deletions.
2 changes: 1 addition & 1 deletion src/install/filesize.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# Copyright (C) Martijn Faassen, Startifact
# <https://pypi.org/project/hurry.filesize/>

from ._types import SizeSystem
from ..typings import SizeSystem

traditional: SizeSystem = [
(1024 ** 5, 'P'),
Expand Down
121 changes: 86 additions & 35 deletions src/install/loadingbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,66 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.

from os import get_terminal_size
from typing import Collection, Generic, Literal, TypeVar, Optional, Type
from types import TracebackType
from typing import (
Collection, Generic, Literal, TypeVar,
Optional, overload, TYPE_CHECKING
)

if TYPE_CHECKING:
from types import TracebackType

from .filesize import size, traditional

T = TypeVar("T")
_T = TypeVar("_T")


class loadingbar(Generic[_T]):
@overload
def __init__(
# total
self, iterator: Collection[_T], /, *,
unit: Literal['it', 'B'] = 'it',
bar_length: Optional[int] = None,
bar_format: str = "{title} {percentage:3.0f}% [{bar}] {current}/{total}",
title: str = '',
show_desc: bool = False,
desc: str = '',
disappear: bool = False,
) -> None: ...

@overload
def __init__(
# total
self, /, *,
total: _T,
unit: Literal['it', 'B'] = 'it',
bar_length: Optional[int] = None,
bar_format: str = "{title} {percentage:3.0f}% [{bar}] {current}/{total}",
title: str = '',
show_desc: bool = False,
desc: str = '',
disappear: bool = False,
) -> None: ...

class loadingbar(Generic[T]):
@overload
def __init__(
self, iterator: Collection[T] | None = None, /, *,
# both
self, iterator: Optional[Collection[_T]] = None, /, *,
total: int = 0,
unit: Literal['it', 'B'] = 'it',
bar_length: int | None = None,
bar_length: Optional[int] = None,
bar_format: str = "{title} {percentage:3.0f}% [{bar}] {current}/{total}",
title: str = '',
show_desc: bool = False,
desc: str = '',
disappear: bool = False,
) -> None: ...

def __init__(
self, iterator: Optional[Collection[_T]] = None, /, *,
total: int | _T = 0,
unit: Literal['it', 'B'] = 'it',
bar_length: Optional[int] = None,
bar_format: str = "{title} {percentage:3.0f}% [{bar}] {current}/{total}",
title: str = '',
show_desc: bool = False,
Expand All @@ -54,21 +100,18 @@ def __init__(
:param disappear: If you want the bar to disappear
"""

# Define class variables
self._iter_type: Literal['iter', 'total', 'both']

if iterator is not None and total == 0:
self._iter_type = 'iter'
# iter
self.iterator = iterator
self.iterable = iter(iterator)
self.iterator_len = len(iterator)
elif iterator is None and total != 0:
self._iter_type = 'total'
# total
self.iterator = None
self.iterable = None
self.total = total
elif iterator is not None and total != 0:
self._iter_type = 'both'
# both
self.iterator = iterator
self.iterable = iter(iterator)
self.iterator_len = len(iterator)
Expand Down Expand Up @@ -112,40 +155,44 @@ def __init__(
else:
self.bar_length = bar_length

def __iter__(self) -> "loadingbar[T]":
def __iter__(self) -> "loadingbar[_T]":
"Method that allows iterators"

return self

def __next__(self) -> T:
def __next__(self) -> _T:
"Go to the next iteration"

# Update the item and idx
if self.iterable is not None:
self.item = next(self.iterable)
self.idx += 1
elif self.idx < self.total: # 'total'
self.idx += 1
else:
raise StopIteration
if TYPE_CHECKING and not isinstance(self.total, int):
raise TypeError

if self.idx < self.total: # total
self.idx += 1
else:
raise StopIteration

# Refresh the loading bar
self.refresh()

# Return the item
if self.iterator is not None: # 'both' or 'iter'
if self.iterator is not None: # both or iter
return self.item
else:
return self.idx # type: ignore

def __enter__(self) -> "loadingbar[T]":
def __enter__(self) -> "loadingbar[_T]":
"Allow a with-as statement"

return self

def __exit__(self, exc_type: Optional[Type[BaseException]],
def __exit__(self, exc_type: Optional[type[BaseException]],
exc_value: Optional[BaseException],
traceback: Optional[TracebackType]) -> bool:
traceback: Optional['TracebackType']) -> bool:
"Allow a with-as statement"

return False # No errors
Expand All @@ -154,7 +201,10 @@ def refresh(self) -> None:
"Refresh the loading bar, called automatically"

# Calculate progress
if self._iter_type in ('both', 'total'):
if hasattr(self, 'total'): # both, total
if TYPE_CHECKING and not isinstance(self.total, int):
raise TypeError

percent = round(self.idx / self.total * 100, 0)
else:
percent = round(self.idx / self.iterator_len * 100, 0)
Expand All @@ -165,12 +215,16 @@ def refresh(self) -> None:
# Define the current and total
if self.unit == 'it':
current = str(self.idx)
total = str(self.total if self._iter_type in (
'both', 'total') else self.iterator_len)
total = str(self.total if hasattr(
self, 'total') else self.iterator_len)
else:
current = size(self.idx, traditional)
total = size(self.total if self._iter_type in (
'both', 'total') else self.iterator_len, traditional)
arg = self.total if hasattr(self, 'total') else self.iterator_len

if TYPE_CHECKING and not isinstance(arg, int):
raise TypeError

total = size(arg, traditional)

# Define the text length
text_length = self.formatting_length + \
Expand All @@ -181,12 +235,10 @@ def refresh(self) -> None:
# Print the loading bar
start = '\033[F\r' if self.show_desc else '\r'

if self.show_desc and self._new_desc:
end = '\n\033[K' + self.desc
elif self.show_desc:
end = '\n' + self.desc
else:
end = ''
end = (
'\n\033[K' + self.desc if self.show_desc and self._new_desc
else '\n' + self.desc if self.show_desc else ''
)

print(start + self.bar_format.format(
title=self.title,
Expand All @@ -197,8 +249,7 @@ def refresh(self) -> None:
), end=end)

# Clear the loading bar at the end
if self.idx == (self.total if self._iter_type in (
'both', 'total') else self.iterator_len):
if self.idx == (self.total if hasattr(self, 'total') else self.iterator_len):
if self.disappear and self.show_desc:
print('\r\033[K\033[F\r\033[K', end='')
elif self.disappear:
Expand All @@ -208,7 +259,7 @@ def refresh(self) -> None:

def update(self, amount: int) -> None:
"Add 'n' amount of iterations to the loading bar"
if self._iter_type == 'iter':
if not hasattr(self, 'total'):
i = 0

# Call next(self) while less than amount
Expand Down
6 changes: 3 additions & 3 deletions src/install/media.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from .modloaders import inst_modloader, MINECRAFT_DIR
from .filesize import size, alternative

from ._types import Manifest, URLMedia, Media, MediaList, Side
from ..typings import Manifest, URLMedia, Media, MediaList, Side


class prepare:
Expand Down Expand Up @@ -218,7 +218,6 @@ def download_files(total_size: int, install_path: str, side: Side, manifest: Man
show_desc=True,
disappear=True
) as bar:
bar: loadingbar[int] # The only way it worked out
for url, fname, fsize, sides in iterator:
if side not in sides:
# As the size isn't calculated, it
Expand Down Expand Up @@ -307,7 +306,8 @@ def install(

# Print the mod info
print(
f"\n{len(mods)} mods, {len(resourcepacks)} recourcepacks, {len(shaderpacks)} shaderpacks\n"
f"\n{len(mods)} mods, {len(resourcepacks)} "
f"recourcepacks, {len(shaderpacks)} shaderpacks\n"
f"Total file size: {size(total_size, system=alternative)}"
)

Expand Down
62 changes: 20 additions & 42 deletions src/install/modloaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.

from atexit import register
from http.client import HTTPResponse
from json import load, loads, dump
from os import path, getenv, mkdir, rename
from shutil import rmtree, copyfile
Expand All @@ -24,16 +25,16 @@
from urllib import request
from zipfile import ZipFile

from .urls import forge as forge_urls, fabric as fabric_urls
from .loadingbar import loadingbar
from .urls import forge as forge_urls

from ..common.maven_coords import maven_parse

from ._types import (
from ..typings import (
Client, Server, Side, Modloader,
MinecraftJson, VersionJson,
ForgeLibrary, ForgeVersionJson,
InstallProfile, Libraries,
Library, OSLibrary
MinecraftJson, OSLibrary
)

# Define the minecraft directory
Expand Down Expand Up @@ -105,13 +106,14 @@ def __init__(self, mc_version: str,
"Please make sure you have Java installed and it is properly configured."
)

self.minecraft_json: MinecraftJson = loads(request.urlopen(
[item for item in loads(
request.urlopen(
forge_urls.version_manifest_v2
).read().decode('utf-8')
)['versions'] if item['id'] == mc_version][0]['url']
).read().decode('utf-8'))
v_man_v2: HTTPResponse = request.urlopen(
forge_urls.version_manifest_v2)

for item in loads(v_man_v2.read().decode('utf-8'))['versions']:
if item['id'] == mc_version:
_res: HTTPResponse = request.urlopen(item['url'])
self.minecraft_json: MinecraftJson = loads(
_res.read().decode('utf-8'))

# Exit if the launcher hasn't launched once
if not path.isfile(path.join(launcher_dir, 'launcher_profiles.json')) and side == 'client':
Expand All @@ -127,7 +129,7 @@ def __init__(self, mc_version: str,
with archive.open('install_profile.json') as fp:
self.install_profile: InstallProfile = load(fp)
with archive.open('version.json') as fp:
self.version_json: VersionJson = load(fp)
self.version_json: ForgeVersionJson = load(fp)

# Define the forge dir
forge_dir = path.join(
Expand Down Expand Up @@ -203,8 +205,10 @@ def download_jar_files(self) -> None:

if self.side == 'client':
# Make the required directories
for directory in [path.join(self.launcher_dir, 'versions'),
path.join(self.launcher_dir, 'versions', self.mc_version)]:
for directory in [
path.join(self.launcher_dir, 'versions'),
path.join(self.launcher_dir, 'versions', self.mc_version)
]:
if not path.isdir(directory):
mkdir(directory)

Expand All @@ -227,7 +231,7 @@ def download_jar_files(self) -> None:
break
mod_file.write(resp_data)

def download_library(self, bar: loadingbar[Library | OSLibrary], library: Library) -> None:
def download_library(self, bar: loadingbar[ForgeLibrary | OSLibrary], library: ForgeLibrary) -> None:
"""Download a library"""
# Define the java os names
osdict = {
Expand Down Expand Up @@ -384,33 +388,7 @@ def build_processors(self) -> None:


class fabric:
"I accidentally uploaded this, it's unfinished"

def __init__(self, mc_version: str,
fabric_version: str,
side: Side,
install_dir: str = MINECRAFT_DIR,
launcher_dir: str = MINECRAFT_DIR) -> None:

self.mc_version = mc_version

# Define the class variables
launcher_dir = install_dir if side == 'server' else launcher_dir

self.mc_version = mc_version
self.fabric_version = fabric_version
self.side = side
self.install_dir = install_dir
self.launcher_dir = launcher_dir

self.install_version()

def install_version(self):
print(request.urlopen(fabric_urls.api_url(
'v2', 'versions', 'loader',
self.mc_version, self.fabric_version,
'server', 'json'
)).read().decode('utf-8'))
pass


def inst_modloader(
Expand Down
8 changes: 1 addition & 7 deletions src/install/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

from ._types import Media
from ..typings import Media


def media_url(media: Media) -> str:
Expand Down Expand Up @@ -44,9 +44,3 @@ class forge:
def forge_installer_url(mc_version: str, forge_version: str) -> str:
return "https://maven.minecraftforge.net/net/minecraftforge/forge/" \
f"{mc_version}-{forge_version}/forge-{mc_version}-{forge_version}-installer.jar"


class fabric:
@staticmethod
def api_url(*paths: str) -> str:
return "https://meta.fabricmc.net/" + '/'.join(paths)
Loading

0 comments on commit 940410f

Please sign in to comment.