umu-commander 1.5.3__py3-none-any.whl → 1.5.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of umu-commander might be problematic. Click here for more details.

@@ -1,6 +1,8 @@
1
+ import importlib
1
2
  import os
2
3
  import tomllib
3
4
  from pathlib import Path
5
+ from typing import Any
4
6
 
5
7
  import tomli_w
6
8
 
@@ -10,63 +12,66 @@ CONFIG_DIR: str = os.path.join(Path.home(), ".config")
10
12
  CONFIG_NAME: str = "umu-commander.toml"
11
13
 
12
14
 
13
- class Configuration:
14
- PROTON_PATHS: tuple[str, ...] = (
15
- os.path.join(Path.home(), ".local/share/Steam/compatibilitytools.d/"),
16
- os.path.join(Path.home(), ".local/share/umu/compatibilitytools"),
17
- )
18
- UMU_PROTON_PATH: str = os.path.join(
19
- Path.home(), ".local/share/Steam/compatibilitytools.d/"
20
- )
21
- DB_NAME: str = "tracking.json"
22
- DB_DIR: str = os.path.join(Path.home(), ".local/share/umu/compatibilitytools")
23
- UMU_CONFIG_NAME: str = "umu-config.toml"
24
- DEFAULT_PREFIX_DIR: str = os.path.join(Path.home(), ".local/share/wineprefixes/")
25
- DLL_OVERRIDES_OPTIONS: tuple[DLLOverride, ...] = (
26
- DLLOverride("winhttp for BepInEx", "winhttp.dll=n;"),
27
- )
28
-
29
- @staticmethod
30
- def load():
31
- try:
32
- with open(os.path.join(CONFIG_DIR, CONFIG_NAME), "rb") as conf_file:
33
- toml_conf = tomllib.load(conf_file)
34
- toml_conf["DLL_OVERRIDES_OPTIONS"] = tuple(
35
- [
36
- DLLOverride(label, override_str)
37
- for label, override_str in toml_conf[
38
- "DLL_OVERRIDES_OPTIONS"
39
- ].items()
40
- ]
41
- )
42
-
43
- for key, value in toml_conf.items():
44
- setattr(Configuration, key, value)
45
-
46
- except FileNotFoundError:
47
- Configuration.dump()
48
-
49
- @staticmethod
50
- def dump():
51
- if not os.path.exists(CONFIG_DIR):
52
- os.mkdir(CONFIG_DIR)
53
-
54
- with open(os.path.join(CONFIG_DIR, CONFIG_NAME), "wb") as conf_file:
55
- toml_conf = Configuration._get_attributes()
56
- toml_conf["DLL_OVERRIDES_OPTIONS"] = dict(
15
+ PROTON_PATHS: tuple[str, ...] = (
16
+ os.path.join(Path.home(), ".local/share/Steam/compatibilitytools.d/"),
17
+ os.path.join(Path.home(), ".local/share/umu/compatibilitytools"),
18
+ )
19
+ UMU_PROTON_PATH: str = os.path.join(
20
+ Path.home(), ".local/share/Steam/compatibilitytools.d/"
21
+ )
22
+ DB_NAME: str = "tracking.json"
23
+ DB_DIR: str = os.path.join(Path.home(), ".local/share/umu/compatibilitytools")
24
+ UMU_CONFIG_NAME: str = "umu-config.toml"
25
+ DEFAULT_PREFIX_DIR: str = os.path.join(Path.home(), ".local/share/wineprefixes/")
26
+ DLL_OVERRIDES_OPTIONS: tuple[DLLOverride, ...] = (
27
+ DLLOverride("winhttp for BepInEx", "winhttp.dll=n;"),
28
+ )
29
+
30
+
31
+ def load():
32
+ config_path: str = os.path.join(CONFIG_DIR, CONFIG_NAME)
33
+ if not os.path.exists(config_path):
34
+ return
35
+
36
+ with open(config_path, "rb") as conf_file:
37
+ toml_conf = tomllib.load(conf_file)
38
+ if "DLL_OVERRIDES_OPTIONS" in toml_conf:
39
+ toml_conf["DLL_OVERRIDES_OPTIONS"] = tuple(
57
40
  [
58
- (override.info, override.value)
59
- for override in Configuration.DLL_OVERRIDES_OPTIONS
41
+ DLLOverride(label, override_str)
42
+ for label, override_str in toml_conf[
43
+ "DLL_OVERRIDES_OPTIONS"
44
+ ].items()
60
45
  ]
61
46
  )
62
47
 
63
- tomli_w.dump(toml_conf, conf_file)
48
+ module = importlib.import_module(__name__)
49
+ for key, value in toml_conf.items():
50
+ setattr(module, key, value)
51
+
52
+
53
+ def _get_attributes() -> dict[str, Any]:
54
+ module = importlib.import_module(__name__)
55
+ attributes: dict[str, Any] = {}
56
+ for key in dir(module):
57
+ value = getattr(module, key)
58
+ if not key.startswith("_") and not callable(value) and key.upper() == key:
59
+ attributes[key] = value
60
+
61
+ return attributes
62
+
63
+
64
+ def dump():
65
+ if not os.path.exists(CONFIG_DIR):
66
+ os.mkdir(CONFIG_DIR)
67
+
68
+ with open(os.path.join(CONFIG_DIR, CONFIG_NAME), "wb") as conf_file:
69
+ toml_conf = _get_attributes()
70
+ del toml_conf["CONFIG_DIR"]
71
+ del toml_conf["CONFIG_NAME"]
64
72
 
65
- @staticmethod
66
- def _get_attributes():
67
- attributes = {}
68
- for key, value in vars(Configuration).items():
69
- if not key.startswith("__") and not callable(getattr(Configuration, key)):
70
- attributes[key] = value
73
+ toml_conf["DLL_OVERRIDES_OPTIONS"] = dict(
74
+ [(override.info, override.value) for override in DLL_OVERRIDES_OPTIONS]
75
+ )
71
76
 
72
- return attributes
77
+ tomli_w.dump(toml_conf, conf_file)
umu_commander/database.py CHANGED
@@ -2,42 +2,53 @@ import json
2
2
  import os
3
3
  from collections import defaultdict
4
4
 
5
- from umu_commander.configuration import Configuration as config
5
+ import umu_commander.configuration as config
6
6
 
7
+ _db: defaultdict[str, defaultdict[str, list[str]]] = defaultdict(
8
+ lambda: defaultdict(list)
9
+ )
7
10
 
8
- class Database:
9
- _db: defaultdict[str, defaultdict[str, list[str]]]
10
11
 
11
- @staticmethod
12
- def load():
13
- if not os.path.exists(config.DB_DIR):
14
- os.mkdir(config.DB_DIR)
12
+ def load():
13
+ global _db
15
14
 
16
- try:
17
- with open(os.path.join(config.DB_DIR, config.DB_NAME), "rt") as db_file:
18
- Database._db = defaultdict(lambda: defaultdict(list))
19
- Database._db.update(json.load(db_file))
15
+ if not os.path.exists(config.DB_DIR):
16
+ os.mkdir(config.DB_DIR)
20
17
 
21
- except FileNotFoundError:
22
- Database._db = defaultdict(lambda: defaultdict(list))
18
+ db_path: str = os.path.join(config.DB_DIR, config.DB_NAME)
19
+ if not os.path.exists(db_path):
20
+ return
23
21
 
24
- @staticmethod
25
- def dump():
26
- with open(os.path.join(config.DB_DIR, config.DB_NAME), "wt") as db_file:
27
- # noinspection PyTypeChecker
28
- json.dump(Database._db, db_file, indent="\t")
22
+ with open(os.path.join(db_path), "rt") as db_file:
23
+ _db.update(json.load(db_file))
29
24
 
30
- @staticmethod
31
- def get(
32
- proton_dir: str = None, proton_ver: str = None
33
- ) -> dict[str, dict[str, list[str]]] | dict[str, list[str]] | list[str]:
34
- if proton_dir is None and proton_ver is None:
35
- return Database._db
36
25
 
37
- if proton_ver is None:
38
- return Database._db[proton_dir]
26
+ def dump():
27
+ if not os.path.exists(config.DB_DIR):
28
+ os.mkdir(config.DB_DIR)
39
29
 
40
- if proton_ver not in Database._db[proton_dir]:
41
- Database._db[proton_dir][proton_ver] = []
30
+ with open(os.path.join(config.DB_DIR, config.DB_NAME), "wt") as db_file:
31
+ # noinspection PyTypeChecker
32
+ json.dump(_db, db_file, indent="\t")
42
33
 
43
- return Database._db[proton_dir][proton_ver]
34
+
35
+ def get(
36
+ proton_dir: str = None, proton_ver: str = None
37
+ ) -> dict[str, dict[str, list[str]]] | dict[str, list[str]] | list[str]:
38
+ global _db
39
+
40
+ if proton_dir is None and proton_ver is None:
41
+ return _db
42
+
43
+ if proton_ver is None:
44
+ return _db[proton_dir]
45
+
46
+ if proton_ver not in _db[proton_dir]:
47
+ _db[proton_dir][proton_ver] = []
48
+
49
+ return _db[proton_dir][proton_ver]
50
+
51
+
52
+ def _reset():
53
+ global _db
54
+ _db = defaultdict(lambda: defaultdict(list))
umu_commander/main.py CHANGED
@@ -3,11 +3,11 @@ import os
3
3
  import sys
4
4
  from json import JSONDecodeError
5
5
 
6
+ import umu_commander.configuration as config
7
+ import umu_commander.database as db
6
8
  from umu_commander import tracking, umu_config
7
9
  from umu_commander.classes import ExitCode
8
10
  from umu_commander.configuration import CONFIG_DIR, CONFIG_NAME
9
- from umu_commander.configuration import Configuration as config
10
- from umu_commander.database import Database as db
11
11
 
12
12
 
13
13
  def print_help():
@@ -36,7 +36,7 @@ def main() -> ExitCode:
36
36
 
37
37
  if len(sys.argv) == 1:
38
38
  print_help()
39
- return ExitCode.SUCCESS
39
+ return ExitCode.SUCCESS.value
40
40
 
41
41
  verb: str = sys.argv[1]
42
42
  match verb:
@@ -55,14 +55,14 @@ def main() -> ExitCode:
55
55
  case _:
56
56
  print("Invalid verb.")
57
57
  print_help()
58
- return ExitCode.INVALID_SELECTION
58
+ return ExitCode.INVALID_SELECTION.value
59
59
 
60
60
  tracking.untrack_unlinked()
61
61
  db.dump()
62
62
  config.dump()
63
63
 
64
- return ExitCode.SUCCESS
64
+ return ExitCode.SUCCESS.value
65
65
 
66
66
 
67
67
  if __name__ == "__main__":
68
- exit(main().value)
68
+ exit(main())
umu_commander/proton.py CHANGED
@@ -2,9 +2,9 @@ import os
2
2
  import re
3
3
  import subprocess
4
4
 
5
+ import umu_commander.configuration as config
6
+ import umu_commander.database as db
5
7
  from umu_commander.classes import ProtonDir, ProtonVer
6
- from umu_commander.configuration import Configuration as config
7
- from umu_commander.database import Database as db
8
8
 
9
9
 
10
10
  def _natural_sort_proton_ver_key(p: ProtonVer, _nsre=re.compile(r"(\d+)")):
@@ -25,9 +25,9 @@ def refresh_proton_versions():
25
25
  if "PROTONPATH" in line and "/" in line:
26
26
  try:
27
27
  left: int = line.rfind("/") + 1
28
- print(f"Using {line[left:len(line) - 1]}.")
28
+ print(f":Latest umu Proton: {line[left:len(line) - 1]}.")
29
29
  except ValueError:
30
- print("Could not fetch latest UMU-Proton.")
30
+ print("Could not fetch latest umu Proton.")
31
31
 
32
32
  break
33
33
 
umu_commander/tracking.py CHANGED
@@ -1,8 +1,8 @@
1
1
  import os
2
2
  import shutil
3
3
 
4
+ import umu_commander.database as db
4
5
  from umu_commander.classes import ProtonDir, ProtonVer
5
- from umu_commander.database import Database as db
6
6
  from umu_commander.proton import (
7
7
  collect_proton_versions,
8
8
  get_latest_umu_proton,
@@ -21,7 +21,7 @@ def untrack(quiet: bool = False):
21
21
  db.get(proton_dir, proton_ver).remove(current_dir)
22
22
 
23
23
  if not quiet:
24
- print("Directory removed from all user lists.")
24
+ print("Directory removed from all tracking lists.")
25
25
 
26
26
 
27
27
  def track(
@@ -32,7 +32,7 @@ def track(
32
32
 
33
33
  if proton_ver is None:
34
34
  proton_ver: ProtonVer = get_selection(
35
- "Select Proton version to add directory as user:",
35
+ "Select Proton version to track directory with:",
36
36
  None,
37
37
  collect_proton_versions(sort=True),
38
38
  ).as_proton_ver()
@@ -43,7 +43,7 @@ def track(
43
43
 
44
44
  if not quiet:
45
45
  print(
46
- f"Directory {current_directory} added to Proton version's {proton_ver.version_num} in {proton_ver.dir} user list."
46
+ f"Directory {current_directory} added to Proton version's {proton_ver.version_num} in {proton_ver.dir} tracking list."
47
47
  )
48
48
 
49
49
 
@@ -57,10 +57,10 @@ def users():
57
57
  if proton_ver.dir in db.get() and proton_ver.version_num in db.get(proton_ver.dir):
58
58
  version_users: list[str] = db.get(proton_ver.dir, proton_ver.version_num)
59
59
  if len(version_users) > 0:
60
- print(f"Directories using {proton_ver.version_num} of {proton_ver.dir}:")
60
+ print(f"Directories tracked by {proton_ver.version_num} of {proton_ver.dir}:")
61
61
  print(*version_users, sep="\n")
62
62
  else:
63
- print("No directories currently use this version.")
63
+ print("This version is tracking no directories.")
64
64
  else:
65
65
  print("This version hasn't been used by umu before.")
66
66
 
@@ -73,7 +73,7 @@ def delete():
73
73
 
74
74
  if len(version_users) == 0:
75
75
  selection: str = input(
76
- f"{proton_ver} in {proton_dir} has no using directories, delete? (Y/N) ? "
76
+ f"Version {proton_ver} in {proton_dir} is tracking no directories, delete? (Y/N) ? "
77
77
  )
78
78
  if selection.lower() == "y":
79
79
  try:
@@ -5,9 +5,9 @@ from typing import Any
5
5
 
6
6
  import tomli_w
7
7
 
8
+ import umu_commander.configuration as config
8
9
  from umu_commander import tracking
9
10
  from umu_commander.classes import DLLOverride, ProtonVer
10
- from umu_commander.configuration import Configuration as config
11
11
  from umu_commander.proton import collect_proton_versions, refresh_proton_versions
12
12
  from umu_commander.util import (
13
13
  get_selection,
@@ -54,7 +54,7 @@ def create():
54
54
  ]
55
55
  selected: set[int] = set()
56
56
  while True:
57
- print("Select DLLs to override, you can select multiple:")
57
+ print("Select DLLs to override, multiple can be selected:")
58
58
  for idx, override in enumerate(possible_overrides):
59
59
  if idx in selected:
60
60
  idx = "Y"
@@ -122,10 +122,14 @@ def create():
122
122
  if not selected_umu_latest:
123
123
  tracking.track(proton_ver, False)
124
124
  except:
125
- print("Could not create configiguration file.")
125
+ print("Could not create configuration file.")
126
126
 
127
127
 
128
128
  def run():
129
+ if not os.path.exists(config.UMU_CONFIG_NAME):
130
+ print("No umu config in current directory.")
131
+ return
132
+
129
133
  with open(config.UMU_CONFIG_NAME, "rb") as toml_file:
130
134
  toml_conf = tomllib.load(toml_file)
131
135
 
@@ -137,3 +141,4 @@ def run():
137
141
  args=["umu-run", "--config", config.UMU_CONFIG_NAME],
138
142
  env=os.environ,
139
143
  )
144
+
umu_commander/util.py CHANGED
@@ -58,7 +58,7 @@ def get_selection(
58
58
  ) -> Element:
59
59
  if not _selection_set_valid(selection_elements, selection_groups):
60
60
  print("Nothing to select from.")
61
- exit(ExitCode.INVALID_SELECTION)
61
+ exit(ExitCode.INVALID_SELECTION.value)
62
62
 
63
63
  if selection_groups is None:
64
64
  selection_groups = []
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: umu-commander
3
- Version: 1.5.3
3
+ Version: 1.5.5
4
4
  Summary: umu-commander is an interactive CLI tool to help you manage umu.
5
5
  Project-URL: Homepage, https://github.com/Mpaxlamitsounas/umu-commander
6
6
  Project-URL: Issues, https://github.com/Mpaxlamitsounas/umu-commander/issues
7
7
  Author-email: Mpaxlamitsounas <worldstudy123@gmail.com>
8
8
  License-Expression: MIT
9
9
  License-File: LICENSE.txt
10
- Keywords: umu
10
+ Keywords: umu,umu-launcher
11
11
  Classifier: Operating System :: POSIX :: Linux
12
12
  Classifier: Programming Language :: Python :: 3
13
13
  Requires-Python: >=3.12
@@ -49,4 +49,11 @@ umu-commander needs one of the following verbs specified after the executable na
49
49
  * This is NOT equivalent to `umu-run --config <config_name>`, as vanilla umu configs do not support setting environment variables as of 07/2025.
50
50
 
51
51
  ### Installation/Usage
52
- Add umu-run to your PATH and then install with pipx by running `pipx install umu-commander`. After that you can invoke umu-commander by running `umu-commander <verb>`.
52
+ Add umu-run to your PATH and then install with pipx by running `pipx install umu-commander`. After that you can invoke umu-commander by running `umu-commander <verb>`.
53
+
54
+ ### Return codes
55
+ | Number | Name | Description |
56
+ |:-------|:------------------|:----------------------------------------------------------------|
57
+ | 0 | SUCCESS | Program executed as intended. |
58
+ | 1 | READING_ERROR | Failed to parse a file and could not recover. |
59
+ | 2 | INVALID_SELECTION | User selected an invalid verb or there are no valid selections. |
@@ -0,0 +1,14 @@
1
+ umu_commander/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ umu_commander/classes.py,sha256=SW8k4TrP4-W4DdaQC_P88wBIgeJ3TIaV7lyt32IfVD8,1654
3
+ umu_commander/configuration.py,sha256=VmOmlXQS08OFlptu04P0zLgCsiToJMgKBXx35aRpnfU,2368
4
+ umu_commander/database.py,sha256=_8FVW-gctDsR6K2LiHQy6Mr_yR0JTY-taIvqBb9Hr0E,1248
5
+ umu_commander/main.py,sha256=-EghV73K7XlV_JXnYgLAc6Qt1svp3vT8s8TUVo6nIXQ,1945
6
+ umu_commander/proton.py,sha256=ZJ3y8sjxTIKm5mUH32eXBGxGuJH_2gWXi_EoqJyOxko,2553
7
+ umu_commander/tracking.py,sha256=V38nWlOZu0BUyPWssX6i0JoXOkd8NkKAdJ0hPauXlMM,3064
8
+ umu_commander/umu_config.py,sha256=ilxWhiT2XhPn9qeJf-i2YWZIhVktPuMkNxpEfdnMF_A,4192
9
+ umu_commander/util.py,sha256=e4IqnxT0K2lLsUUgqnK0Z60MJRasvGCzo90ZX-gVBOE,2648
10
+ umu_commander-1.5.5.dist-info/METADATA,sha256=H7XhadfLpQZeVa8hUfP66Gm0oeTMsHdRM6oI_B4M_6o,3720
11
+ umu_commander-1.5.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
12
+ umu_commander-1.5.5.dist-info/entry_points.txt,sha256=7RGP35zAHeEojZ-sv7JIITuMeH_VVNuG2g2_SUrUnbM,58
13
+ umu_commander-1.5.5.dist-info/licenses/LICENSE.txt,sha256=yipFXBRmVZ2Q44x1q18HccPUAECBQLXAOAr21aS57uY,1071
14
+ umu_commander-1.5.5.dist-info/RECORD,,
@@ -1,14 +0,0 @@
1
- umu_commander/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- umu_commander/classes.py,sha256=SW8k4TrP4-W4DdaQC_P88wBIgeJ3TIaV7lyt32IfVD8,1654
3
- umu_commander/configuration.py,sha256=tzVFoQx7M1RGGtP_c_k3IUVFNcLwsmjbQplTeKlFUnM,2398
4
- umu_commander/database.py,sha256=rkjEEy-Em9ghZOypsWyKTlNjDNMU4XXWuthnpfa6yz4,1343
5
- umu_commander/main.py,sha256=LWLLzMO2xm-45USc0Uw1-oTdPW14tOd0-WAbnLvFTQg,1966
6
- umu_commander/proton.py,sha256=QWqU5N2v-QqP_d-kFGXxXiCufLFQywnMNrbuLXaINZk,2572
7
- umu_commander/tracking.py,sha256=MVj-GfbROyqhKa-m6557RGCzavTxgphNBVPJNtSTe3k,3058
8
- umu_commander/umu_config.py,sha256=3b5XeTZppmLpxUGBHi4JSBc7zmKxNKjboldwGfLE0rc,4091
9
- umu_commander/util.py,sha256=mBRdLs-dnrTE_23qSb9wZ7tw4WmcNU3AS9oJFrVLgH4,2642
10
- umu_commander-1.5.3.dist-info/METADATA,sha256=jJ7sIBXBNnm8C00jkxmvGCEm5i314rBFDxA8HS_8kCY,3203
11
- umu_commander-1.5.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
12
- umu_commander-1.5.3.dist-info/entry_points.txt,sha256=7RGP35zAHeEojZ-sv7JIITuMeH_VVNuG2g2_SUrUnbM,58
13
- umu_commander-1.5.3.dist-info/licenses/LICENSE.txt,sha256=yipFXBRmVZ2Q44x1q18HccPUAECBQLXAOAr21aS57uY,1071
14
- umu_commander-1.5.3.dist-info/RECORD,,