softmax-cli 0.26.10__tar.gz → 0.26.12__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 (21) hide show
  1. {softmax_cli-0.26.10/src/softmax_cli.egg-info → softmax_cli-0.26.12}/PKG-INFO +1 -1
  2. {softmax_cli-0.26.10 → softmax_cli-0.26.12}/src/softmax/__init__.py +8 -9
  3. {softmax_cli-0.26.10 → softmax_cli-0.26.12}/src/softmax/auth.py +22 -25
  4. {softmax_cli-0.26.10 → softmax_cli-0.26.12}/src/softmax/cli.py +30 -33
  5. {softmax_cli-0.26.10 → softmax_cli-0.26.12}/src/softmax/cogames.py +4 -4
  6. {softmax_cli-0.26.10 → softmax_cli-0.26.12}/src/softmax/perform_login.py +14 -13
  7. {softmax_cli-0.26.10 → softmax_cli-0.26.12}/src/softmax/token_storage.py +3 -0
  8. {softmax_cli-0.26.10 → softmax_cli-0.26.12/src/softmax_cli.egg-info}/PKG-INFO +1 -1
  9. {softmax_cli-0.26.10 → softmax_cli-0.26.12}/tests/test_auth_login.py +15 -20
  10. {softmax_cli-0.26.10 → softmax_cli-0.26.12}/tests/test_python_api.py +2 -2
  11. {softmax_cli-0.26.10 → softmax_cli-0.26.12}/BUILD.bazel +0 -0
  12. {softmax_cli-0.26.10 → softmax_cli-0.26.12}/pyproject.toml +0 -0
  13. {softmax_cli-0.26.10 → softmax_cli-0.26.12}/setup.cfg +0 -0
  14. {softmax_cli-0.26.10 → softmax_cli-0.26.12}/src/softmax/_console.py +0 -0
  15. {softmax_cli-0.26.10 → softmax_cli-0.26.12}/src/softmax_cli.egg-info/SOURCES.txt +0 -0
  16. {softmax_cli-0.26.10 → softmax_cli-0.26.12}/src/softmax_cli.egg-info/dependency_links.txt +0 -0
  17. {softmax_cli-0.26.10 → softmax_cli-0.26.12}/src/softmax_cli.egg-info/entry_points.txt +0 -0
  18. {softmax_cli-0.26.10 → softmax_cli-0.26.12}/src/softmax_cli.egg-info/requires.txt +0 -0
  19. {softmax_cli-0.26.10 → softmax_cli-0.26.12}/src/softmax_cli.egg-info/top_level.txt +0 -0
  20. {softmax_cli-0.26.10 → softmax_cli-0.26.12}/tests/BUILD.bazel +0 -0
  21. {softmax_cli-0.26.10 → softmax_cli-0.26.12}/tests/test_cli_plugins.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: softmax-cli
3
- Version: 0.26.10
3
+ Version: 0.26.12
4
4
  Summary: Softmax CLI — authentication and account tools
5
5
  Classifier: Programming Language :: Python :: 3
6
6
  Classifier: Programming Language :: Python :: 3.11
@@ -5,7 +5,7 @@ import sys
5
5
  from pkgutil import extend_path
6
6
 
7
7
  from softmax.auth import (
8
- DEFAULT_COGAMES_SERVER,
8
+ DEFAULT_API_SERVER,
9
9
  load_cogames_user_token,
10
10
  save_cogames_active_token,
11
11
  )
@@ -17,13 +17,13 @@ __path__ = extend_path(__path__, __name__)
17
17
 
18
18
  def login(
19
19
  *,
20
- login_server: str = DEFAULT_COGAMES_SERVER,
20
+ api_server: str = DEFAULT_API_SERVER,
21
21
  force: bool = False,
22
22
  open_browser: bool = True,
23
23
  ) -> str:
24
- token = None if force else load_cogames_user_token(login_server=login_server)
24
+ token = None if force else load_cogames_user_token(api_server=api_server)
25
25
  if token is not None:
26
- save_cogames_active_token(login_server=login_server, token=token)
26
+ save_cogames_active_token(api_server=api_server, token=token)
27
27
  return token
28
28
 
29
29
  if not sys.stdin.isatty():
@@ -33,8 +33,7 @@ def login(
33
33
  )
34
34
 
35
35
  do_interactive_login_for_token(
36
- login_server=login_server,
37
- server_to_save_token_under=login_server,
36
+ api_server=api_server,
38
37
  token_kind=TokenKind.COGAMES_USER,
39
38
  agent_hint=(
40
39
  "If you are a coding agent, ask your human to open the URL below and give you "
@@ -45,10 +44,10 @@ def login(
45
44
  open_browser=open_browser,
46
45
  )
47
46
 
48
- token = load_cogames_user_token(login_server=login_server)
47
+ token = load_cogames_user_token(api_server=api_server)
49
48
  if token is None:
50
- raise RuntimeError(f"Interactive login did not save a token for {login_server}")
51
- save_cogames_active_token(login_server=login_server, token=token)
49
+ raise RuntimeError(f"Interactive login did not save a token for {api_server}")
50
+ save_cogames_active_token(api_server=api_server, token=token)
52
51
  return token
53
52
 
54
53
 
@@ -13,12 +13,11 @@ from softmax.token_storage import delete_token as delete_stored_token
13
13
  from softmax.token_storage import load_token as load_saved_token
14
14
  from softmax.token_storage import save_token as save_stored_token
15
15
 
16
- DEFAULT_COGAMES_SERVER = "https://softmax.com/api"
17
- DEFAULT_COGAMES_API_SERVER = "https://api.observatory.softmax-research.net"
16
+ DEFAULT_API_SERVER = "https://softmax.com/api"
18
17
 
19
18
 
20
- def get_login_server() -> str:
21
- return os.environ.get("COGAMES_LOGIN_URL", DEFAULT_COGAMES_SERVER)
19
+ def get_api_server() -> str:
20
+ return os.environ.get("COGAMES_API_URL", DEFAULT_API_SERVER)
22
21
 
23
22
 
24
23
  class WhoAmIResponse(BaseModel):
@@ -31,14 +30,14 @@ class WhoAmIResponse(BaseModel):
31
30
  scopes: list[str] = Field(default_factory=list)
32
31
 
33
32
 
34
- def build_browser_login_url(login_server: str, *, callback_url: str | None = None) -> str:
33
+ def build_browser_login_url(api_server: str, *, callback_url: str | None = None) -> str:
35
34
  """Build the hosted browser sign-in URL for CLI login."""
36
35
  params: dict[str, str] = {}
37
36
  if callback_url:
38
37
  params["callback"] = callback_url
39
38
 
40
39
  query = urlencode(params)
41
- parsed = urlsplit(login_server)
40
+ parsed = urlsplit(api_server)
42
41
  browser_path = parsed.path.rstrip("/").removesuffix("/api") + "/cli-login"
43
42
  return urlunsplit((parsed.scheme, parsed.netloc, browser_path, query, ""))
44
43
 
@@ -59,35 +58,33 @@ def delete_token(*, token_kind: TokenKind, server: str) -> bool:
59
58
  return delete_stored_token(token_kind=token_kind, server=server)
60
59
 
61
60
 
62
- def load_cogames_user_token(*, login_server: str) -> str | None:
63
- return load_token(token_kind=TokenKind.COGAMES_USER, server=login_server)
61
+ def load_cogames_user_token(*, api_server: str) -> str | None:
62
+ return load_token(token_kind=TokenKind.COGAMES_USER, server=api_server)
64
63
 
65
64
 
66
- def load_current_cogames_token(*, login_server: str) -> str | None:
67
- return load_token(token_kind=TokenKind.COGAMES, server=login_server) or load_cogames_user_token(
68
- login_server=login_server
69
- )
65
+ def load_current_cogames_token(*, api_server: str) -> str | None:
66
+ return load_token(token_kind=TokenKind.COGAMES, server=api_server) or load_cogames_user_token(api_server=api_server)
70
67
 
71
68
 
72
- def save_cogames_active_token(*, login_server: str, token: str) -> None:
73
- save_token(token_kind=TokenKind.COGAMES, server=login_server, token=token)
69
+ def save_cogames_active_token(*, api_server: str, token: str) -> None:
70
+ save_token(token_kind=TokenKind.COGAMES, server=api_server, token=token)
74
71
 
75
72
 
76
- def save_cogames_user_token(*, login_server: str, token: str) -> None:
77
- save_token(token_kind=TokenKind.COGAMES_USER, server=login_server, token=token)
78
- save_cogames_active_token(login_server=login_server, token=token)
73
+ def save_cogames_user_token(*, api_server: str, token: str) -> None:
74
+ save_token(token_kind=TokenKind.COGAMES_USER, server=api_server, token=token)
75
+ save_cogames_active_token(api_server=api_server, token=token)
79
76
 
80
77
 
81
- def delete_cogames_tokens(*, login_server: str) -> bool:
82
- deleted_active = delete_token(token_kind=TokenKind.COGAMES, server=login_server)
83
- deleted_user = delete_token(token_kind=TokenKind.COGAMES_USER, server=login_server)
78
+ def delete_cogames_tokens(*, api_server: str) -> bool:
79
+ deleted_active = delete_token(token_kind=TokenKind.COGAMES, server=api_server)
80
+ deleted_user = delete_token(token_kind=TokenKind.COGAMES_USER, server=api_server)
84
81
  return deleted_active or deleted_user
85
82
 
86
83
 
87
84
  def fetch_cogames_whoami(*, api_server: str | None = None, token: str) -> WhoAmIResponse:
88
- server = api_server or DEFAULT_COGAMES_API_SERVER
85
+ server = api_server or DEFAULT_API_SERVER
89
86
  response = httpx.get(
90
- f"{server.rstrip('/')}/whoami",
87
+ f"{server.rstrip('/')}/observatory/whoami",
91
88
  headers={"Authorization": f"Bearer {token}"},
92
89
  timeout=10.0,
93
90
  )
@@ -95,9 +92,9 @@ def fetch_cogames_whoami(*, api_server: str | None = None, token: str) -> WhoAmI
95
92
  return WhoAmIResponse.model_validate(response.json())
96
93
 
97
94
 
98
- def restore_cogames_user_session(*, login_server: str) -> str | None:
99
- user_token = load_cogames_user_token(login_server=login_server)
95
+ def restore_cogames_user_session(*, api_server: str) -> str | None:
96
+ user_token = load_cogames_user_token(api_server=api_server)
100
97
  if user_token is None:
101
98
  return None
102
- save_cogames_active_token(login_server=login_server, token=user_token)
99
+ save_cogames_active_token(api_server=api_server, token=user_token)
103
100
  return user_token
@@ -10,11 +10,11 @@ from rich.panel import Panel
10
10
 
11
11
  from softmax._console import console
12
12
  from softmax.auth import (
13
- DEFAULT_COGAMES_SERVER,
13
+ DEFAULT_API_SERVER,
14
14
  build_browser_login_url,
15
15
  delete_cogames_tokens,
16
16
  fetch_cogames_whoami,
17
- get_login_server,
17
+ get_api_server,
18
18
  load_cogames_user_token,
19
19
  load_current_cogames_token,
20
20
  save_cogames_active_token,
@@ -47,9 +47,9 @@ def _build_manual_set_token_command(server: str | None = None) -> str:
47
47
  return "softmax set-token '<TOKEN>'"
48
48
 
49
49
 
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
50
+ def _print_non_tty_login_instructions(api_server: str | None = None) -> None:
51
+ resolved = api_server or get_api_server()
52
+ is_custom = resolved != DEFAULT_API_SERVER
53
53
  auth_url = build_browser_login_url(resolved)
54
54
  console.print("Interactive login requires a TTY.", style="red")
55
55
  console.print()
@@ -89,17 +89,15 @@ def login_cmd(
89
89
  "--server",
90
90
  "-s",
91
91
  metavar="URL",
92
- help="Authentication server URL.",
92
+ help="API server URL.",
93
93
  ),
94
94
  ) -> None:
95
95
  """Sign in to Softmax."""
96
96
  from urllib.parse import urlparse # noqa: PLC0415
97
97
 
98
- login_server = server or get_login_server()
99
- is_default_server = login_server == DEFAULT_COGAMES_SERVER
100
- user_token = None if force else load_cogames_user_token(login_server=login_server)
98
+ api_server = server or get_api_server()
99
+ user_token = None if force else load_cogames_user_token(api_server=api_server)
101
100
  if user_token is not None:
102
- api_server = None if is_default_server else login_server
103
101
  try:
104
102
  whoami = fetch_cogames_whoami(api_server=api_server, token=user_token)
105
103
  if whoami.subject_type == "anonymous":
@@ -115,18 +113,17 @@ def login_cmd(
115
113
  console.print("Could not reach server to verify token. Proceeding with saved token.", style="yellow")
116
114
 
117
115
  if user_token is not None:
118
- save_cogames_active_token(login_server=login_server, token=user_token)
119
- console.print(f"Already authenticated with {urlparse(login_server).hostname}", style="green")
116
+ save_cogames_active_token(api_server=api_server, token=user_token)
117
+ console.print(f"Already authenticated with {urlparse(api_server).hostname}", style="green")
120
118
  return
121
119
 
122
120
  if not sys.stdin.isatty():
123
- _print_non_tty_login_instructions(login_server)
121
+ _print_non_tty_login_instructions(api_server)
124
122
  raise typer.Exit(1)
125
123
 
126
124
  try:
127
125
  do_interactive_login_for_token(
128
- login_server=login_server,
129
- server_to_save_token_under=login_server,
126
+ api_server=api_server,
130
127
  token_kind=TokenKind.COGAMES_USER,
131
128
  agent_hint=(
132
129
  "If you are a coding agent, ask your human to open the URL below and give you "
@@ -142,9 +139,9 @@ def login_cmd(
142
139
  console.print("Authentication failed.", style="red")
143
140
  raise typer.Exit(1) from e
144
141
 
145
- user_token = load_cogames_user_token(login_server=login_server)
142
+ user_token = load_cogames_user_token(api_server=api_server)
146
143
  assert user_token is not None
147
- save_cogames_active_token(login_server=login_server, token=user_token)
144
+ save_cogames_active_token(api_server=api_server, token=user_token)
148
145
  console.print("Authentication successful.", style="green")
149
146
 
150
147
 
@@ -155,12 +152,12 @@ def logout_cmd(
155
152
  "--server",
156
153
  "-s",
157
154
  metavar="URL",
158
- help="Authentication server URL.",
155
+ help="API server URL.",
159
156
  ),
160
157
  ) -> None:
161
158
  """Remove saved authentication token."""
162
- login_server = server or get_login_server()
163
- if delete_cogames_tokens(login_server=login_server):
159
+ api_server = server or get_api_server()
160
+ if delete_cogames_tokens(api_server=api_server):
164
161
  console.print("Logged out.", style="green")
165
162
  else:
166
163
  console.print("No token found — already logged out.", style="yellow")
@@ -173,11 +170,11 @@ def get_login_url_cmd(
173
170
  "--server",
174
171
  "-s",
175
172
  metavar="URL",
176
- help="Authentication server URL.",
173
+ help="API server URL.",
177
174
  ),
178
175
  ) -> None:
179
176
  """Print a browser sign-in URL for manual login."""
180
- print(build_browser_login_url(server or get_login_server()))
177
+ print(build_browser_login_url(server or get_api_server()))
181
178
 
182
179
 
183
180
  @app.command(name="status")
@@ -187,17 +184,17 @@ def status_cmd(
187
184
  "--server",
188
185
  "-s",
189
186
  metavar="URL",
190
- help="Authentication server URL.",
187
+ help="API server URL.",
191
188
  ),
192
189
  ) -> None:
193
190
  """Check authentication status via /whoami."""
194
- login_server = server or get_login_server()
195
- token = load_current_cogames_token(login_server=login_server)
191
+ api_server = server or get_api_server()
192
+ token = load_current_cogames_token(api_server=api_server)
196
193
  if not token:
197
194
  console.print("[red]Not authenticated.[/red] Run [cyan]softmax login[/cyan] first.")
198
195
  raise typer.Exit(1)
199
196
 
200
- session = fetch_cogames_whoami(api_server=server, token=token)
197
+ session = fetch_cogames_whoami(api_server=api_server, token=token)
201
198
  if session.subject_type == "anonymous":
202
199
  console.print("[red]Token is invalid or expired.[/red] Run [cyan]softmax login[/cyan] to re-authenticate.")
203
200
  raise typer.Exit(1)
@@ -215,12 +212,12 @@ def get_token_cmd(
215
212
  "--server",
216
213
  "-s",
217
214
  metavar="URL",
218
- help="Authentication server URL.",
215
+ help="API server URL.",
219
216
  ),
220
217
  ) -> None:
221
218
  """Print the saved token to stdout (for scripting)."""
222
- login_server = server or get_login_server()
223
- token = load_current_cogames_token(login_server=login_server)
219
+ api_server = server or get_api_server()
220
+ token = load_current_cogames_token(api_server=api_server)
224
221
  if not token:
225
222
  console.print("[red]No token found.[/red] Run [cyan]softmax login[/cyan] first.", style="bold")
226
223
  raise typer.Exit(1)
@@ -235,13 +232,13 @@ def set_token_cmd(
235
232
  "--server",
236
233
  "-s",
237
234
  metavar="URL",
238
- help="Authentication server URL.",
235
+ help="API server URL.",
239
236
  ),
240
237
  ) -> None:
241
238
  """Manually set a token (for CI or headless environments)."""
242
- login_server = server or get_login_server()
243
- save_cogames_user_token(login_server=login_server, token=token)
244
- print(f"\nToken saved for {login_server}")
239
+ api_server = server or get_api_server()
240
+ save_cogames_user_token(api_server=api_server, token=token)
241
+ print(f"\nToken saved for {api_server}")
245
242
 
246
243
 
247
244
  _register_optional_apps()
@@ -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_API_SERVER
7
7
 
8
8
 
9
9
  def _get_tournament_client_class() -> type[Any]:
@@ -26,7 +26,7 @@ class _PlayerAPI:
26
26
  self,
27
27
  token: str,
28
28
  *,
29
- server: str = DEFAULT_COGAMES_API_SERVER,
29
+ server: str = DEFAULT_API_SERVER,
30
30
  ) -> list[Any]:
31
31
  with _create_client(token=token, server=server) as client:
32
32
  return client.list_players()
@@ -39,7 +39,7 @@ def login(
39
39
  token: str,
40
40
  player_id: str,
41
41
  *,
42
- server: str = DEFAULT_COGAMES_API_SERVER,
42
+ server: str = DEFAULT_API_SERVER,
43
43
  ) -> str:
44
44
  with _create_client(token=token, server=server) as client:
45
45
  return client.login_player(player_id).token
@@ -49,7 +49,7 @@ def login_response(
49
49
  token: str,
50
50
  player_id: str,
51
51
  *,
52
- server: str = DEFAULT_COGAMES_API_SERVER,
52
+ server: str = DEFAULT_API_SERVER,
53
53
  ) -> Any:
54
54
  with _create_client(token=token, server=server) as client:
55
55
  return client.login_player(player_id)
@@ -269,11 +269,11 @@ def _create_app(session: _CLIAuthSession) -> FastAPI:
269
269
  return app
270
270
 
271
271
 
272
- def _validate_token(*, login_server: str, token: str) -> bool | None:
273
- validate_url = f"{login_server.rstrip('/')}/validate"
272
+ def _validate_token(*, api_server: str, token: str) -> bool | None:
273
+ whoami_url = f"{api_server.rstrip('/')}/observatory/whoami"
274
274
  try:
275
275
  response = httpx.get(
276
- validate_url,
276
+ whoami_url,
277
277
  headers={"Authorization": f"Bearer {token}"},
278
278
  timeout=5.0,
279
279
  )
@@ -282,8 +282,8 @@ def _validate_token(*, login_server: str, token: str) -> bool | None:
282
282
 
283
283
  if response.status_code == 200:
284
284
  data = response.json()
285
- return bool(data.get("valid"))
286
- if response.status_code in {400, 401, 403, 404}:
285
+ return data.get("subject_type") != "anonymous"
286
+ if response.status_code in {400, 401, 403}:
287
287
  return False
288
288
  return None
289
289
 
@@ -304,7 +304,7 @@ def _print_login_instructions(*, auth_url: str, agent_hint: str | None) -> None:
304
304
  console.print()
305
305
 
306
306
 
307
- def _start_manual_token_prompt(*, session: _CLIAuthSession, login_server: str) -> None:
307
+ def _start_manual_token_prompt(*, session: _CLIAuthSession, api_server: str) -> None:
308
308
  def prompt_loop() -> None:
309
309
  while not session.auth_completed.is_set():
310
310
  try:
@@ -317,7 +317,7 @@ def _start_manual_token_prompt(*, session: _CLIAuthSession, login_server: str) -
317
317
  if not token:
318
318
  continue
319
319
 
320
- validation_result = _validate_token(login_server=login_server, token=token)
320
+ validation_result = _validate_token(api_server=api_server, token=token)
321
321
  if validation_result is False:
322
322
  console.print("Invalid token. Please try again.", style="red")
323
323
  continue
@@ -360,11 +360,11 @@ def _wait_for_callback_server_to_start(*, session: _CLIAuthSession, port: int, t
360
360
 
361
361
  def do_interactive_login_for_token(
362
362
  *,
363
- login_server: str,
364
- server_to_save_token_under: str,
363
+ api_server: str,
365
364
  token_kind: TokenKind,
366
365
  agent_hint: str | None,
367
366
  open_browser: bool,
367
+ save_token_under: str | None = None,
368
368
  ) -> None:
369
369
  """Run the CLI browser login flow and save the resulting token."""
370
370
  assert sys.stdin.isatty(), "This function should only be called when stdin is a TTY"
@@ -378,18 +378,19 @@ def do_interactive_login_for_token(
378
378
  callback_url = f"http://127.0.0.1:{port}/callback"
379
379
  session.error = None
380
380
 
381
- auth_url = build_browser_login_url(login_server, callback_url=callback_url)
381
+ auth_url = build_browser_login_url(api_server, callback_url=callback_url)
382
382
  _print_login_instructions(auth_url=auth_url, agent_hint=agent_hint)
383
383
  if open_browser:
384
384
  _open_browser(url=auth_url)
385
385
 
386
- _start_manual_token_prompt(session=session, login_server=login_server)
386
+ _start_manual_token_prompt(session=session, api_server=api_server)
387
387
  session.auth_completed.wait()
388
388
  if session.error:
389
389
  raise RuntimeError(session.error)
390
390
  if not session.token:
391
391
  raise RuntimeError("No token received")
392
392
 
393
- save_token(token_kind=token_kind, server=server_to_save_token_under, token=session.token)
394
- print(f"\nToken saved for {server_to_save_token_under}")
393
+ token_server = save_token_under or api_server
394
+ save_token(token_kind=token_kind, server=token_server, token=session.token)
395
+ print(f"\nToken saved for {token_server}")
395
396
  print()
@@ -45,6 +45,7 @@ def _load_token_data(*, token_file_name: str) -> dict:
45
45
 
46
46
 
47
47
  def load_token(*, token_kind: TokenKind, server: str) -> str | None:
48
+ server = server.rstrip("/")
48
49
  data = _load_token_data(token_file_name=_token_file_name(token_kind=token_kind))
49
50
  assert isinstance(data, dict), "Token storage file must contain a mapping at the top level"
50
51
 
@@ -57,6 +58,7 @@ def load_token(*, token_kind: TokenKind, server: str) -> str | None:
57
58
 
58
59
 
59
60
  def save_token(*, token_kind: TokenKind, server: str, token: str) -> None:
61
+ server = server.rstrip("/")
60
62
  token_file_name = _token_file_name(token_kind=token_kind)
61
63
  token_storage_key = _token_storage_key(token_kind=token_kind)
62
64
  data = _load_token_data(token_file_name=token_file_name)
@@ -76,6 +78,7 @@ def save_token(*, token_kind: TokenKind, server: str, token: str) -> None:
76
78
 
77
79
 
78
80
  def delete_token(*, token_kind: TokenKind, server: str) -> bool:
81
+ server = server.rstrip("/")
79
82
  token_file_name = _token_file_name(token_kind=token_kind)
80
83
  token_storage_key = _token_storage_key(token_kind=token_kind)
81
84
  data = _load_token_data(token_file_name=token_file_name)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: softmax-cli
3
- Version: 0.26.10
3
+ Version: 0.26.12
4
4
  Summary: Softmax CLI — authentication and account tools
5
5
  Classifier: Programming Language :: Python :: 3
6
6
  Classifier: Programming Language :: Python :: 3.11
@@ -28,13 +28,12 @@ def test_authenticate_accepts_pasted_token(
28
28
  monkeypatch.setattr("softmax.perform_login._find_free_port", lambda: 43123)
29
29
  monkeypatch.setattr("softmax.perform_login._run_server", lambda *, session, port: None)
30
30
  monkeypatch.setattr("softmax.perform_login._wait_for_callback_server_to_start", lambda *, session, port: False)
31
- monkeypatch.setattr("softmax.perform_login._validate_token", lambda *, login_server, token: True)
31
+ monkeypatch.setattr("softmax.perform_login._validate_token", lambda *, api_server, token: True)
32
32
  monkeypatch.setattr(sys.stdin, "isatty", lambda: True)
33
33
  monkeypatch.setattr(builtins, "input", lambda _prompt="": "manual-token-123")
34
34
 
35
35
  do_interactive_login_for_token(
36
- login_server="https://softmax.com/api",
37
- server_to_save_token_under="https://softmax.com/api",
36
+ api_server="https://softmax.com/api",
38
37
  token_kind=TokenKind.COGAMES,
39
38
  agent_hint=COGAMES_AGENT_HINT,
40
39
  open_browser=False,
@@ -63,12 +62,11 @@ def test_authenticate_skips_browser_when_requested(
63
62
  )
64
63
  monkeypatch.setattr(
65
64
  "softmax.perform_login._start_manual_token_prompt",
66
- lambda *, session, login_server: auth_module._finish_authentication(session, token="manual-token-456"),
65
+ lambda *, session, api_server: auth_module._finish_authentication(session, token="manual-token-456"),
67
66
  )
68
67
 
69
68
  do_interactive_login_for_token(
70
- login_server="https://softmax.com/api",
71
- server_to_save_token_under="https://softmax.com/api",
69
+ api_server="https://softmax.com/api",
72
70
  token_kind=TokenKind.COGAMES,
73
71
  agent_hint=COGAMES_AGENT_HINT,
74
72
  open_browser=False,
@@ -100,12 +98,11 @@ def test_authenticate_falls_back_to_manual_when_callback_server_fails(
100
98
  )
101
99
  monkeypatch.setattr(
102
100
  "softmax.perform_login._start_manual_token_prompt",
103
- lambda *, session, login_server: auth_module._finish_authentication(session, token="manual-token-789"),
101
+ lambda *, session, api_server: auth_module._finish_authentication(session, token="manual-token-789"),
104
102
  )
105
103
 
106
104
  do_interactive_login_for_token(
107
- login_server="https://softmax.com/api",
108
- server_to_save_token_under="https://softmax.com/api",
105
+ api_server="https://softmax.com/api",
109
106
  token_kind=TokenKind.COGAMES,
110
107
  agent_hint=COGAMES_AGENT_HINT,
111
108
  open_browser=True,
@@ -132,12 +129,11 @@ def test_authenticate_reprompts_after_invalid_token(
132
129
  validation_results = iter([False, True])
133
130
  monkeypatch.setattr(
134
131
  "softmax.perform_login._validate_token",
135
- lambda *, login_server, token: next(validation_results),
132
+ lambda *, api_server, token: next(validation_results),
136
133
  )
137
134
 
138
135
  do_interactive_login_for_token(
139
- login_server="https://softmax.com/api",
140
- server_to_save_token_under="https://softmax.com/api",
136
+ api_server="https://softmax.com/api",
141
137
  token_kind=TokenKind.COGAMES,
142
138
  agent_hint=COGAMES_AGENT_HINT,
143
139
  open_browser=False,
@@ -166,15 +162,15 @@ def test_generic_authenticator_does_not_print_cogames_agent_hint(
166
162
  monkeypatch.setattr("softmax.perform_login._run_server", lambda *, session, port: None)
167
163
  monkeypatch.setattr(
168
164
  "softmax.perform_login._start_manual_token_prompt",
169
- lambda *, session, login_server: auth_module._finish_authentication(session, token="manual-token-000"),
165
+ lambda *, session, api_server: auth_module._finish_authentication(session, token="manual-token-000"),
170
166
  )
171
167
 
172
168
  do_interactive_login_for_token(
173
- login_server="https://softmax.com/api",
174
- server_to_save_token_under="token-key",
169
+ api_server="https://softmax.com/api",
175
170
  token_kind=TokenKind.OBSERVATORY,
176
171
  agent_hint=None,
177
172
  open_browser=False,
173
+ save_token_under="token-key",
178
174
  )
179
175
  output = capsys.readouterr().out
180
176
  assert "Open this URL in any browser to sign in:" in output
@@ -193,15 +189,15 @@ def test_generic_authenticator_works_without_agent_hint(
193
189
  monkeypatch.setattr("softmax.perform_login._run_server", lambda *, session, port: None)
194
190
  monkeypatch.setattr(
195
191
  "softmax.perform_login._start_manual_token_prompt",
196
- lambda *, session, login_server: auth_module._finish_authentication(session, token="manual-token-001"),
192
+ lambda *, session, api_server: auth_module._finish_authentication(session, token="manual-token-001"),
197
193
  )
198
194
 
199
195
  do_interactive_login_for_token(
200
- login_server="https://softmax.com/api",
201
- server_to_save_token_under="token-key",
196
+ api_server="https://softmax.com/api",
202
197
  token_kind=TokenKind.OBSERVATORY,
203
198
  agent_hint=None,
204
199
  open_browser=False,
200
+ save_token_under="token-key",
205
201
  )
206
202
 
207
203
 
@@ -254,8 +250,7 @@ def test_interactive_login_requires_tty(
254
250
 
255
251
  with pytest.raises(AssertionError, match="only be called when stdin is a TTY"):
256
252
  do_interactive_login_for_token(
257
- login_server="https://softmax.com/api",
258
- server_to_save_token_under="https://softmax.com/api",
253
+ api_server="https://softmax.com/api",
259
254
  token_kind=TokenKind.COGAMES,
260
255
  agent_hint=COGAMES_AGENT_HINT,
261
256
  open_browser=False,
@@ -91,7 +91,7 @@ def test_softmax_cogames_player_list_uses_expected_defaults(monkeypatch: pytest.
91
91
 
92
92
  assert cast(Any, softmax).cogames.player.list("softmax-token") == ["alpha", "beta"]
93
93
  assert captured == {
94
- "server_url": "https://api.observatory.softmax-research.net",
94
+ "server_url": "https://softmax.com/api",
95
95
  "token": "softmax-token",
96
96
  }
97
97
 
@@ -112,7 +112,7 @@ def test_softmax_cogames_login_returns_player_token(monkeypatch: pytest.MonkeyPa
112
112
  return None
113
113
 
114
114
  def login_player(self, player_id: str) -> FakeLoginResponse:
115
- assert self.server_url == "https://api.observatory.softmax-research.net"
115
+ assert self.server_url == "https://softmax.com/api"
116
116
  assert self.token == "softmax-token"
117
117
  assert player_id == "ply_alpha"
118
118
  return FakeLoginResponse()
File without changes
File without changes