softmax-cli 0.26.8__tar.gz → 0.26.10__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.
- {softmax_cli-0.26.8/src/softmax_cli.egg-info → softmax_cli-0.26.10}/PKG-INFO +1 -1
- {softmax_cli-0.26.8 → softmax_cli-0.26.10}/src/softmax/auth.py +5 -0
- {softmax_cli-0.26.8 → softmax_cli-0.26.10}/src/softmax/cli.py +68 -43
- {softmax_cli-0.26.8 → softmax_cli-0.26.10}/src/softmax/cogames.py +6 -9
- {softmax_cli-0.26.8 → softmax_cli-0.26.10/src/softmax_cli.egg-info}/PKG-INFO +1 -1
- {softmax_cli-0.26.8 → softmax_cli-0.26.10}/tests/test_auth_login.py +59 -6
- {softmax_cli-0.26.8 → softmax_cli-0.26.10}/tests/test_python_api.py +3 -7
- {softmax_cli-0.26.8 → softmax_cli-0.26.10}/BUILD.bazel +0 -0
- {softmax_cli-0.26.8 → softmax_cli-0.26.10}/pyproject.toml +0 -0
- {softmax_cli-0.26.8 → softmax_cli-0.26.10}/setup.cfg +0 -0
- {softmax_cli-0.26.8 → softmax_cli-0.26.10}/src/softmax/__init__.py +0 -0
- {softmax_cli-0.26.8 → softmax_cli-0.26.10}/src/softmax/_console.py +0 -0
- {softmax_cli-0.26.8 → softmax_cli-0.26.10}/src/softmax/perform_login.py +0 -0
- {softmax_cli-0.26.8 → softmax_cli-0.26.10}/src/softmax/token_storage.py +0 -0
- {softmax_cli-0.26.8 → softmax_cli-0.26.10}/src/softmax_cli.egg-info/SOURCES.txt +0 -0
- {softmax_cli-0.26.8 → softmax_cli-0.26.10}/src/softmax_cli.egg-info/dependency_links.txt +0 -0
- {softmax_cli-0.26.8 → softmax_cli-0.26.10}/src/softmax_cli.egg-info/entry_points.txt +0 -0
- {softmax_cli-0.26.8 → softmax_cli-0.26.10}/src/softmax_cli.egg-info/requires.txt +0 -0
- {softmax_cli-0.26.8 → softmax_cli-0.26.10}/src/softmax_cli.egg-info/top_level.txt +0 -0
- {softmax_cli-0.26.8 → softmax_cli-0.26.10}/tests/BUILD.bazel +0 -0
- {softmax_cli-0.26.8 → softmax_cli-0.26.10}/tests/test_cli_plugins.py +0 -0
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import os
|
|
5
6
|
from urllib.parse import urlencode, urlsplit, urlunsplit
|
|
6
7
|
|
|
7
8
|
import httpx
|
|
@@ -16,6 +17,10 @@ DEFAULT_COGAMES_SERVER = "https://softmax.com/api"
|
|
|
16
17
|
DEFAULT_COGAMES_API_SERVER = "https://api.observatory.softmax-research.net"
|
|
17
18
|
|
|
18
19
|
|
|
20
|
+
def get_login_server() -> str:
|
|
21
|
+
return os.environ.get("COGAMES_LOGIN_URL", DEFAULT_COGAMES_SERVER)
|
|
22
|
+
|
|
23
|
+
|
|
19
24
|
class WhoAmIResponse(BaseModel):
|
|
20
25
|
user_email: str
|
|
21
26
|
is_softmax_team_member: bool = False
|
|
@@ -4,6 +4,7 @@ import importlib
|
|
|
4
4
|
import importlib.util
|
|
5
5
|
import sys
|
|
6
6
|
|
|
7
|
+
import httpx
|
|
7
8
|
import typer
|
|
8
9
|
from rich.panel import Panel
|
|
9
10
|
|
|
@@ -13,6 +14,7 @@ from softmax.auth import (
|
|
|
13
14
|
build_browser_login_url,
|
|
14
15
|
delete_cogames_tokens,
|
|
15
16
|
fetch_cogames_whoami,
|
|
17
|
+
get_login_server,
|
|
16
18
|
load_cogames_user_token,
|
|
17
19
|
load_current_cogames_token,
|
|
18
20
|
save_cogames_active_token,
|
|
@@ -39,15 +41,16 @@ def _register_optional_apps() -> None:
|
|
|
39
41
|
app.add_typer(cogames_cli.app, name="cogames", rich_help_panel="Local Games")
|
|
40
42
|
|
|
41
43
|
|
|
42
|
-
def _build_manual_set_token_command(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return command
|
|
44
|
+
def _build_manual_set_token_command(server: str | None = None) -> str:
|
|
45
|
+
if server:
|
|
46
|
+
return f"softmax set-token --server '{server}' '<TOKEN>'"
|
|
47
|
+
return "softmax set-token '<TOKEN>'"
|
|
47
48
|
|
|
48
49
|
|
|
49
|
-
def _print_non_tty_login_instructions(
|
|
50
|
-
|
|
50
|
+
def _print_non_tty_login_instructions(login_server: str | None = None) -> None:
|
|
51
|
+
resolved = login_server or get_login_server()
|
|
52
|
+
is_custom = resolved != DEFAULT_COGAMES_SERVER
|
|
53
|
+
auth_url = build_browser_login_url(resolved)
|
|
51
54
|
console.print("Interactive login requires a TTY.", style="red")
|
|
52
55
|
console.print()
|
|
53
56
|
console.print("Open this URL in any browser to sign in:", style="yellow")
|
|
@@ -56,7 +59,7 @@ def _print_non_tty_login_instructions(*, login_server: str) -> None:
|
|
|
56
59
|
console.print()
|
|
57
60
|
console.print("Copy the auth token from the browser, then run:", style="yellow")
|
|
58
61
|
console.print()
|
|
59
|
-
console.print(" ", _build_manual_set_token_command(
|
|
62
|
+
console.print(" ", _build_manual_set_token_command(resolved if is_custom else None))
|
|
60
63
|
console.print()
|
|
61
64
|
console.print(
|
|
62
65
|
Panel(
|
|
@@ -70,12 +73,6 @@ def _print_non_tty_login_instructions(*, login_server: str) -> None:
|
|
|
70
73
|
|
|
71
74
|
@app.command(name="login")
|
|
72
75
|
def login_cmd(
|
|
73
|
-
login_server: str = typer.Option(
|
|
74
|
-
DEFAULT_COGAMES_SERVER,
|
|
75
|
-
"--login-server",
|
|
76
|
-
metavar="URL",
|
|
77
|
-
help="Authentication server URL",
|
|
78
|
-
),
|
|
79
76
|
no_browser: bool = typer.Option(
|
|
80
77
|
False,
|
|
81
78
|
"--no-browser",
|
|
@@ -87,18 +84,43 @@ def login_cmd(
|
|
|
87
84
|
"-f",
|
|
88
85
|
help="Re-authenticate even if already logged in",
|
|
89
86
|
),
|
|
87
|
+
server: str | None = typer.Option(
|
|
88
|
+
None,
|
|
89
|
+
"--server",
|
|
90
|
+
"-s",
|
|
91
|
+
metavar="URL",
|
|
92
|
+
help="Authentication server URL.",
|
|
93
|
+
),
|
|
90
94
|
) -> None:
|
|
91
95
|
"""Sign in to Softmax."""
|
|
92
96
|
from urllib.parse import urlparse # noqa: PLC0415
|
|
93
97
|
|
|
98
|
+
login_server = server or get_login_server()
|
|
99
|
+
is_default_server = login_server == DEFAULT_COGAMES_SERVER
|
|
94
100
|
user_token = None if force else load_cogames_user_token(login_server=login_server)
|
|
101
|
+
if user_token is not None:
|
|
102
|
+
api_server = None if is_default_server else login_server
|
|
103
|
+
try:
|
|
104
|
+
whoami = fetch_cogames_whoami(api_server=api_server, token=user_token)
|
|
105
|
+
if whoami.subject_type == "anonymous":
|
|
106
|
+
console.print("Saved token is no longer valid. Re-authenticating...", style="yellow")
|
|
107
|
+
user_token = None
|
|
108
|
+
except httpx.HTTPStatusError as exc:
|
|
109
|
+
if exc.response.status_code == 401:
|
|
110
|
+
console.print("Saved token is no longer valid. Re-authenticating...", style="yellow")
|
|
111
|
+
user_token = None
|
|
112
|
+
else:
|
|
113
|
+
console.print(f"Could not verify token (HTTP {exc.response.status_code}), proceeding.", style="yellow")
|
|
114
|
+
except httpx.HTTPError:
|
|
115
|
+
console.print("Could not reach server to verify token. Proceeding with saved token.", style="yellow")
|
|
116
|
+
|
|
95
117
|
if user_token is not None:
|
|
96
118
|
save_cogames_active_token(login_server=login_server, token=user_token)
|
|
97
119
|
console.print(f"Already authenticated with {urlparse(login_server).hostname}", style="green")
|
|
98
120
|
return
|
|
99
121
|
|
|
100
122
|
if not sys.stdin.isatty():
|
|
101
|
-
_print_non_tty_login_instructions(login_server
|
|
123
|
+
_print_non_tty_login_instructions(login_server)
|
|
102
124
|
raise typer.Exit(1)
|
|
103
125
|
|
|
104
126
|
try:
|
|
@@ -110,7 +132,7 @@ def login_cmd(
|
|
|
110
132
|
"If you are a coding agent, ask your human to open the URL below and give you "
|
|
111
133
|
"the auth token. Then paste the token into this window or run:\n"
|
|
112
134
|
"\n"
|
|
113
|
-
f"{_build_manual_set_token_command(
|
|
135
|
+
f"{_build_manual_set_token_command(server)}"
|
|
114
136
|
),
|
|
115
137
|
open_browser=not no_browser,
|
|
116
138
|
)
|
|
@@ -128,14 +150,16 @@ def login_cmd(
|
|
|
128
150
|
|
|
129
151
|
@app.command(name="logout")
|
|
130
152
|
def logout_cmd(
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
"--
|
|
153
|
+
server: str | None = typer.Option(
|
|
154
|
+
None,
|
|
155
|
+
"--server",
|
|
156
|
+
"-s",
|
|
134
157
|
metavar="URL",
|
|
135
|
-
help="Authentication server URL",
|
|
158
|
+
help="Authentication server URL.",
|
|
136
159
|
),
|
|
137
160
|
) -> None:
|
|
138
161
|
"""Remove saved authentication token."""
|
|
162
|
+
login_server = server or get_login_server()
|
|
139
163
|
if delete_cogames_tokens(login_server=login_server):
|
|
140
164
|
console.print("Logged out.", style="green")
|
|
141
165
|
else:
|
|
@@ -144,42 +168,39 @@ def logout_cmd(
|
|
|
144
168
|
|
|
145
169
|
@app.command(name="get-login-url")
|
|
146
170
|
def get_login_url_cmd(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
"--
|
|
171
|
+
server: str | None = typer.Option(
|
|
172
|
+
None,
|
|
173
|
+
"--server",
|
|
174
|
+
"-s",
|
|
150
175
|
metavar="URL",
|
|
151
|
-
help="Authentication server URL",
|
|
176
|
+
help="Authentication server URL.",
|
|
152
177
|
),
|
|
153
178
|
) -> None:
|
|
154
179
|
"""Print a browser sign-in URL for manual login."""
|
|
155
|
-
print(build_browser_login_url(
|
|
180
|
+
print(build_browser_login_url(server or get_login_server()))
|
|
156
181
|
|
|
157
182
|
|
|
158
183
|
@app.command(name="status")
|
|
159
184
|
def status_cmd(
|
|
160
|
-
login_server: str = typer.Option(
|
|
161
|
-
DEFAULT_COGAMES_SERVER,
|
|
162
|
-
"--login-server",
|
|
163
|
-
metavar="URL",
|
|
164
|
-
help="Authentication server URL",
|
|
165
|
-
),
|
|
166
185
|
server: str | None = typer.Option(
|
|
167
186
|
None,
|
|
168
187
|
"--server",
|
|
169
188
|
"-s",
|
|
170
189
|
metavar="URL",
|
|
171
|
-
help="
|
|
172
|
-
" that is overridden, otherwise the production Observatory API.",
|
|
190
|
+
help="Authentication server URL.",
|
|
173
191
|
),
|
|
174
192
|
) -> None:
|
|
175
193
|
"""Check authentication status via /whoami."""
|
|
194
|
+
login_server = server or get_login_server()
|
|
176
195
|
token = load_current_cogames_token(login_server=login_server)
|
|
177
196
|
if not token:
|
|
178
197
|
console.print("[red]Not authenticated.[/red] Run [cyan]softmax login[/cyan] first.")
|
|
179
198
|
raise typer.Exit(1)
|
|
180
199
|
|
|
181
|
-
|
|
182
|
-
session
|
|
200
|
+
session = fetch_cogames_whoami(api_server=server, token=token)
|
|
201
|
+
if session.subject_type == "anonymous":
|
|
202
|
+
console.print("[red]Token is invalid or expired.[/red] Run [cyan]softmax login[/cyan] to re-authenticate.")
|
|
203
|
+
raise typer.Exit(1)
|
|
183
204
|
console.print("[green]Authenticated[/green]")
|
|
184
205
|
console.print(f"user_email: {session.user_email}")
|
|
185
206
|
console.print(f"subject_type: {session.subject_type}")
|
|
@@ -189,14 +210,16 @@ def status_cmd(
|
|
|
189
210
|
|
|
190
211
|
@app.command(name="get-token")
|
|
191
212
|
def get_token_cmd(
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
"--
|
|
213
|
+
server: str | None = typer.Option(
|
|
214
|
+
None,
|
|
215
|
+
"--server",
|
|
216
|
+
"-s",
|
|
195
217
|
metavar="URL",
|
|
196
|
-
help="Authentication server URL",
|
|
218
|
+
help="Authentication server URL.",
|
|
197
219
|
),
|
|
198
220
|
) -> None:
|
|
199
221
|
"""Print the saved token to stdout (for scripting)."""
|
|
222
|
+
login_server = server or get_login_server()
|
|
200
223
|
token = load_current_cogames_token(login_server=login_server)
|
|
201
224
|
if not token:
|
|
202
225
|
console.print("[red]No token found.[/red] Run [cyan]softmax login[/cyan] first.", style="bold")
|
|
@@ -207,14 +230,16 @@ def get_token_cmd(
|
|
|
207
230
|
@app.command(name="set-token")
|
|
208
231
|
def set_token_cmd(
|
|
209
232
|
token: str = typer.Argument(help="Bearer token to save"),
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
"--
|
|
233
|
+
server: str | None = typer.Option(
|
|
234
|
+
None,
|
|
235
|
+
"--server",
|
|
236
|
+
"-s",
|
|
213
237
|
metavar="URL",
|
|
214
|
-
help="Authentication server URL",
|
|
238
|
+
help="Authentication server URL.",
|
|
215
239
|
),
|
|
216
240
|
) -> None:
|
|
217
241
|
"""Manually set a token (for CI or headless environments)."""
|
|
242
|
+
login_server = server or get_login_server()
|
|
218
243
|
save_cogames_user_token(login_server=login_server, token=token)
|
|
219
244
|
print(f"\nToken saved for {login_server}")
|
|
220
245
|
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import importlib
|
|
4
4
|
from typing import Any
|
|
5
5
|
|
|
6
|
-
from softmax.auth import DEFAULT_COGAMES_API_SERVER
|
|
6
|
+
from softmax.auth import DEFAULT_COGAMES_API_SERVER
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
def _get_tournament_client_class() -> type[Any]:
|
|
@@ -16,9 +16,9 @@ def _get_tournament_client_class() -> type[Any]:
|
|
|
16
16
|
return tournament_client_module.TournamentServerClient
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
def _create_client(*, token: str, server: str
|
|
19
|
+
def _create_client(*, token: str, server: str) -> Any:
|
|
20
20
|
client_class = _get_tournament_client_class()
|
|
21
|
-
return client_class(server_url=server, token=token
|
|
21
|
+
return client_class(server_url=server, token=token)
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
class _PlayerAPI:
|
|
@@ -27,9 +27,8 @@ class _PlayerAPI:
|
|
|
27
27
|
token: str,
|
|
28
28
|
*,
|
|
29
29
|
server: str = DEFAULT_COGAMES_API_SERVER,
|
|
30
|
-
login_server: str = DEFAULT_COGAMES_SERVER,
|
|
31
30
|
) -> list[Any]:
|
|
32
|
-
with _create_client(token=token, server=server
|
|
31
|
+
with _create_client(token=token, server=server) as client:
|
|
33
32
|
return client.list_players()
|
|
34
33
|
|
|
35
34
|
|
|
@@ -41,9 +40,8 @@ def login(
|
|
|
41
40
|
player_id: str,
|
|
42
41
|
*,
|
|
43
42
|
server: str = DEFAULT_COGAMES_API_SERVER,
|
|
44
|
-
login_server: str = DEFAULT_COGAMES_SERVER,
|
|
45
43
|
) -> str:
|
|
46
|
-
with _create_client(token=token, server=server
|
|
44
|
+
with _create_client(token=token, server=server) as client:
|
|
47
45
|
return client.login_player(player_id).token
|
|
48
46
|
|
|
49
47
|
|
|
@@ -52,9 +50,8 @@ def login_response(
|
|
|
52
50
|
player_id: str,
|
|
53
51
|
*,
|
|
54
52
|
server: str = DEFAULT_COGAMES_API_SERVER,
|
|
55
|
-
login_server: str = DEFAULT_COGAMES_SERVER,
|
|
56
53
|
) -> Any:
|
|
57
|
-
with _create_client(token=token, server=server
|
|
54
|
+
with _create_client(token=token, server=server) as client:
|
|
58
55
|
return client.login_player(player_id)
|
|
59
56
|
|
|
60
57
|
|
|
@@ -146,12 +146,8 @@ def test_authenticate_reprompts_after_invalid_token(
|
|
|
146
146
|
assert "Invalid token. Please try again." in capsys.readouterr().out
|
|
147
147
|
|
|
148
148
|
|
|
149
|
-
def
|
|
150
|
-
assert _build_manual_set_token_command(
|
|
151
|
-
assert (
|
|
152
|
-
_build_manual_set_token_command(login_server="https://example.ngrok.app/api")
|
|
153
|
-
== "softmax set-token '<TOKEN>' --login-server 'https://example.ngrok.app/api'"
|
|
154
|
-
)
|
|
149
|
+
def test_manual_command_format() -> None:
|
|
150
|
+
assert _build_manual_set_token_command() == "softmax set-token '<TOKEN>'"
|
|
155
151
|
|
|
156
152
|
|
|
157
153
|
def test_generic_authenticator_does_not_print_cogames_agent_hint(
|
|
@@ -294,3 +290,60 @@ def test_save_token_raises_for_malformed_storage_section(
|
|
|
294
290
|
server="https://softmax.com/api",
|
|
295
291
|
token="abc",
|
|
296
292
|
)
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def test_status_fails_for_anonymous_session(
|
|
296
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
297
|
+
tmp_path,
|
|
298
|
+
) -> None:
|
|
299
|
+
monkeypatch.setenv("HOME", str(tmp_path))
|
|
300
|
+
save_token(token_kind=TokenKind.COGAMES, server="https://softmax.com/api", token="bad-token")
|
|
301
|
+
|
|
302
|
+
class FakeResponse:
|
|
303
|
+
def raise_for_status(self) -> None:
|
|
304
|
+
return None
|
|
305
|
+
|
|
306
|
+
def json(self) -> dict[str, object]:
|
|
307
|
+
return {
|
|
308
|
+
"user_email": "unknown",
|
|
309
|
+
"is_softmax_team_member": False,
|
|
310
|
+
"is_softmax_admin": False,
|
|
311
|
+
"subject_type": "anonymous",
|
|
312
|
+
"subject_id": None,
|
|
313
|
+
"owner_user_id": None,
|
|
314
|
+
"scopes": [],
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
monkeypatch.setattr("softmax.auth.httpx.get", lambda *args, **kwargs: FakeResponse())
|
|
318
|
+
|
|
319
|
+
result = runner.invoke(app, ["status"])
|
|
320
|
+
assert result.exit_code == 1
|
|
321
|
+
assert "invalid or expired" in result.stdout
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
def test_login_detects_anonymous_whoami_as_invalid_token(
|
|
325
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
326
|
+
tmp_path,
|
|
327
|
+
) -> None:
|
|
328
|
+
monkeypatch.setenv("HOME", str(tmp_path))
|
|
329
|
+
save_token(token_kind=TokenKind.COGAMES_USER, server="https://softmax.com/api", token="stale-token")
|
|
330
|
+
|
|
331
|
+
class FakeResponse:
|
|
332
|
+
def raise_for_status(self) -> None:
|
|
333
|
+
return None
|
|
334
|
+
|
|
335
|
+
def json(self) -> dict[str, object]:
|
|
336
|
+
return {
|
|
337
|
+
"user_email": "unknown",
|
|
338
|
+
"is_softmax_team_member": False,
|
|
339
|
+
"is_softmax_admin": False,
|
|
340
|
+
"subject_type": "anonymous",
|
|
341
|
+
"subject_id": None,
|
|
342
|
+
"owner_user_id": None,
|
|
343
|
+
"scopes": [],
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
monkeypatch.setattr("softmax.auth.httpx.get", lambda *args, **kwargs: FakeResponse())
|
|
347
|
+
|
|
348
|
+
result = runner.invoke(app, ["login", "--no-browser"])
|
|
349
|
+
assert "no longer valid" in result.stdout
|
|
@@ -74,10 +74,9 @@ def test_softmax_cogames_player_list_uses_expected_defaults(monkeypatch: pytest.
|
|
|
74
74
|
captured: dict[str, object] = {}
|
|
75
75
|
|
|
76
76
|
class FakeClient:
|
|
77
|
-
def __init__(self, *, server_url: str, token: str
|
|
77
|
+
def __init__(self, *, server_url: str, token: str) -> None:
|
|
78
78
|
captured["server_url"] = server_url
|
|
79
79
|
captured["token"] = token
|
|
80
|
-
captured["login_server"] = login_server
|
|
81
80
|
|
|
82
81
|
def __enter__(self) -> "FakeClient":
|
|
83
82
|
return self
|
|
@@ -94,7 +93,6 @@ def test_softmax_cogames_player_list_uses_expected_defaults(monkeypatch: pytest.
|
|
|
94
93
|
assert captured == {
|
|
95
94
|
"server_url": "https://api.observatory.softmax-research.net",
|
|
96
95
|
"token": "softmax-token",
|
|
97
|
-
"login_server": "https://softmax.com/api",
|
|
98
96
|
}
|
|
99
97
|
|
|
100
98
|
|
|
@@ -103,10 +101,9 @@ def test_softmax_cogames_login_returns_player_token(monkeypatch: pytest.MonkeyPa
|
|
|
103
101
|
token = "player-token"
|
|
104
102
|
|
|
105
103
|
class FakeClient:
|
|
106
|
-
def __init__(self, *, server_url: str, token: str
|
|
104
|
+
def __init__(self, *, server_url: str, token: str) -> None:
|
|
107
105
|
self.server_url = server_url
|
|
108
106
|
self.token = token
|
|
109
|
-
self.login_server = login_server
|
|
110
107
|
|
|
111
108
|
def __enter__(self) -> "FakeClient":
|
|
112
109
|
return self
|
|
@@ -117,7 +114,6 @@ def test_softmax_cogames_login_returns_player_token(monkeypatch: pytest.MonkeyPa
|
|
|
117
114
|
def login_player(self, player_id: str) -> FakeLoginResponse:
|
|
118
115
|
assert self.server_url == "https://api.observatory.softmax-research.net"
|
|
119
116
|
assert self.token == "softmax-token"
|
|
120
|
-
assert self.login_server == "https://softmax.com/api"
|
|
121
117
|
assert player_id == "ply_alpha"
|
|
122
118
|
return FakeLoginResponse()
|
|
123
119
|
|
|
@@ -132,7 +128,7 @@ def test_softmax_cogames_login_response_returns_full_response(monkeypatch: pytes
|
|
|
132
128
|
expires_at = "2026-02-21T12:00:00Z"
|
|
133
129
|
|
|
134
130
|
class FakeClient:
|
|
135
|
-
def __init__(self, *, server_url: str, token: str
|
|
131
|
+
def __init__(self, *, server_url: str, token: str) -> None:
|
|
136
132
|
pass
|
|
137
133
|
|
|
138
134
|
def __enter__(self) -> "FakeClient":
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|