Lgndr: Replace the monkey functions with factories to create them
The factories are also usable in Rare's code to create compatible functions for the callbacks. If they there is no callback they just log what is happening. It also removes the need for `typing-extentions` module.
This commit is contained in:
parent
df0f7603f2
commit
fa5294b1d5
|
@ -12,7 +12,7 @@ script:
|
|||
# copy Logo
|
||||
- cp AppDir/usr/src/rare/resources/images/Rare.png AppDir/usr/share/icons/hicolor/256x256/apps/
|
||||
# Install application dependencies
|
||||
- python3 -m pip install --ignore-installed --prefix=/usr --root=AppDir pypresence qtawesome legendary-gl orjson typing_extensions
|
||||
- python3 -m pip install --ignore-installed --prefix=/usr --root=AppDir pypresence qtawesome legendary-gl orjson
|
||||
|
||||
AppDir:
|
||||
path: AppDir
|
||||
|
|
59
README.md
59
README.md
|
@ -45,32 +45,36 @@ Run it via:
|
|||
There are some AUR packages available:
|
||||
|
||||
- [rare](https://aur.archlinux.org/packages/rare) - for stable releases
|
||||
- [rare-git](https://aur.archlinux.org/packages/rare-git) - for the latest features, which are not in a stable release
|
||||
- [rare-git](https://aur.archlinux.org/packages/rare-git) - for the latest development version
|
||||
|
||||
#### Debian based
|
||||
|
||||
- DUR package: [rare](https://mpr.hunterwittenborn.com/packages/rare)
|
||||
- .deb file in [releases page](https://github.com/Dummerle/Rare/releases)
|
||||
- `.deb` file in [releases page](https://github.com/Dummerle/Rare/releases)
|
||||
|
||||
**Note**:
|
||||
|
||||
- pypresence is an optional package. You can install it
|
||||
from [DUR](https://mpr.hunterwittenborn.com/packages/python3-pypresence) or with pip.
|
||||
- Do not wonder if some icons look strange, because the official python3-qtawesome package is too old. Many icons were
|
||||
replaced.
|
||||
- pypresence is an optional package. You can install it from [DUR](https://mpr.hunterwittenborn.com/packages/python3-pypresence) or with pip.
|
||||
- Some icons might look strange on Debian based distributions. The official python3-qtawesome package is too old.
|
||||
|
||||
|
||||
### macOS
|
||||
|
||||
There is a .dmg file available in [releases page](https://github.com/Dummerle/Rare/releases).
|
||||
There is a `.dmg` file available in [releases page](https://github.com/Dummerle/Rare/releases).
|
||||
|
||||
**Note**: When you launch it, you will see an error, that the package is from an unknown source. You have to enable it
|
||||
manually in `Settings -> Security and Privacy`. Otherwise, Gatekeeper will block Rare from running.
|
||||
**Note**: When you launch it, you will see an error, that the package is from an unknown source. You have to enable it manually in `Settings -> Security and Privacy`. Otherwise, Gatekeeper will block Rare from running.
|
||||
|
||||
You can also use `pip`.
|
||||
|
||||
### Windows
|
||||
|
||||
There is an `.msi` installer available in [releases page](https://github.com/Dummerle/Rare/releases).
|
||||
|
||||
There is also a semi-portable `.zip` archive in [releases page](https://github.com/Dummerle/Rare/releases) that lets you run Rare without installing it.
|
||||
|
||||
**Important**: On recent version of Windows you should have MSVC 2015 installed, you can get it from [here](https://learn.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist?view=msvc-170#visual-studio-2015-2017-2019-and-2022)
|
||||
|
||||
#### Packages
|
||||
|
||||
- Rare is available as a [Winget package](https://github.com/microsoft/winget-pkgs/tree/master/manifests/d/Dummerle/Rare)
|
||||
You can install Rare with the following one-liner:
|
||||
|
||||
|
@ -81,10 +85,7 @@ You can install Rare with the following one-liner:
|
|||
|
||||
`choco install rare`
|
||||
|
||||
- There is a small beta tool for Windows: [Rare Updater](https://github.com/Dummerle/RareUpdater), which installs and updates rare with a single click
|
||||
|
||||
|
||||
*NOTE*: On recent Windows you should have MSVC 2015 installed, you can get it from [here](https://learn.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist?view=msvc-170#visual-studio-2015-2017-2019-and-2022)
|
||||
- We also have a beta tool for Windows: [Rare Updater](https://github.com/Dummerle/RareUpdater), which installs and updates rare with a single click
|
||||
|
||||
### Packages
|
||||
|
||||
|
@ -95,7 +96,8 @@ file for macOS.
|
|||
|
||||
In the [actions](https://github.com/Dummerle/Rare/actions) tab you can find packages for the latest commits.
|
||||
|
||||
**Note**: They might be unstable.
|
||||
**Note**: They might be unstable and likely broken.
|
||||
|
||||
|
||||
### Installation via pip (platform independent)
|
||||
|
||||
|
@ -105,22 +107,13 @@ Linux, Mac and FreeBSD: execute `rare` in your terminal.
|
|||
|
||||
Windows: execute `pythonw -m rare` in cmd
|
||||
|
||||
It is possible to create a desktop link, or a start menu link. Execute the command above with `--desktop-shortcut`
|
||||
or `--startmenu-shortcut` option, alternatively you can create them in the settings.
|
||||
It is possible to create a desktop link, or a start menu link. Execute the command above with `--desktop-shortcut` or `--startmenu-shortcut` option, alternatively you can create them in the settings.
|
||||
|
||||
**Note about $PATH**:
|
||||
|
||||
On Linux:
|
||||
|
||||
`/home/user/.local/bin` must be in your PATH.
|
||||
|
||||
On Windows:
|
||||
|
||||
`PythonInstallationDirectory\Scripts` must be in your PATH.
|
||||
|
||||
On Mac:
|
||||
|
||||
`/Users/user/Library/Python/3.x/bin` must be in your PATH.
|
||||
* On Linux `/home/user/.local/bin` must be in your PATH.
|
||||
* On Windows `PythonInstallationDirectory\Scripts` must be in your PATH.
|
||||
* On Mac `/Users/user/Library/Python/3.x/bin` must be in your PATH.
|
||||
|
||||
|
||||
### Run from source
|
||||
|
@ -128,10 +121,9 @@ On Mac:
|
|||
1. Clone the repo: `git clone https://github.com/Dummerle/Rare
|
||||
2. Change your working directory to the project folder: `cd Rare`
|
||||
3. Run `pip install -r requirements.txt` to install all required dependencies.
|
||||
If you want to be able to use the automatic login and Discord pypresence, run `pip install -r requirements-full.txt`
|
||||
If you are on Arch you can
|
||||
run `sudo pacman --needed -S python-wheel python-setuptools python-pyqt5 python-qtawesome python-requests python-typing_extensions` and `yay -S legendary`
|
||||
If you are on FreeBSD you have to install py39-qt5 from the packages: `sudo pkg install py39-qt5`
|
||||
* If you want to be able to use the automatic login and Discord pypresence, run `pip install -r requirements-full.txt`
|
||||
* If you are on Arch you can run `sudo pacman --needed -S python-wheel python-setuptools python-pyqt5 python-qtawesome python-requests python-orjson` and `yay -S legendary`
|
||||
* If you are on FreeBSD you have to install py39-qt5 from the packages: `sudo pkg install py39-qt5`
|
||||
4. Run `python3 -m rare`
|
||||
|
||||
## Contributing
|
||||
|
@ -139,8 +131,7 @@ On Mac:
|
|||
There are several options to contribute.
|
||||
|
||||
- If you know Python and PyQt, you can implement new features (Some ideas are in the projects tab).
|
||||
- You can translate the application in your language: Check our [transifex](https://www.transifex.com/rare-1/rare) page
|
||||
for that.
|
||||
- You can translate the application in your language: Check our [transifex](https://www.transifex.com/rare-1/rare) page for that.
|
||||
|
||||
More information is available in CONTRIBUTING.md.
|
||||
|
||||
|
|
|
@ -388,7 +388,6 @@ class LegendaryCLI(LegendaryCLIReal):
|
|||
# Override logger for the local context to use message as part of the indirect return value
|
||||
logger = LgndrIndirectLogger(args.indirect_status, self.logger, logging.WARNING)
|
||||
get_boolean_choice = args.get_boolean_choice_main
|
||||
# def get_boolean_choice(x, default): return True
|
||||
if not self.core.lgd.lock_installed():
|
||||
logger.fatal('Failed to acquire installed data lock, only one instance of Legendary may '
|
||||
'install/import/move applications at a time.')
|
||||
|
@ -429,7 +428,6 @@ class LegendaryCLI(LegendaryCLIReal):
|
|||
# Override logger for the local context to use message as part of the indirect return value
|
||||
logger = LgndrIndirectLogger(args.indirect_status, self.logger, logging.WARNING)
|
||||
get_boolean_choice = args.get_boolean_choice_handler
|
||||
# def get_boolean_choice(x, default): return True
|
||||
# noinspection PyShadowingBuiltins
|
||||
def print(x): self.logger.info(x) if x else None
|
||||
|
||||
|
|
|
@ -4,9 +4,10 @@ from typing import Callable, List, Optional, Dict
|
|||
|
||||
from rare.lgndr.glue.monkeys import (
|
||||
LgndrIndirectStatus,
|
||||
GetBooleanChoiceProtocol,
|
||||
get_boolean_choice,
|
||||
verify_stdout,
|
||||
get_boolean_choice_factory,
|
||||
sdl_prompt_factory,
|
||||
verify_stdout_factory,
|
||||
ui_update_factory,
|
||||
DLManagerSignals,
|
||||
)
|
||||
from rare.lgndr.models.downloading import UIUpdate
|
||||
|
@ -33,7 +34,7 @@ class LgndrImportGameArgs:
|
|||
yes: bool = False
|
||||
# Rare: Extra arguments
|
||||
indirect_status: LgndrIndirectStatus = field(default_factory=LgndrIndirectStatus)
|
||||
get_boolean_choice: GetBooleanChoiceProtocol = get_boolean_choice
|
||||
get_boolean_choice: Callable[[str, bool], bool] = get_boolean_choice_factory(True)
|
||||
|
||||
|
||||
@dataclass
|
||||
|
@ -44,8 +45,8 @@ class LgndrUninstallGameArgs:
|
|||
yes: bool = False
|
||||
# Rare: Extra arguments
|
||||
indirect_status: LgndrIndirectStatus = field(default_factory=LgndrIndirectStatus)
|
||||
get_boolean_choice_main: GetBooleanChoiceProtocol = get_boolean_choice
|
||||
get_boolean_choice_handler: GetBooleanChoiceProtocol = get_boolean_choice
|
||||
get_boolean_choice_main: Callable[[str, bool], bool] = get_boolean_choice_factory(True)
|
||||
get_boolean_choice_handler: Callable[[str, bool], bool] = get_boolean_choice_factory(True)
|
||||
|
||||
|
||||
@dataclass
|
||||
|
@ -53,7 +54,7 @@ class LgndrVerifyGameArgs:
|
|||
app_name: str
|
||||
# Rare: Extra arguments
|
||||
indirect_status: LgndrIndirectStatus = field(default_factory=LgndrIndirectStatus)
|
||||
verify_stdout: Callable[[int, int, float, float], None] = verify_stdout
|
||||
verify_stdout: Callable[[int, int, float, float], None] = verify_stdout_factory(None)
|
||||
|
||||
|
||||
@dataclass
|
||||
|
@ -94,14 +95,11 @@ class LgndrInstallGameArgs:
|
|||
yes: bool = True
|
||||
# Rare: Extra arguments
|
||||
indirect_status: LgndrIndirectStatus = field(default_factory=LgndrIndirectStatus)
|
||||
get_boolean_choice: GetBooleanChoiceProtocol = get_boolean_choice
|
||||
sdl_prompt: Callable[[str, str], List[str]] = lambda app_name, title: [""]
|
||||
verify_stdout: Callable[[int, int, float, float], None] = verify_stdout
|
||||
get_boolean_choice: Callable[[str, bool], bool] = get_boolean_choice_factory(True)
|
||||
verify_stdout: Callable[[int, int, float, float], None] = verify_stdout_factory(None)
|
||||
|
||||
# def __post_init__(self):
|
||||
# if self.sdl_prompt is None:
|
||||
# self.sdl_prompt: Callable[[str, str], list] = \
|
||||
# lambda app_name, title: self.install_tag if self.install_tag is not None else [""]
|
||||
def __post_init__(self):
|
||||
self.sdl_prompt: Callable[[Dict, str], List[str]] = sdl_prompt_factory(self.install_tag)
|
||||
|
||||
|
||||
@dataclass
|
||||
|
@ -119,8 +117,8 @@ class LgndrInstallGameRealArgs:
|
|||
# Rare: Extra arguments
|
||||
install_prereqs: bool = False
|
||||
indirect_status: LgndrIndirectStatus = field(default_factory=LgndrIndirectStatus)
|
||||
ui_update: Callable[[UIUpdate], None] = lambda ui: None
|
||||
dlm_signals: DLManagerSignals = DLManagerSignals()
|
||||
ui_update: Callable[[UIUpdate], None] = ui_update_factory(None)
|
||||
dlm_signals: DLManagerSignals = field(default_factory=DLManagerSignals)
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
|
@ -1,20 +1,48 @@
|
|||
import logging
|
||||
from dataclasses import dataclass
|
||||
from typing import Callable, List, Optional, Dict
|
||||
|
||||
from typing_extensions import Protocol
|
||||
from rare.lgndr.models.downloading import UIUpdate
|
||||
|
||||
logger = logging.getLogger("LgndrMonkeys")
|
||||
|
||||
|
||||
class GetBooleanChoiceProtocol(Protocol):
|
||||
def __call__(self, prompt: str, default: bool = ...) -> bool:
|
||||
...
|
||||
def get_boolean_choice_factory(value: bool = True) -> Callable[[str, bool], bool]:
|
||||
def get_boolean_choice(prompt: str, default: bool) -> bool:
|
||||
logger.debug("get_boolean_choice: %s, default: %s, choice: %s", prompt, default, value)
|
||||
return value
|
||||
return get_boolean_choice
|
||||
|
||||
|
||||
def get_boolean_choice(prompt: str, default: bool = True) -> bool:
|
||||
return default
|
||||
def sdl_prompt_factory(install_tag: Optional[List[str]] = None) -> Callable[[Dict, str], List[str]]:
|
||||
def sdl_prompt(sdl_data: Dict, title: str) -> List[str]:
|
||||
logger.debug("sdl_prompt: %s", title)
|
||||
for key in sdl_data.keys():
|
||||
logger.debug("%s: %s %s", key, sdl_data[key]["tags"], sdl_data[key]["name"])
|
||||
tags = install_tag if install_tag is not None else [""]
|
||||
logger.debug("choice: %s, tags: %s", install_tag, tags)
|
||||
return tags
|
||||
return sdl_prompt
|
||||
|
||||
|
||||
def verify_stdout(a0: int, a1: int, a2: float, a3: float) -> None:
|
||||
print(f"Verification progress: {a0}/{a1} ({a2:.01f}%) [{a3:.1f} MiB/s]\t\r")
|
||||
def verify_stdout_factory(
|
||||
callback: Callable[[int, int, float, float], None] = None
|
||||
) -> Callable[[int, int, float, float], None]:
|
||||
def verify_stdout(a0: int, a1: int, a2: float, a3: float) -> None:
|
||||
if callback is not None and callable(callback):
|
||||
callback(a0, a1, a2, a3)
|
||||
else:
|
||||
logger.info("Verification progress: %d/%d (%.01f%%) [%.1f MiB/s]", a0, a1, a2, a3)
|
||||
return verify_stdout
|
||||
|
||||
|
||||
def ui_update_factory(callback: Callable[[UIUpdate], None] = None) -> Callable[[UIUpdate], None]:
|
||||
def ui_update(status: UIUpdate) -> None:
|
||||
if callback is not None and callable(callback):
|
||||
callback(status)
|
||||
else:
|
||||
logger.info("Installation progress: %s", status)
|
||||
return ui_update
|
||||
|
||||
|
||||
class DLManagerSignals:
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import os
|
||||
import platform as pf
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timedelta
|
||||
from typing import List, Optional, Callable, Dict, Tuple
|
||||
from typing import List, Optional, Dict, Tuple
|
||||
|
||||
from legendary.models.downloading import AnalysisResult, ConditionCheckResult
|
||||
from legendary.models.game import Game, InstalledGame
|
||||
|
@ -35,10 +34,6 @@ class InstallOptionsModel:
|
|||
silent: bool = False
|
||||
install_prereqs: bool = False
|
||||
|
||||
def __post_init__(self):
|
||||
self.sdl_prompt: Callable[[str, str], list] = \
|
||||
lambda app_name, title: self.install_tag if self.install_tag is not None else [""]
|
||||
|
||||
def as_install_kwargs(self) -> Dict:
|
||||
return {
|
||||
k: getattr(self, k)
|
||||
|
|
5
requirements-flatpak.txt
Normal file
5
requirements-flatpak.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
requests
|
||||
QtAwesome
|
||||
setuptools
|
||||
legendary-gl>=0.20.34
|
||||
pypresence
|
|
@ -1,4 +1,3 @@
|
|||
typing_extensions
|
||||
requests
|
||||
PyQt5
|
||||
QtAwesome
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
typing_extensions
|
||||
requests
|
||||
PyQt5
|
||||
QtAwesome
|
||||
|
|
Loading…
Reference in a new issue