multiplayer 0.12.0__tar.gz → 1.1.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.
- {multiplayer-0.12.0 → multiplayer-1.1.0}/PKG-INFO +57 -20
- {multiplayer-0.12.0 → multiplayer-1.1.0}/README.md +54 -18
- {multiplayer-0.12.0 → multiplayer-1.1.0}/pyproject.toml +9 -3
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/__init__.py +2 -0
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/client.py +282 -103
- multiplayer-1.1.0/src/multiplayer/data/persistence.py +516 -0
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/exceptions.py +8 -0
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/game.py +134 -31
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/run_server.py +31 -1
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/server.py +522 -123
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/utils.py +35 -2
- {multiplayer-0.12.0 → multiplayer-1.1.0}/LICENSE.md +0 -0
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/IPClogging/__init__.py +0 -0
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/IPClogging/echoing.py +0 -0
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/IPClogging/server.py +0 -0
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/IPClogging/test.py +0 -0
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/data/__init__.py +0 -0
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/data/cities.csv +0 -0
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/data/countries.csv +0 -0
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/data/egyptian_gods.csv +0 -0
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/data/european_kings.csv +0 -0
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/data/european_queens.csv +0 -0
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/data/greek_gods.csv +0 -0
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/data/planets_moons.csv +0 -0
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/data/rivers.csv +0 -0
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/data/roman_gods.csv +0 -0
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/data/seas_oceans.csv +0 -0
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/language/__init__.py +0 -0
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/language/language.py +0 -0
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/py.typed +0 -0
- {multiplayer-0.12.0 → multiplayer-1.1.0}/src/multiplayer/run_log_server.py +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: multiplayer
|
|
3
|
-
Version:
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: Library that allows you to manage multiple players, locally, on a network, or on the Internet.
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
License-File: LICENSE.md
|
|
7
|
-
Classifier: Development Status ::
|
|
7
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
8
8
|
Classifier: Intended Audience :: Developers
|
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
|
10
10
|
Classifier: Programming Language :: Python :: 3.12
|
|
@@ -13,6 +13,7 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
13
13
|
Classifier: Topic :: Games/Entertainment
|
|
14
14
|
Requires-Dist: colorlog
|
|
15
15
|
Requires-Dist: cryptography
|
|
16
|
+
Requires-Dist: bcrypt
|
|
16
17
|
Requires-Dist: pytest ; extra == 'dev'
|
|
17
18
|
Requires-Dist: requests ; extra == 'dev'
|
|
18
19
|
Requires-Dist: ruff ; extra == 'dev'
|
|
@@ -20,7 +21,7 @@ Requires-Python: >=3.12
|
|
|
20
21
|
Provides-Extra: dev
|
|
21
22
|
Description-Content-Type: text/markdown
|
|
22
23
|
|
|
23
|
-
**English** | [Español](translation/README.es.md) | [Français](translation/README.fr.md)
|
|
24
|
+
**English** | [Español](translation/README.es.md) | [Français](translation/README.fr.md)
|
|
24
25
|
|
|
25
26
|
# Multiplayer Game Manager
|
|
26
27
|
|
|
@@ -41,12 +42,13 @@ For a detailed technical description of all classes and functions, see the [API
|
|
|
41
42
|
* **Observer Support:** Ability to add observers who can view the game state without participating as players.
|
|
42
43
|
* **Administrator Role:** New `ServerAdmin` class to manage the server, kick players/observers, and monitor server status.
|
|
43
44
|
* **Game Grouping:** Organize several game sessions within the same server using the `GameGroup` class.
|
|
44
|
-
* **Multi-Layered Security:** Supports server passwords, admin passwords, and per-game passwords, with optional TLS v1.3 encryption. Passwords can be updated dynamically by administrators.
|
|
45
|
+
* **Multi-Layered Security:** Supports server passwords, admin passwords, and per-game passwords, with optional TLS v1.3 encryption. Passwords can be updated dynamically by administrators and are securely stored using `bcrypt` hashing.
|
|
45
46
|
* **Automatic Server Discovery:** Clients can automatically find running servers on the local network.
|
|
46
47
|
* **Extensible Name Suggestions:** Includes a utility function to suggest creative names for games and players.
|
|
47
|
-
* **Multiple Games:** The server can manage multiple game sessions simultaneously,
|
|
48
|
+
* **Multiple Games:** The server can manage multiple game sessions simultaneously. By default, the game list for standard clients is filtered to hide finished games, but administrators can access all sessions via specialized methods like `list_all_server_games()` or `list_all_group_games()`.
|
|
48
49
|
* **Robust Error Handling:** A clear set of custom exceptions for both game logic and network issues.
|
|
49
|
-
* **Persistent Player Accounts:** Ability for players to create an account with a password for repeated use across the server.
|
|
50
|
+
* **Persistent Player Accounts:** Ability for players to create an account with a password for repeated use across the server. All persistent passwords (players, groups, and server) are protected with `bcrypt`.
|
|
51
|
+
* **Data Persistence:** Optional support for persisting server configuration, player accounts, and game sessions to disk (e.g., in JSON format). Hash-based password storage ensures security even if the data file is compromised.
|
|
50
52
|
|
|
51
53
|
## Installation
|
|
52
54
|
|
|
@@ -60,9 +62,9 @@ pip install multiplayer
|
|
|
60
62
|
### 2. From a Wheel file (GitHub)
|
|
61
63
|
Download the `.whl` file from the [Releases](https://github.com/devfred78/multiplayer/releases) page and run:
|
|
62
64
|
```sh
|
|
63
|
-
pip install multiplayer-
|
|
65
|
+
pip install multiplayer-1.1.0-py3-none-any.whl
|
|
64
66
|
```
|
|
65
|
-
*Replace `multiplayer-
|
|
67
|
+
*Replace `multiplayer-1.1.0-py3-none-any.whl` with the actual name of the downloaded file.*
|
|
66
68
|
|
|
67
69
|
## Usage
|
|
68
70
|
|
|
@@ -103,7 +105,7 @@ game2 = Game("Match 2")
|
|
|
103
105
|
group.add_game(game1)
|
|
104
106
|
group.add_game(game2)
|
|
105
107
|
|
|
106
|
-
print(f"Game 1 ID: {game1.
|
|
108
|
+
print(f"Game 1 ID: {game1.game_id}")
|
|
107
109
|
# > Game 1 ID: 550e8400-e29b-41d4-a716-446655440000
|
|
108
110
|
|
|
109
111
|
print(f"Group '{group.name}' has {len(group.games)} games.")
|
|
@@ -199,11 +201,7 @@ admin = ServerAdmin(
|
|
|
199
201
|
|
|
200
202
|
# Manage the server
|
|
201
203
|
info = admin.get_server_info()
|
|
202
|
-
print(f"
|
|
203
|
-
|
|
204
|
-
# Check certificate expiration
|
|
205
|
-
expiration = admin.get_cert_expiration()
|
|
206
|
-
print(f"Certificate expires on: {expiration}")
|
|
204
|
+
print(f"Uptime: {info['uptime']} seconds")
|
|
207
205
|
|
|
208
206
|
# Kick a player if necessary
|
|
209
207
|
# admin.kick_player(game_id, player_id)
|
|
@@ -221,7 +219,7 @@ servers = GameClient.discover_servers()
|
|
|
221
219
|
if not servers:
|
|
222
220
|
print("No servers found.")
|
|
223
221
|
else:
|
|
224
|
-
host, port = servers[0]
|
|
222
|
+
host, port, name = servers[0]
|
|
225
223
|
client = GameClient(
|
|
226
224
|
host=host,
|
|
227
225
|
port=port,
|
|
@@ -234,12 +232,13 @@ else:
|
|
|
234
232
|
name=suggest_game_name(),
|
|
235
233
|
password="my_game_password"
|
|
236
234
|
)
|
|
237
|
-
print(f"Created game with ID: {private_game.
|
|
235
|
+
print(f"Created game with ID: {private_game.game_id}")
|
|
238
236
|
|
|
239
237
|
# 3. Create and use a Game Group
|
|
240
|
-
|
|
241
|
-
game_in_group =
|
|
242
|
-
|
|
238
|
+
remote_group = client.create_group("Tournament A")
|
|
239
|
+
game_in_group = remote_group.create_game(name="Final Match")
|
|
240
|
+
# To get the group ID or name, we use the properties
|
|
241
|
+
print(f"Game in group '{remote_group.name}' has ID: {game_in_group.game_id}")
|
|
243
242
|
|
|
244
243
|
# 4. A player joins and sets the initial state
|
|
245
244
|
private_game.add_player(Player("Charlie"), password="my_game_password")
|
|
@@ -247,6 +246,39 @@ else:
|
|
|
247
246
|
private_game.start()
|
|
248
247
|
```
|
|
249
248
|
|
|
249
|
+
### Name Suggestions
|
|
250
|
+
|
|
251
|
+
The `multiplayer` package includes a powerful name suggestion utility to help you create creative names for games and players.
|
|
252
|
+
|
|
253
|
+
```python
|
|
254
|
+
from multiplayer import suggest_game_name, suggest_player_name
|
|
255
|
+
|
|
256
|
+
# Get a random name
|
|
257
|
+
print(suggest_game_name()) # e.g., "Pacific Ocean"
|
|
258
|
+
print(suggest_player_name()) # e.g., "Zeus"
|
|
259
|
+
|
|
260
|
+
# Specify a category
|
|
261
|
+
print(suggest_game_name(category="planets_moons")) # e.g., "Europa"
|
|
262
|
+
print(suggest_player_name(category="european_queens")) # e.g., "Elizabeth I"
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
#### Built-in Categories
|
|
266
|
+
* **For Games**: `cities`, `countries`, `rivers`, `seas_oceans`, `planets_moons`.
|
|
267
|
+
* **For Players**: `roman_gods`, `greek_gods`, `egyptian_gods`, `european_kings`, `european_queens`.
|
|
268
|
+
|
|
269
|
+
#### Custom Categories
|
|
270
|
+
You can also register your own categories using a list of names or a file:
|
|
271
|
+
|
|
272
|
+
```python
|
|
273
|
+
from multiplayer import register_name_category
|
|
274
|
+
|
|
275
|
+
# Register from a list
|
|
276
|
+
register_name_category("monsters", ["Godzilla", "King Kong"], category_type="player")
|
|
277
|
+
|
|
278
|
+
# Register from a text/CSV file
|
|
279
|
+
register_name_category("races", "path/to/races.txt", category_type="player")
|
|
280
|
+
```
|
|
281
|
+
|
|
250
282
|
## Error Handling
|
|
251
283
|
|
|
252
284
|
The module provides a set of custom exceptions, including `AuthenticationError` for both server and game passwords.
|
|
@@ -282,4 +314,9 @@ pip install pytest
|
|
|
282
314
|
Then, you can run the tests from the root of the project:
|
|
283
315
|
|
|
284
316
|
```sh
|
|
285
|
-
pytest
|
|
317
|
+
pytest
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## License
|
|
321
|
+
|
|
322
|
+
This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
**English** | [Español](translation/README.es.md) | [Français](translation/README.fr.md)
|
|
1
|
+
**English** | [Español](translation/README.es.md) | [Français](translation/README.fr.md)
|
|
2
2
|
|
|
3
3
|
# Multiplayer Game Manager
|
|
4
4
|
|
|
@@ -19,12 +19,13 @@ For a detailed technical description of all classes and functions, see the [API
|
|
|
19
19
|
* **Observer Support:** Ability to add observers who can view the game state without participating as players.
|
|
20
20
|
* **Administrator Role:** New `ServerAdmin` class to manage the server, kick players/observers, and monitor server status.
|
|
21
21
|
* **Game Grouping:** Organize several game sessions within the same server using the `GameGroup` class.
|
|
22
|
-
* **Multi-Layered Security:** Supports server passwords, admin passwords, and per-game passwords, with optional TLS v1.3 encryption. Passwords can be updated dynamically by administrators.
|
|
22
|
+
* **Multi-Layered Security:** Supports server passwords, admin passwords, and per-game passwords, with optional TLS v1.3 encryption. Passwords can be updated dynamically by administrators and are securely stored using `bcrypt` hashing.
|
|
23
23
|
* **Automatic Server Discovery:** Clients can automatically find running servers on the local network.
|
|
24
24
|
* **Extensible Name Suggestions:** Includes a utility function to suggest creative names for games and players.
|
|
25
|
-
* **Multiple Games:** The server can manage multiple game sessions simultaneously,
|
|
25
|
+
* **Multiple Games:** The server can manage multiple game sessions simultaneously. By default, the game list for standard clients is filtered to hide finished games, but administrators can access all sessions via specialized methods like `list_all_server_games()` or `list_all_group_games()`.
|
|
26
26
|
* **Robust Error Handling:** A clear set of custom exceptions for both game logic and network issues.
|
|
27
|
-
* **Persistent Player Accounts:** Ability for players to create an account with a password for repeated use across the server.
|
|
27
|
+
* **Persistent Player Accounts:** Ability for players to create an account with a password for repeated use across the server. All persistent passwords (players, groups, and server) are protected with `bcrypt`.
|
|
28
|
+
* **Data Persistence:** Optional support for persisting server configuration, player accounts, and game sessions to disk (e.g., in JSON format). Hash-based password storage ensures security even if the data file is compromised.
|
|
28
29
|
|
|
29
30
|
## Installation
|
|
30
31
|
|
|
@@ -38,9 +39,9 @@ pip install multiplayer
|
|
|
38
39
|
### 2. From a Wheel file (GitHub)
|
|
39
40
|
Download the `.whl` file from the [Releases](https://github.com/devfred78/multiplayer/releases) page and run:
|
|
40
41
|
```sh
|
|
41
|
-
pip install multiplayer-
|
|
42
|
+
pip install multiplayer-1.1.0-py3-none-any.whl
|
|
42
43
|
```
|
|
43
|
-
*Replace `multiplayer-
|
|
44
|
+
*Replace `multiplayer-1.1.0-py3-none-any.whl` with the actual name of the downloaded file.*
|
|
44
45
|
|
|
45
46
|
## Usage
|
|
46
47
|
|
|
@@ -81,7 +82,7 @@ game2 = Game("Match 2")
|
|
|
81
82
|
group.add_game(game1)
|
|
82
83
|
group.add_game(game2)
|
|
83
84
|
|
|
84
|
-
print(f"Game 1 ID: {game1.
|
|
85
|
+
print(f"Game 1 ID: {game1.game_id}")
|
|
85
86
|
# > Game 1 ID: 550e8400-e29b-41d4-a716-446655440000
|
|
86
87
|
|
|
87
88
|
print(f"Group '{group.name}' has {len(group.games)} games.")
|
|
@@ -177,11 +178,7 @@ admin = ServerAdmin(
|
|
|
177
178
|
|
|
178
179
|
# Manage the server
|
|
179
180
|
info = admin.get_server_info()
|
|
180
|
-
print(f"
|
|
181
|
-
|
|
182
|
-
# Check certificate expiration
|
|
183
|
-
expiration = admin.get_cert_expiration()
|
|
184
|
-
print(f"Certificate expires on: {expiration}")
|
|
181
|
+
print(f"Uptime: {info['uptime']} seconds")
|
|
185
182
|
|
|
186
183
|
# Kick a player if necessary
|
|
187
184
|
# admin.kick_player(game_id, player_id)
|
|
@@ -199,7 +196,7 @@ servers = GameClient.discover_servers()
|
|
|
199
196
|
if not servers:
|
|
200
197
|
print("No servers found.")
|
|
201
198
|
else:
|
|
202
|
-
host, port = servers[0]
|
|
199
|
+
host, port, name = servers[0]
|
|
203
200
|
client = GameClient(
|
|
204
201
|
host=host,
|
|
205
202
|
port=port,
|
|
@@ -212,12 +209,13 @@ else:
|
|
|
212
209
|
name=suggest_game_name(),
|
|
213
210
|
password="my_game_password"
|
|
214
211
|
)
|
|
215
|
-
print(f"Created game with ID: {private_game.
|
|
212
|
+
print(f"Created game with ID: {private_game.game_id}")
|
|
216
213
|
|
|
217
214
|
# 3. Create and use a Game Group
|
|
218
|
-
|
|
219
|
-
game_in_group =
|
|
220
|
-
|
|
215
|
+
remote_group = client.create_group("Tournament A")
|
|
216
|
+
game_in_group = remote_group.create_game(name="Final Match")
|
|
217
|
+
# To get the group ID or name, we use the properties
|
|
218
|
+
print(f"Game in group '{remote_group.name}' has ID: {game_in_group.game_id}")
|
|
221
219
|
|
|
222
220
|
# 4. A player joins and sets the initial state
|
|
223
221
|
private_game.add_player(Player("Charlie"), password="my_game_password")
|
|
@@ -225,6 +223,39 @@ else:
|
|
|
225
223
|
private_game.start()
|
|
226
224
|
```
|
|
227
225
|
|
|
226
|
+
### Name Suggestions
|
|
227
|
+
|
|
228
|
+
The `multiplayer` package includes a powerful name suggestion utility to help you create creative names for games and players.
|
|
229
|
+
|
|
230
|
+
```python
|
|
231
|
+
from multiplayer import suggest_game_name, suggest_player_name
|
|
232
|
+
|
|
233
|
+
# Get a random name
|
|
234
|
+
print(suggest_game_name()) # e.g., "Pacific Ocean"
|
|
235
|
+
print(suggest_player_name()) # e.g., "Zeus"
|
|
236
|
+
|
|
237
|
+
# Specify a category
|
|
238
|
+
print(suggest_game_name(category="planets_moons")) # e.g., "Europa"
|
|
239
|
+
print(suggest_player_name(category="european_queens")) # e.g., "Elizabeth I"
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
#### Built-in Categories
|
|
243
|
+
* **For Games**: `cities`, `countries`, `rivers`, `seas_oceans`, `planets_moons`.
|
|
244
|
+
* **For Players**: `roman_gods`, `greek_gods`, `egyptian_gods`, `european_kings`, `european_queens`.
|
|
245
|
+
|
|
246
|
+
#### Custom Categories
|
|
247
|
+
You can also register your own categories using a list of names or a file:
|
|
248
|
+
|
|
249
|
+
```python
|
|
250
|
+
from multiplayer import register_name_category
|
|
251
|
+
|
|
252
|
+
# Register from a list
|
|
253
|
+
register_name_category("monsters", ["Godzilla", "King Kong"], category_type="player")
|
|
254
|
+
|
|
255
|
+
# Register from a text/CSV file
|
|
256
|
+
register_name_category("races", "path/to/races.txt", category_type="player")
|
|
257
|
+
```
|
|
258
|
+
|
|
228
259
|
## Error Handling
|
|
229
260
|
|
|
230
261
|
The module provides a set of custom exceptions, including `AuthenticationError` for both server and game passwords.
|
|
@@ -260,4 +291,9 @@ pip install pytest
|
|
|
260
291
|
Then, you can run the tests from the root of the project:
|
|
261
292
|
|
|
262
293
|
```sh
|
|
263
|
-
pytest
|
|
294
|
+
pytest
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## License
|
|
298
|
+
|
|
299
|
+
This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "multiplayer"
|
|
3
|
-
version = "
|
|
3
|
+
version = "1.1.0"
|
|
4
4
|
description = "Library that allows you to manage multiple players, locally, on a network, or on the Internet."
|
|
5
5
|
license = "MIT"
|
|
6
6
|
license-files = ["LICENSE.md"]
|
|
@@ -8,7 +8,7 @@ author = "devfred78"
|
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
requires-python = ">=3.12"
|
|
10
10
|
classifiers = [
|
|
11
|
-
"Development Status ::
|
|
11
|
+
"Development Status :: 5 - Production/Stable",
|
|
12
12
|
"Intended Audience :: Developers",
|
|
13
13
|
"Programming Language :: Python :: 3",
|
|
14
14
|
"Programming Language :: Python :: 3.12",
|
|
@@ -19,6 +19,7 @@ classifiers = [
|
|
|
19
19
|
dependencies = [
|
|
20
20
|
"colorlog",
|
|
21
21
|
"cryptography",
|
|
22
|
+
"bcrypt",
|
|
22
23
|
]
|
|
23
24
|
|
|
24
25
|
[project.scripts]
|
|
@@ -33,10 +34,15 @@ dev = [
|
|
|
33
34
|
]
|
|
34
35
|
|
|
35
36
|
[build-system]
|
|
36
|
-
requires = ["uv_build>=0.11.7,<
|
|
37
|
+
requires = ["uv_build>=0.11.7,<1.1.0"]
|
|
37
38
|
build-backend = "uv_build"
|
|
38
39
|
|
|
39
40
|
[tool.uv.build-backend]
|
|
40
41
|
module-name = "multiplayer"
|
|
41
42
|
module-root = "src"
|
|
42
43
|
package-data = { "multiplayer" = ["data/*.csv"] }
|
|
44
|
+
|
|
45
|
+
[dependency-groups]
|
|
46
|
+
dev = [
|
|
47
|
+
"requests>=2.34.1",
|
|
48
|
+
]
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
This package provides classes for managing a multiplayer game, both locally and over a network.
|
|
3
3
|
"""
|
|
4
|
+
__version__ = "1.1.0"
|
|
4
5
|
from .game import Game, Player, Observer, GameState, GameGroup
|
|
5
6
|
from .server import GameServer
|
|
6
7
|
from .client import GameClient, RemoteGame, ServerAdmin, GroupAdmin
|
|
@@ -49,4 +50,5 @@ __all__ = [
|
|
|
49
50
|
'ConnectionError',
|
|
50
51
|
'ServerError',
|
|
51
52
|
'AuthenticationError',
|
|
53
|
+
'__version__',
|
|
52
54
|
]
|