steam-client 3.0.0.dev0__tar.gz → 4.0.0__tar.gz

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.
Files changed (33) hide show
  1. steam_client-4.0.0/PKG-INFO +147 -0
  2. steam_client-4.0.0/README.md +130 -0
  3. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/pyproject.toml +2 -2
  4. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/steam_client/app.py +1 -7
  5. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/steam_client/commands.py +12 -18
  6. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/steam_client/game.py +14 -13
  7. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/steam_client/library.py +22 -20
  8. steam_client-4.0.0/steam_client/library_folder.py +17 -0
  9. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/steam_client/login_users.py +11 -12
  10. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/steam_client/shortcut.py +3 -4
  11. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/steam_client/steam.py +1 -1
  12. steam_client-4.0.0/steam_client.egg-info/PKG-INFO +147 -0
  13. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/steam_client.egg-info/SOURCES.txt +3 -1
  14. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/tests/test_commands.py +5 -5
  15. steam_client-4.0.0/tests/test_game.py +103 -0
  16. steam_client-4.0.0/tests/test_library.py +220 -0
  17. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/tests/test_login_users.py +5 -5
  18. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/tests/test_shortcut.py +2 -2
  19. steam_client-3.0.0.dev0/PKG-INFO +0 -16
  20. steam_client-3.0.0.dev0/steam_client/library_directory.py +0 -18
  21. steam_client-3.0.0.dev0/steam_client.egg-info/PKG-INFO +0 -16
  22. steam_client-3.0.0.dev0/tests/test_game.py +0 -61
  23. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/LICENSE +0 -0
  24. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/setup.cfg +0 -0
  25. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/setup.py +0 -0
  26. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/steam_client/__init__.py +0 -0
  27. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/steam_client/py.typed +0 -0
  28. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/steam_client/utils.py +0 -0
  29. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/steam_client/web_api.py +0 -0
  30. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/steam_client.egg-info/dependency_links.txt +0 -0
  31. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/steam_client.egg-info/requires.txt +0 -0
  32. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/steam_client.egg-info/top_level.txt +0 -0
  33. {steam_client-3.0.0.dev0 → steam_client-4.0.0}/tests/test_steam.py +0 -0
@@ -0,0 +1,147 @@
1
+ Metadata-Version: 2.4
2
+ Name: steam-client
3
+ Version: 4.0.0
4
+ Summary: Steam client library for Python
5
+ Author-email: William McAllister <dev.garulf@gmail.com>
6
+ License: MIT
7
+ Project-URL: Source, https://github.com/garulf/steam-client
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3 :: Only
11
+ Requires-Python: >=3.8
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: vdf>=3.4
15
+ Requires-Dist: pycrc>=0.10.0
16
+ Dynamic: license-file
17
+
18
+ # Steam Client
19
+
20
+ A Python library for interacting with a locally installed Steam client — enumerate your game library/non-steam games, read game metadata and artwork paths, send Steam URI commands, and query the Steam Web API.
21
+
22
+ [![Buy Me a Coffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-garulf-FFDD00?style=flat&logo=buy-me-a-coffee&logoColor=black)](https://www.buymeacoffee.com/garulf)
23
+ [![Ko-fi](https://img.shields.io/badge/Ko--fi-garulf-FF5E5B?style=flat&logo=ko-fi&logoColor=white)](https://ko-fi.com/garulf)
24
+
25
+ ---
26
+
27
+ ## Installation
28
+
29
+ Requires Python 3.8+.
30
+
31
+ ```bash
32
+ pip install steam-client
33
+ ```
34
+
35
+ Or install from source:
36
+
37
+ ```bash
38
+ pip install -e .
39
+ ```
40
+
41
+ ---
42
+
43
+ ## Quickstart
44
+
45
+ ```python
46
+ from steam_client.steam import Steam
47
+
48
+ steam = Steam() # Uses default path: C:\Program Files (x86)\Steam
49
+
50
+ # On Windows, auto-detect path from registry:
51
+ from steam_client.utils import steam_from_registry
52
+ steam = steam_from_registry()
53
+ ```
54
+
55
+ ---
56
+
57
+ ## Common Operations
58
+
59
+ ### List all installed games
60
+
61
+ ```python
62
+ for game in steam.library.games():
63
+ print(game.appid, game.name)
64
+ ```
65
+
66
+ ### Find a game
67
+
68
+ ```python
69
+ game = steam.library.game_by_id("440") # by app ID
70
+ game = steam.library.game_by_name("Portal 2") # by name (case-insensitive)
71
+ ```
72
+
73
+ ### Artwork paths
74
+
75
+ ```python
76
+ game.header # Path to header image (460×215 jpg)
77
+ game.grid # Path to grid image (600×900 jpg)
78
+ game.hero # Path to hero image
79
+ game.icon # Path to icon file, or None
80
+ ```
81
+
82
+ ### Launch and manage games via Steam URI commands
83
+
84
+ ```python
85
+ from steam_client.commands import Commands, SteamWindows
86
+
87
+ commands = Commands()
88
+ commands.run_game_id("440") # Launch a game
89
+ commands.store("440") # Open store page
90
+ commands.install("440") # Prompt install
91
+ commands.uninstall("440") # Prompt uninstall
92
+ commands.open(SteamWindows.FRIENDS) # Open a Steam window
93
+ commands.open_url("https://store.steampowered.com")
94
+ ```
95
+
96
+ Or launch a game directly from a `SteamGame` object:
97
+
98
+ ```python
99
+ game.run()
100
+ ```
101
+
102
+ ### Users and shortcuts
103
+
104
+ ```python
105
+ for user in steam.users:
106
+ print(user.user.data.PersonaName)
107
+
108
+ for shortcut in steam.library.shortcuts():
109
+ print(shortcut.appname)
110
+ ```
111
+
112
+ ### Steam Web API
113
+
114
+ ```python
115
+ from steam_client.web_api import WebAPI
116
+
117
+ api = WebAPI()
118
+ apps = api.get_app_list()
119
+ ```
120
+
121
+ ---
122
+
123
+ ## Platform Notes
124
+
125
+ | Platform | Default path | Registry helper |
126
+ |----------|--------------------------------|-------------------------|
127
+ | Windows | `C:\Program Files (x86)\Steam` | `steam_from_registry()` |
128
+ | Linux | `~/.local/share/steam` | Not available |
129
+
130
+ Pass a custom path to override the default:
131
+
132
+ ```python
133
+ steam = Steam("/custom/steam/path")
134
+ ```
135
+
136
+ Requires read access to local Steam config files (`libraryfolders.vdf`, `shortcuts.vdf`, appmanifest files).
137
+
138
+ ---
139
+
140
+ ## Development
141
+
142
+ ```bash
143
+ pytest # Run tests
144
+ flake8 steam_client # Lint
145
+ mypy steam_client # Type check
146
+ tox # Run all environments (lint, type, py311–314)
147
+ ```
@@ -0,0 +1,130 @@
1
+ # Steam Client
2
+
3
+ A Python library for interacting with a locally installed Steam client — enumerate your game library/non-steam games, read game metadata and artwork paths, send Steam URI commands, and query the Steam Web API.
4
+
5
+ [![Buy Me a Coffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-garulf-FFDD00?style=flat&logo=buy-me-a-coffee&logoColor=black)](https://www.buymeacoffee.com/garulf)
6
+ [![Ko-fi](https://img.shields.io/badge/Ko--fi-garulf-FF5E5B?style=flat&logo=ko-fi&logoColor=white)](https://ko-fi.com/garulf)
7
+
8
+ ---
9
+
10
+ ## Installation
11
+
12
+ Requires Python 3.8+.
13
+
14
+ ```bash
15
+ pip install steam-client
16
+ ```
17
+
18
+ Or install from source:
19
+
20
+ ```bash
21
+ pip install -e .
22
+ ```
23
+
24
+ ---
25
+
26
+ ## Quickstart
27
+
28
+ ```python
29
+ from steam_client.steam import Steam
30
+
31
+ steam = Steam() # Uses default path: C:\Program Files (x86)\Steam
32
+
33
+ # On Windows, auto-detect path from registry:
34
+ from steam_client.utils import steam_from_registry
35
+ steam = steam_from_registry()
36
+ ```
37
+
38
+ ---
39
+
40
+ ## Common Operations
41
+
42
+ ### List all installed games
43
+
44
+ ```python
45
+ for game in steam.library.games():
46
+ print(game.appid, game.name)
47
+ ```
48
+
49
+ ### Find a game
50
+
51
+ ```python
52
+ game = steam.library.game_by_id("440") # by app ID
53
+ game = steam.library.game_by_name("Portal 2") # by name (case-insensitive)
54
+ ```
55
+
56
+ ### Artwork paths
57
+
58
+ ```python
59
+ game.header # Path to header image (460×215 jpg)
60
+ game.grid # Path to grid image (600×900 jpg)
61
+ game.hero # Path to hero image
62
+ game.icon # Path to icon file, or None
63
+ ```
64
+
65
+ ### Launch and manage games via Steam URI commands
66
+
67
+ ```python
68
+ from steam_client.commands import Commands, SteamWindows
69
+
70
+ commands = Commands()
71
+ commands.run_game_id("440") # Launch a game
72
+ commands.store("440") # Open store page
73
+ commands.install("440") # Prompt install
74
+ commands.uninstall("440") # Prompt uninstall
75
+ commands.open(SteamWindows.FRIENDS) # Open a Steam window
76
+ commands.open_url("https://store.steampowered.com")
77
+ ```
78
+
79
+ Or launch a game directly from a `SteamGame` object:
80
+
81
+ ```python
82
+ game.run()
83
+ ```
84
+
85
+ ### Users and shortcuts
86
+
87
+ ```python
88
+ for user in steam.users:
89
+ print(user.user.data.PersonaName)
90
+
91
+ for shortcut in steam.library.shortcuts():
92
+ print(shortcut.appname)
93
+ ```
94
+
95
+ ### Steam Web API
96
+
97
+ ```python
98
+ from steam_client.web_api import WebAPI
99
+
100
+ api = WebAPI()
101
+ apps = api.get_app_list()
102
+ ```
103
+
104
+ ---
105
+
106
+ ## Platform Notes
107
+
108
+ | Platform | Default path | Registry helper |
109
+ |----------|--------------------------------|-------------------------|
110
+ | Windows | `C:\Program Files (x86)\Steam` | `steam_from_registry()` |
111
+ | Linux | `~/.local/share/steam` | Not available |
112
+
113
+ Pass a custom path to override the default:
114
+
115
+ ```python
116
+ steam = Steam("/custom/steam/path")
117
+ ```
118
+
119
+ Requires read access to local Steam config files (`libraryfolders.vdf`, `shortcuts.vdf`, appmanifest files).
120
+
121
+ ---
122
+
123
+ ## Development
124
+
125
+ ```bash
126
+ pytest # Run tests
127
+ flake8 steam_client # Lint
128
+ mypy steam_client # Type check
129
+ tox # Run all environments (lint, type, py311–314)
130
+ ```
@@ -6,7 +6,7 @@ name = "steam-client"
6
6
  authors = [
7
7
  {name = "William McAllister", email = "dev.garulf@gmail.com"}
8
8
  ]
9
- version = "3.0.0-dev.0"
9
+ version = "4.0.0"
10
10
  description = "Steam client library for Python"
11
11
  readme = "README.md"
12
12
  requires-python = ">=3.8"
@@ -31,7 +31,7 @@ packages = ["steam_client"]
31
31
  "steam_client" = ["py.typed"]
32
32
 
33
33
  [tool.bumpversion]
34
- current_version = "3.0.0-dev.0"
34
+ current_version = "4.0.0"
35
35
  search = "version = \"{current_version}\""
36
36
  replace = "version = \"{new_version}\""
37
37
  parse = """(?x)
@@ -1,20 +1,14 @@
1
1
  from __future__ import annotations
2
2
  from abc import ABC, abstractmethod
3
3
  from pathlib import Path
4
- from typing import TYPE_CHECKING
5
-
6
4
 
7
5
  from .commands import Commands
8
6
 
9
- if TYPE_CHECKING:
10
- from .steam import Steam
11
-
12
7
 
13
8
  class App(ABC):
14
9
  """Abstract base class for all Steam apps."""
15
10
 
16
- def __init__(self, steam: Steam):
17
- self._steam = steam
11
+ def __init__(self):
18
12
  self._commands = Commands()
19
13
 
20
14
  @property
@@ -1,9 +1,6 @@
1
- from typing import List
2
1
  import webbrowser
3
2
  from enum import StrEnum
4
3
 
5
- SCHEME = 'steam'
6
-
7
4
 
8
5
  class SteamWindows(StrEnum):
9
6
  """Enumeration of Steam client windows."""
@@ -23,47 +20,44 @@ class SteamWindows(StrEnum):
23
20
 
24
21
  class Command():
25
22
 
26
- def __init__(self, scheme: str):
27
- self._scheme = scheme
28
-
29
- def _create_uri(self, path: List[str], endpoint: str) -> str:
30
- return f'{self._scheme}://{"/".join(path)}/{endpoint}'
23
+ def _create_uri(self, *segments: str) -> str:
24
+ return f'steam://{"/".join(segments)}'
31
25
 
32
- def __call__(self, path: List[str], endpoint: str) -> None:
26
+ def open(self, *segments: str) -> None:
33
27
  """Executes the command with the specified endpoint."""
34
- webbrowser.open(self._create_uri(path, endpoint))
28
+ webbrowser.open(self._create_uri(*segments))
35
29
 
36
30
 
37
31
  class Commands:
38
32
  """A collection of commands for the Steam client."""
39
33
 
40
34
  def __init__(self):
41
- self._command = Command(SCHEME)
35
+ self._command = Command()
42
36
 
43
37
  def run_game_id(self, app_id: str) -> None:
44
38
  """Launches game with the specified ID in the Steam client."""
45
- self._command(['rungameid'], app_id)
39
+ self._command.open('rungameid', app_id)
46
40
 
47
41
  def store(self, app_id: str) -> None:
48
42
  """Opens the game's store page in the Steam client."""
49
- self._command(['store'], app_id)
43
+ self._command.open('store', app_id)
50
44
 
51
45
  def install(self, app_id: str) -> None:
52
46
  """Opens the game's install prompt in the Steam client."""
53
- self._command(['install'], app_id)
47
+ self._command.open('install', app_id)
54
48
 
55
49
  def uninstall(self, app_id: str) -> None:
56
50
  """Opens the game's uninstall prompt in the Steam client."""
57
- self._command(['uninstall'], app_id)
51
+ self._command.open('uninstall', app_id)
58
52
 
59
53
  def update_news(self, app_id: str) -> None:
60
54
  """Opens the game's update news in the Steam client."""
61
- self._command(['updatenews'], app_id)
55
+ self._command.open('updatenews', app_id)
62
56
 
63
57
  def open(self, window: SteamWindows) -> None:
64
58
  """Opens the specified window in the Steam client."""
65
- self._command(['open'], window)
59
+ self._command.open('open', window)
66
60
 
67
61
  def open_url(self, url: str) -> None:
68
62
  """Opens the specified URL in the Steam client."""
69
- self._command(['openurl'], url)
63
+ self._command.open('openurl', url)
@@ -1,13 +1,9 @@
1
1
  from __future__ import annotations
2
2
  import functools
3
3
  from pathlib import Path
4
- from typing import TYPE_CHECKING
5
4
 
6
5
  import vdf # type: ignore
7
6
 
8
- if TYPE_CHECKING:
9
- from .steam import Steam
10
-
11
7
  from .app import App
12
8
 
13
9
 
@@ -22,19 +18,20 @@ ASSETS = frozenset({
22
18
  })
23
19
 
24
20
 
25
- class SteamGame(App):
21
+ class Game(App):
26
22
  """Represents a Steam game."""
27
23
 
28
- def __init__(self, steam: Steam, library_path: str, appid: str):
24
+ def __init__(self, library_cache_path: Path, library_path: str, appid: str):
25
+ self._library_cache_path = Path(library_cache_path)
29
26
  self.library_path = library_path
30
27
  self._appid = appid
31
28
  self._icon: Path | None = None
32
29
  self._name: str | None = None
33
- super().__init__(steam)
30
+ super().__init__()
34
31
 
35
32
  def __repr__(self) -> str:
36
33
  return (
37
- f'Game(steam={self._steam.__repr__()}, '
34
+ f'Game(library_cache_path={self._library_cache_path.__repr__()}, '
38
35
  f'library_path={self.library_path.__repr__()}, '
39
36
  f'appid={self.appid.__repr__()})'
40
37
  )
@@ -42,7 +39,7 @@ class SteamGame(App):
42
39
  @property
43
40
  def asset_dir(self) -> Path:
44
41
  """Returns the path to the game's asset directory."""
45
- return Path(self._steam.library_cache).joinpath(self.appid)
42
+ return self._library_cache_path.joinpath(self.appid)
46
43
 
47
44
  @property
48
45
  def icon(self) -> Path | None:
@@ -61,22 +58,22 @@ class SteamGame(App):
61
58
  @property
62
59
  def header(self) -> Path:
63
60
  """Returns the path to the header image."""
64
- return Path(self._steam.library_cache).joinpath(f'{self.appid}_header.jpg')
61
+ return self._library_cache_path.joinpath(f'{self.appid}_header.jpg')
65
62
 
66
63
  @property
67
64
  def grid(self) -> Path:
68
65
  """Returns the path to the 600x900 grid image."""
69
- return Path(self._steam.library_cache).joinpath(f'{self.appid}_library_600x900.jpg')
66
+ return self._library_cache_path.joinpath(f'{self.appid}_library_600x900.jpg')
70
67
 
71
68
  @property
72
69
  def hero(self) -> Path:
73
70
  """Returns the path to the hero image."""
74
- return Path(self._steam.library_cache).joinpath(f'{self.appid}_library_hero.jpg')
71
+ return self._library_cache_path.joinpath(f'{self.appid}_library_hero.jpg')
75
72
 
76
73
  @property
77
74
  def hero_blur(self) -> Path:
78
75
  """Returns the path to the blurred hero image."""
79
- return Path(self._steam.library_cache).joinpath(f'{self.appid}_library_hero_blur.jpg')
76
+ return self._library_cache_path.joinpath(f'{self.appid}_library_hero_blur.jpg')
80
77
 
81
78
  @property
82
79
  def manifest_path(self) -> Path:
@@ -115,6 +112,10 @@ class SteamGame(App):
115
112
  """Opens the game's store page in the Steam client."""
116
113
  self._commands.store(self.appid)
117
114
 
115
+ def install(self):
116
+ """Installs the game."""
117
+ self._commands.install(self.appid)
118
+
118
119
  def uninstall(self):
119
120
  """Uninstalls the game."""
120
121
  self._commands.uninstall(self.appid)
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
  import hashlib
3
- from typing import TYPE_CHECKING, List, Optional, Union
3
+ from typing import TYPE_CHECKING, List, Optional, Union, Generator
4
4
 
5
5
  import vdf # type: ignore
6
6
 
@@ -8,8 +8,8 @@ from steam_client.shortcut import Shortcut
8
8
 
9
9
  if TYPE_CHECKING:
10
10
  from .steam import Steam
11
- from .library_directory import LibraryDirectory
12
- from .game import SteamGame
11
+ from .library_folder import LibraryFolder
12
+ from .game import Game
13
13
 
14
14
 
15
15
  class Library:
@@ -18,7 +18,7 @@ class Library:
18
18
  def __init__(self, steam: 'Steam'):
19
19
  self._steam = steam
20
20
  self._libraries_hash: Optional[str] = None
21
- self._libraries: List[LibraryDirectory] = []
21
+ self._libraries: List[LibraryFolder] = []
22
22
 
23
23
  def _hash_steam_libraries(self) -> str:
24
24
  """Returns the MD5 hash of the Steam library folders file."""
@@ -35,44 +35,46 @@ class Library:
35
35
  libraries = vdf.load(f)
36
36
  # The is not always formatted the same way, so we grab the first key
37
37
  folder_key = list(libraries.keys())[0]
38
- self._libraries = [LibraryDirectory(self._steam, libraries[folder_key][item]["path"],
39
- libraries[folder_key][item]["apps"]) for item in libraries[folder_key]]
38
+ self._libraries = [LibraryFolder(self._steam.library_cache, libraries[folder_key][item]["path"],
39
+ libraries[folder_key][item]["apps"]) for item in libraries[folder_key]]
40
40
 
41
- def libraries(self) -> List[LibraryDirectory]:
41
+ def libraries(self) -> Generator[LibraryFolder, None, None]:
42
42
  """Returns the Steam library folders."""
43
43
  if self._is_updated():
44
44
  self._libraries_hash = self._hash_steam_libraries()
45
45
  self._update_libraries()
46
- return self._libraries
46
+ for library in self._libraries:
47
+ yield library
47
48
 
48
- def games(self) -> List[SteamGame]:
49
+ def games(self) -> Generator[Game, None, None]:
49
50
  """Returns the games from the Steam library."""
50
- games = []
51
51
  for library in self.libraries():
52
- games.extend(library.get_games())
53
- return games
52
+ for game in library.get_games():
53
+ yield game
54
54
 
55
- def game_by_id(self, appid: str) -> Optional[SteamGame]:
55
+ def game_by_id(self, appid: str) -> Optional[Game]:
56
56
  """Returns the game with the specified ID."""
57
57
  for game in self.games():
58
58
  if game.appid == appid:
59
59
  return game
60
60
  return None
61
61
 
62
- def game_by_name(self, name: str) -> Optional[SteamGame]:
62
+ def game_by_name(self, name: str) -> Optional[Game]:
63
63
  """Returns the game with the specified name."""
64
64
  for game in self.games():
65
65
  if game.name.casefold() == name.casefold():
66
66
  return game
67
67
  return None
68
68
 
69
- def shortcuts(self) -> List[Shortcut]:
69
+ def shortcuts(self) -> Generator[Shortcut, None, None]:
70
70
  """Returns the Non-Steam shortcuts from the Steam library."""
71
- shortcuts = []
72
71
  for user in self._steam.users:
73
- shortcuts.extend(user.shortcuts())
74
- return shortcuts
72
+ for shortcut in user.shortcuts():
73
+ yield shortcut
75
74
 
76
- def all(self) -> List[Union[SteamGame, Shortcut]]:
75
+ def all(self) -> Generator[Union[Game, Shortcut], None, None]:
77
76
  """Returns all the games and shortcuts from the Steam library."""
78
- return self.games() + self.shortcuts()
77
+ for game in self.games():
78
+ yield game
79
+ for shortcut in self.shortcuts():
80
+ yield shortcut
@@ -0,0 +1,17 @@
1
+ from __future__ import annotations
2
+ from dataclasses import dataclass
3
+ from pathlib import Path
4
+ from typing import List
5
+
6
+ from .game import Game
7
+
8
+
9
+ @dataclass
10
+ class LibraryFolder:
11
+ """Represents a Steam library folder."""
12
+ library_cache_path: Path
13
+ path: str
14
+ apps: List[str]
15
+
16
+ def get_games(self) -> List[Game]:
17
+ return [Game(self.library_cache_path, self.path, appid) for appid in self.apps]
@@ -2,13 +2,9 @@ from __future__ import annotations
2
2
  from dataclasses import dataclass
3
3
  from pathlib import Path
4
4
  from typing import List, Optional
5
- from typing import TYPE_CHECKING
6
5
 
7
6
  import vdf # type: ignore
8
7
 
9
- if TYPE_CHECKING:
10
- from steam_client.steam import Steam
11
-
12
8
  from .shortcut import Shortcut
13
9
 
14
10
  STEAM64_OFFSET = 76561197960265728
@@ -35,8 +31,8 @@ class UserData:
35
31
  class LoginUser:
36
32
  """Represents a current or previous logged in Steam user."""
37
33
 
38
- def __init__(self, steam: Steam, user: User):
39
- self._steam = steam
34
+ def __init__(self, base_path: str, user: User):
35
+ self._base_path = Path(base_path)
40
36
  self.user = user
41
37
 
42
38
  @property
@@ -53,7 +49,7 @@ class LoginUser:
53
49
  @property
54
50
  def user_data_dir(self) -> Path:
55
51
  """Returns the path to the userdata folder."""
56
- return Path(self._steam.base_path).joinpath('userdata', str(self.steam_id3))
52
+ return self._base_path.joinpath('userdata', str(self.steam_id3))
57
53
 
58
54
  @property
59
55
  def config(self) -> Path:
@@ -74,25 +70,28 @@ class LoginUser:
74
70
  """Returns the data from the shortcuts.vdf file."""
75
71
  with open(self.shortcuts_file, 'rb') as f:
76
72
  shortcuts = vdf.binary_load(f)
77
- return [Shortcut(self._steam, self, shortcuts['shortcuts'][shortcut_idx]) for shortcut_idx in shortcuts['shortcuts']]
73
+ return [Shortcut(self, shortcuts['shortcuts'][shortcut_idx]) for shortcut_idx in shortcuts['shortcuts']]
78
74
 
79
75
 
80
76
  class LoginUsers:
81
77
  """Represents the loginusers.vdf file."""
82
78
 
83
- def __init__(self, steam: Steam):
84
- self._steam = steam
79
+ def __init__(self, base_path: str):
80
+ self._base_path = Path(base_path)
85
81
 
86
82
  @property
87
83
  def _path(self) -> Path:
88
84
  """Returns the path to the loginusers.vdf file."""
89
- return Path(self._steam.base_path).joinpath('config', 'loginusers.vdf')
85
+ return self._base_path.joinpath('config', 'loginusers.vdf')
90
86
 
91
87
  def users(self) -> List[LoginUser]:
92
88
  """Returns the users from the loginusers.vdf file."""
93
89
  with open(self._path, 'r', encoding='utf-8', errors='ignore') as f:
94
90
  login_users = vdf.load(f)
95
- return [LoginUser(self._steam, User(int(user_id), user_data)) for user_id, user_data in login_users['users'].items()]
91
+ return [
92
+ LoginUser(str(self._base_path), User(int(user_id), user_data))
93
+ for user_id, user_data in login_users['users'].items()
94
+ ]
96
95
 
97
96
  def most_recent_user(self) -> Optional[LoginUser]:
98
97
  """Returns the most recent user from the loginusers.vdf file."""
@@ -6,7 +6,6 @@ from typing import TypedDict
6
6
  import pycrc.algorithms as crc # type: ignore
7
7
 
8
8
  if TYPE_CHECKING:
9
- from .steam import Steam
10
9
  from .login_users import LoginUser
11
10
 
12
11
  from .app import App
@@ -25,13 +24,13 @@ class ShortcutEntry(TypedDict):
25
24
  class Shortcut(App):
26
25
  """Represents a Non-Steam Game shortcut."""
27
26
 
28
- def __init__(self, steam: Steam, user: LoginUser, data: ShortcutEntry):
27
+ def __init__(self, user: LoginUser, data: ShortcutEntry):
29
28
  self._data = data
30
29
  self._user = user
31
- super().__init__(steam)
30
+ super().__init__()
32
31
 
33
32
  def __repr__(self) -> str:
34
- return f'Shortcut(steam={self._steam.__repr__()}, data={self._data.__repr__()})'
33
+ return f'Shortcut(data={self._data.__repr__()})'
35
34
 
36
35
  @property
37
36
  def name(self) -> str:
@@ -39,7 +39,7 @@ class Steam:
39
39
 
40
40
  @property
41
41
  def users(self):
42
- return LoginUsers(self).users()
42
+ return LoginUsers(self.base_path).users()
43
43
 
44
44
  @property
45
45
  def library(self) -> Library: