sweatstack-cli 0.4.1__tar.gz → 0.6.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 (45) hide show
  1. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/PKG-INFO +3 -3
  2. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/pyproject.toml +3 -3
  3. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/src/sweatstack_cli/__init__.py +1 -1
  4. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/src/sweatstack_cli/commands/app.py +82 -5
  5. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/src/sweatstack_cli/commands/auth.py +1 -1
  6. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/src/sweatstack_cli/commands/page.py +31 -11
  7. sweatstack_cli-0.6.0/src/sweatstack_cli/project.py +111 -0
  8. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/src/sweatstack_cli/version_check.py +2 -2
  9. sweatstack_cli-0.6.0/sweatstack.toml +3 -0
  10. sweatstack_cli-0.6.0/tests/test_project.py +110 -0
  11. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/tests/test_version_check.py +1 -1
  12. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/uv.lock +2 -102
  13. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/.claude/settings.local.json +0 -0
  14. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/.gitignore +0 -0
  15. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/.python-version +0 -0
  16. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/CREATE_PRIVATE_APP.md +0 -0
  17. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/DEVELOPMENT.md +0 -0
  18. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/Makefile +0 -0
  19. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/PLAN.md +0 -0
  20. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/README.md +0 -0
  21. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/src/sweatstack_cli/api/__init__.py +0 -0
  22. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/src/sweatstack_cli/api/client.py +0 -0
  23. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/src/sweatstack_cli/auth/__init__.py +0 -0
  24. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/src/sweatstack_cli/auth/callback_server.py +0 -0
  25. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/src/sweatstack_cli/auth/jwt.py +0 -0
  26. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/src/sweatstack_cli/auth/pkce.py +0 -0
  27. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/src/sweatstack_cli/auth/tokens.py +0 -0
  28. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/src/sweatstack_cli/commands/__init__.py +0 -0
  29. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/src/sweatstack_cli/config.py +0 -0
  30. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/src/sweatstack_cli/console.py +0 -0
  31. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/src/sweatstack_cli/exceptions.py +0 -0
  32. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/src/sweatstack_cli/main.py +0 -0
  33. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/src/sweatstack_cli/py.typed +0 -0
  34. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/tests/__init__.py +0 -0
  35. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/tests/conftest.py +0 -0
  36. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/tests/test_api/__init__.py +0 -0
  37. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/tests/test_api/test_client.py +0 -0
  38. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/tests/test_auth/__init__.py +0 -0
  39. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/tests/test_auth/test_callback_server.py +0 -0
  40. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/tests/test_auth/test_jwt.py +0 -0
  41. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/tests/test_auth/test_pkce.py +0 -0
  42. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/tests/test_auth/test_tokens.py +0 -0
  43. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/tests/test_commands/__init__.py +0 -0
  44. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/tests/test_commands/test_app.py +0 -0
  45. {sweatstack_cli-0.4.1 → sweatstack_cli-0.6.0}/tests/test_commands/test_cli.py +0 -0
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sweatstack-cli
3
- Version: 0.4.1
3
+ Version: 0.6.0
4
4
  Summary: Command-line interface for SweatStack — the sports data platform for developers
5
5
  Project-URL: Homepage, https://sweatstack.no
6
6
  Project-URL: Documentation, https://docs.sweatstack.no
7
7
  Project-URL: Repository, https://github.com/sweatstack/sweatstack-cli
8
- Author-email: Aart Goossens <aart@goossens.me>
8
+ Author-email: Aart Goossens <aart@sweatstack.no>
9
9
  License: MIT
10
10
  Keywords: api,cli,fitness,sports,sweatstack
11
11
  Classifier: Development Status :: 3 - Alpha
@@ -16,7 +16,7 @@ Classifier: Operating System :: OS Independent
16
16
  Classifier: Programming Language :: Python :: 3.13
17
17
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
18
  Classifier: Typing :: Typed
19
- Requires-Python: >=3.10
19
+ Requires-Python: >=3.11
20
20
  Requires-Dist: httpx>=0.28.0
21
21
  Requires-Dist: platformdirs>=4.0
22
22
  Requires-Dist: typer>=0.15.0
@@ -1,10 +1,10 @@
1
1
  [project]
2
2
  name = "sweatstack-cli"
3
- version = "0.4.1"
3
+ version = "0.6.0"
4
4
  description = "Command-line interface for SweatStack — the sports data platform for developers"
5
5
  readme = "README.md"
6
- authors = [{ name = "Aart Goossens", email = "aart@goossens.me" }]
7
- requires-python = ">=3.10"
6
+ authors = [{ name = "Aart Goossens", email = "aart@sweatstack.no" }]
7
+ requires-python = ">=3.11"
8
8
  license = { text = "MIT" }
9
9
  keywords = ["sweatstack", "cli", "sports", "fitness", "api"]
10
10
  classifiers = [
@@ -1,3 +1,3 @@
1
1
  """SweatStack CLI — Command-line interface for the SweatStack platform."""
2
2
 
3
- __version__ = "0.4.1"
3
+ __version__ = "0.6.0"
@@ -4,12 +4,14 @@ from __future__ import annotations
4
4
 
5
5
  import json as json_lib
6
6
  from pathlib import Path
7
+ from typing import Any, cast
7
8
 
8
9
  import typer
9
10
 
10
11
  from sweatstack_cli.api import APIClient
11
12
  from sweatstack_cli.console import console, stderr_console
12
13
  from sweatstack_cli.exceptions import APIError, AuthenticationError
14
+ from sweatstack_cli.project import CONFIG_FILENAME, write_config
13
15
 
14
16
  app = typer.Typer(name="app", help="Manage OAuth2 applications.")
15
17
 
@@ -75,13 +77,20 @@ def create(
75
77
  if env_path:
76
78
  _write_env_file(env_path, result)
77
79
 
80
+ # Write sweatstack.toml
81
+ config_path = write_config(
82
+ app_name=result["name"],
83
+ client_id=result["client_id"],
84
+ page_slug=page,
85
+ )
86
+
78
87
  if json_output:
79
88
  console.print(json_lib.dumps(result, indent=2))
80
89
  else:
81
- _print_app_created(result, env_path)
90
+ _print_app_created(result, env_path, config_path)
82
91
 
83
92
 
84
- def _write_env_file(path: Path, result: dict) -> None:
93
+ def _write_env_file(path: Path, result: dict[str, str]) -> None:
85
94
  """Append credentials to an env file."""
86
95
  lines_to_add: list[str] = []
87
96
  existing_content = ""
@@ -116,7 +125,7 @@ def _write_env_file(path: Path, result: dict) -> None:
116
125
  f.write("\n".join(lines_to_add) + "\n")
117
126
 
118
127
 
119
- def _print_app_created(result: dict, env_path: Path | None) -> None:
128
+ def _print_app_created(result: dict[str, str], env_path: Path | None, config_path: Path) -> None:
120
129
  """Pretty-print the created application details."""
121
130
  console.print(f"[green]✓[/green] Created application [bold]{result['name']}[/bold]")
122
131
  console.print()
@@ -131,9 +140,77 @@ def _print_app_created(result: dict, env_path: Path | None) -> None:
131
140
  for uri in result["redirect_uris"]:
132
141
  console.print(f" - {uri}")
133
142
 
143
+ console.print()
144
+ console.print(f"[green]✓[/green] Config written to [bold]{config_path}[/bold]")
145
+
134
146
  if env_path:
135
- console.print()
136
147
  console.print(f"[green]✓[/green] Credentials written to [bold]{env_path}[/bold]")
137
- elif "client_secret" in result:
148
+
149
+ if "client_secret" in result and not env_path:
138
150
  console.print()
139
151
  console.print("[yellow]Save the secret now — it won't be shown again.[/yellow]")
152
+
153
+
154
+ @app.command()
155
+ def link(
156
+ force: bool = typer.Option(
157
+ False,
158
+ "--force",
159
+ "-f",
160
+ help="Overwrite existing sweatstack.toml.",
161
+ ),
162
+ ) -> None:
163
+ """Link this directory to an existing application."""
164
+ config_path = Path(CONFIG_FILENAME)
165
+
166
+ # Check if config already exists
167
+ if config_path.exists() and not force:
168
+ console.print(f"[yellow]Already linked.[/yellow] {CONFIG_FILENAME} exists.")
169
+ console.print("Use [cyan]--force[/cyan] to overwrite.")
170
+ raise typer.Exit(1)
171
+
172
+ # Fetch user's apps
173
+ try:
174
+ client = APIClient()
175
+ except AuthenticationError as e:
176
+ console.print(f"[red]Error:[/red] {e}")
177
+ console.print("[dim]Run 'sweatstack login' to authenticate.[/dim]")
178
+ raise typer.Exit(2)
179
+
180
+ try:
181
+ # API returns a list, but client.get is typed as returning dict
182
+ apps = cast(list[dict[str, Any]], client.get("/api/v1/applications"))
183
+ except APIError as e:
184
+ console.print(f"[red]Error:[/red] {e}")
185
+ raise typer.Exit(3)
186
+
187
+ if not apps:
188
+ console.print("[yellow]No applications found.[/yellow]")
189
+ console.print("Create one with [cyan]sweatstack app create <name>[/cyan]")
190
+ raise typer.Exit(1)
191
+
192
+ # Show apps and let user select
193
+ console.print("Link this directory to an existing application.\n")
194
+ console.print("Your applications:")
195
+ for i, app_info in enumerate(apps, 1):
196
+ page_info = f" [dim](page: {app_info['page_slug']})[/dim]" if app_info.get("page_slug") else ""
197
+ console.print(f" [cyan][{i}][/cyan] {app_info['name']}{page_info}")
198
+
199
+ console.print()
200
+ selection = typer.prompt("Select application", type=int)
201
+
202
+ if selection < 1 or selection > len(apps):
203
+ console.print("[red]Invalid selection.[/red]")
204
+ raise typer.Exit(1)
205
+
206
+ selected = apps[selection - 1]
207
+
208
+ # Write config
209
+ write_config(
210
+ app_name=selected["name"],
211
+ client_id=selected["id"],
212
+ page_slug=selected.get("page_slug"),
213
+ )
214
+
215
+ console.print()
216
+ console.print(f"[green]✓[/green] Linked to [bold]{selected['name']}[/bold]")
@@ -87,7 +87,7 @@ def status() -> None:
87
87
  if update_available and latest:
88
88
  console.print(
89
89
  f"[yellow]⚠[/yellow] Update available: {latest} (current: {__version__})\n"
90
- f" Run: [cyan]pip install --upgrade sweatstack-cli[/cyan]"
90
+ f" Run: [cyan]uv tool upgrade sweatstack-cli[/cyan] [dim](or pip/pipx)[/dim]"
91
91
  )
92
92
  elif latest:
93
93
  console.print(f"[green]✓[/green] Up to date ({__version__})")
@@ -11,6 +11,7 @@ from rich.progress import Progress, SpinnerColumn, TextColumn
11
11
  from sweatstack_cli.api import APIClient
12
12
  from sweatstack_cli.console import console
13
13
  from sweatstack_cli.exceptions import APIError, AuthenticationError
14
+ from sweatstack_cli.project import CONFIG_FILENAME, ProjectConfig
14
15
 
15
16
  # URL where users can create pages for their applications
16
17
  SETTINGS_URL = "https://app.sweatstack.no/settings/api"
@@ -53,21 +54,40 @@ def _collect_files(directory: Path) -> list[tuple[str, tuple[str, bytes, str]]]:
53
54
 
54
55
  @app.command()
55
56
  def deploy(
56
- slug: str = typer.Argument(
57
- ...,
58
- help="Page slug (must be created first at app.sweatstack.no).",
57
+ slug: str | None = typer.Argument(
58
+ None,
59
+ help="Page slug. Reads from sweatstack.toml if not provided.",
59
60
  ),
60
- directory: Path = typer.Argument(
61
- ".",
62
- help="Directory containing static files to deploy.",
63
- exists=True,
64
- file_okay=False,
65
- dir_okay=True,
66
- resolve_path=True,
61
+ directory: Path | None = typer.Argument(
62
+ None,
63
+ help="Directory to deploy. Reads from sweatstack.toml or defaults to current dir.",
67
64
  ),
68
65
  ) -> None:
69
66
  """Deploy a static site to SweatStack Pages."""
70
- page_slug = slug
67
+ # Load config for defaults
68
+ config = ProjectConfig.load()
69
+
70
+ # Resolve slug
71
+ page_slug = slug or (config.page.slug if config else None)
72
+ if not page_slug:
73
+ console.print("[red]Error:[/red] No page slug provided.")
74
+ console.print(f"Specify a slug or add it to [bold]{CONFIG_FILENAME}[/bold]")
75
+ raise typer.Exit(1)
76
+
77
+ # Resolve directory
78
+ if directory is None:
79
+ dir_from_config = config.page.directory if config else None
80
+ directory = Path(dir_from_config) if dir_from_config else Path(".")
81
+
82
+ if not directory.exists():
83
+ console.print(f"[red]Error:[/red] Directory '{directory}' does not exist.")
84
+ raise typer.Exit(1)
85
+
86
+ if not directory.is_dir():
87
+ console.print(f"[red]Error:[/red] '{directory}' is not a directory.")
88
+ raise typer.Exit(1)
89
+
90
+ directory = directory.resolve()
71
91
 
72
92
  # Collect files
73
93
  files = _collect_files(directory)
@@ -0,0 +1,111 @@
1
+ """Project configuration via sweatstack.toml."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import tomllib
6
+ from dataclasses import dataclass
7
+ from pathlib import Path
8
+
9
+ CONFIG_FILENAME = "sweatstack.toml"
10
+
11
+
12
+ @dataclass
13
+ class PageConfig:
14
+ """Page configuration."""
15
+
16
+ slug: str | None = None
17
+ directory: str | None = None
18
+
19
+
20
+ @dataclass
21
+ class AppConfig:
22
+ """Application configuration."""
23
+
24
+ name: str | None = None
25
+ client_id: str | None = None
26
+
27
+
28
+ @dataclass
29
+ class ProjectConfig:
30
+ """Project configuration from sweatstack.toml."""
31
+
32
+ app: AppConfig
33
+ page: PageConfig
34
+
35
+ @classmethod
36
+ def load(cls, path: Path | None = None) -> ProjectConfig | None:
37
+ """
38
+ Load config from sweatstack.toml in current directory.
39
+
40
+ Args:
41
+ path: Optional path to config file. Defaults to ./sweatstack.toml.
42
+
43
+ Returns:
44
+ ProjectConfig if file exists and is valid, None otherwise.
45
+ """
46
+ config_path = path or Path(CONFIG_FILENAME)
47
+
48
+ if not config_path.exists():
49
+ return None
50
+
51
+ try:
52
+ data = tomllib.loads(config_path.read_text(encoding="utf-8"))
53
+ except tomllib.TOMLDecodeError:
54
+ return None
55
+
56
+ app_data = data.get("app", {})
57
+ page_data = data.get("page", {})
58
+
59
+ return cls(
60
+ app=AppConfig(
61
+ name=app_data.get("name"),
62
+ client_id=app_data.get("client_id"),
63
+ ),
64
+ page=PageConfig(
65
+ slug=page_data.get("slug"),
66
+ directory=page_data.get("directory"),
67
+ ),
68
+ )
69
+
70
+
71
+ def write_config(
72
+ path: Path | None = None,
73
+ *,
74
+ app_name: str | None = None,
75
+ client_id: str | None = None,
76
+ page_slug: str | None = None,
77
+ page_directory: str | None = None,
78
+ ) -> Path:
79
+ """
80
+ Write sweatstack.toml file.
81
+
82
+ Args:
83
+ path: Optional path to config file. Defaults to ./sweatstack.toml.
84
+ app_name: Application name.
85
+ client_id: OAuth2 client ID.
86
+ page_slug: Page slug.
87
+ page_directory: Page directory.
88
+
89
+ Returns:
90
+ Path to the written config file.
91
+ """
92
+ config_path = path or Path(CONFIG_FILENAME)
93
+
94
+ lines = ["[app]"]
95
+ if app_name:
96
+ lines.append(f'name = "{app_name}"')
97
+ if client_id:
98
+ lines.append(f'client_id = "{client_id}"')
99
+
100
+ if page_slug or page_directory:
101
+ lines.append("")
102
+ lines.append("[page]")
103
+ if page_slug:
104
+ lines.append(f'slug = "{page_slug}"')
105
+ if page_directory:
106
+ lines.append(f'directory = "{page_directory}"')
107
+
108
+ lines.append("") # Trailing newline
109
+ config_path.write_text("\n".join(lines), encoding="utf-8")
110
+
111
+ return config_path
@@ -70,6 +70,6 @@ def get_update_message() -> str | None:
70
70
  return None
71
71
 
72
72
  return (
73
- f"A new version of sweatstack-cli is available: {latest} (current: {__version__})\n"
74
- f"Update with: [cyan]pip install --upgrade sweatstack-cli[/cyan]"
73
+ f"Update available: {latest} (current: {__version__})\n"
74
+ f"Run: [cyan]uv tool upgrade sweatstack-cli[/cyan] [dim](or pip/pipx)[/dim]"
75
75
  )
@@ -0,0 +1,3 @@
1
+ [app]
2
+ name = "Test App"
3
+ client_id = "abc123"
@@ -0,0 +1,110 @@
1
+ """Tests for project configuration."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+
7
+ from sweatstack_cli.project import ProjectConfig, write_config
8
+
9
+
10
+ class TestWriteConfig:
11
+ """Tests for write_config function."""
12
+
13
+ def test_writes_app_only(self, tmp_path: Path) -> None:
14
+ """Should write config with app section only."""
15
+ config_path = tmp_path / "sweatstack.toml"
16
+
17
+ write_config(
18
+ path=config_path,
19
+ app_name="My App",
20
+ client_id="abc123",
21
+ )
22
+
23
+ content = config_path.read_text()
24
+ assert '[app]' in content
25
+ assert 'name = "My App"' in content
26
+ assert 'client_id = "abc123"' in content
27
+ assert '[page]' not in content
28
+
29
+ def test_writes_app_and_page(self, tmp_path: Path) -> None:
30
+ """Should write config with both sections."""
31
+ config_path = tmp_path / "sweatstack.toml"
32
+
33
+ write_config(
34
+ path=config_path,
35
+ app_name="My App",
36
+ client_id="abc123",
37
+ page_slug="my-page",
38
+ page_directory="dist",
39
+ )
40
+
41
+ content = config_path.read_text()
42
+ assert '[app]' in content
43
+ assert '[page]' in content
44
+ assert 'slug = "my-page"' in content
45
+ assert 'directory = "dist"' in content
46
+
47
+ def test_returns_path(self, tmp_path: Path) -> None:
48
+ """Should return the path to the config file."""
49
+ config_path = tmp_path / "sweatstack.toml"
50
+
51
+ result = write_config(path=config_path, app_name="Test")
52
+
53
+ assert result == config_path
54
+
55
+
56
+ class TestProjectConfigLoad:
57
+ """Tests for ProjectConfig.load method."""
58
+
59
+ def test_loads_full_config(self, tmp_path: Path) -> None:
60
+ """Should load all fields from config file."""
61
+ config_path = tmp_path / "sweatstack.toml"
62
+ config_path.write_text('''
63
+ [app]
64
+ name = "My App"
65
+ client_id = "abc123"
66
+
67
+ [page]
68
+ slug = "my-page"
69
+ directory = "dist"
70
+ ''')
71
+
72
+ config = ProjectConfig.load(config_path)
73
+
74
+ assert config is not None
75
+ assert config.app.name == "My App"
76
+ assert config.app.client_id == "abc123"
77
+ assert config.page.slug == "my-page"
78
+ assert config.page.directory == "dist"
79
+
80
+ def test_loads_partial_config(self, tmp_path: Path) -> None:
81
+ """Should handle missing optional fields."""
82
+ config_path = tmp_path / "sweatstack.toml"
83
+ config_path.write_text('''
84
+ [app]
85
+ client_id = "abc123"
86
+ ''')
87
+
88
+ config = ProjectConfig.load(config_path)
89
+
90
+ assert config is not None
91
+ assert config.app.name is None
92
+ assert config.app.client_id == "abc123"
93
+ assert config.page.slug is None
94
+
95
+ def test_returns_none_for_missing_file(self, tmp_path: Path) -> None:
96
+ """Should return None if file doesn't exist."""
97
+ config_path = tmp_path / "nonexistent.toml"
98
+
99
+ config = ProjectConfig.load(config_path)
100
+
101
+ assert config is None
102
+
103
+ def test_returns_none_for_invalid_toml(self, tmp_path: Path) -> None:
104
+ """Should return None for invalid TOML."""
105
+ config_path = tmp_path / "sweatstack.toml"
106
+ config_path.write_text("not valid toml [[[")
107
+
108
+ config = ProjectConfig.load(config_path)
109
+
110
+ assert config is None
@@ -103,7 +103,7 @@ class TestGetUpdateMessage:
103
103
 
104
104
  assert msg is not None
105
105
  assert "99.0.0" in msg
106
- assert "pip install --upgrade sweatstack-cli" in msg
106
+ assert "sweatstack-cli" in msg
107
107
 
108
108
  def test_returns_none_when_up_to_date(self, httpx_mock: HTTPXMock) -> None:
109
109
  """Should return None when on latest version."""
@@ -1,6 +1,6 @@
1
1
  version = 1
2
2
  revision = 3
3
- requires-python = ">=3.10"
3
+ requires-python = ">=3.11"
4
4
 
5
5
  [[package]]
6
6
  name = "annotated-doc"
@@ -16,7 +16,6 @@ name = "anyio"
16
16
  version = "4.12.1"
17
17
  source = { registry = "https://pypi.org/simple" }
18
18
  dependencies = [
19
- { name = "exceptiongroup", marker = "python_full_version < '3.11'" },
20
19
  { name = "idna" },
21
20
  { name = "typing-extensions", marker = "python_full_version < '3.13'" },
22
21
  ]
@@ -61,20 +60,6 @@ version = "7.13.4"
61
60
  source = { registry = "https://pypi.org/simple" }
62
61
  sdist = { url = "https://files.pythonhosted.org/packages/24/56/95b7e30fa389756cb56630faa728da46a27b8c6eb46f9d557c68fff12b65/coverage-7.13.4.tar.gz", hash = "sha256:e5c8f6ed1e61a8b2dcdf31eb0b9bbf0130750ca79c1c49eb898e2ad86f5ccc91", size = 827239, upload-time = "2026-02-09T12:59:03.86Z" }
63
62
  wheels = [
64
- { url = "https://files.pythonhosted.org/packages/44/d4/7827d9ffa34d5d4d752eec907022aa417120936282fc488306f5da08c292/coverage-7.13.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0fc31c787a84f8cd6027eba44010517020e0d18487064cd3d8968941856d1415", size = 219152, upload-time = "2026-02-09T12:56:11.974Z" },
65
- { url = "https://files.pythonhosted.org/packages/35/b0/d69df26607c64043292644dbb9dc54b0856fabaa2cbb1eeee3331cc9e280/coverage-7.13.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a32ebc02a1805adf637fc8dec324b5cdacd2e493515424f70ee33799573d661b", size = 219667, upload-time = "2026-02-09T12:56:13.33Z" },
66
- { url = "https://files.pythonhosted.org/packages/82/a4/c1523f7c9e47b2271dbf8c2a097e7a1f89ef0d66f5840bb59b7e8814157b/coverage-7.13.4-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e24f9156097ff9dc286f2f913df3a7f63c0e333dcafa3c196f2c18b4175ca09a", size = 246425, upload-time = "2026-02-09T12:56:14.552Z" },
67
- { url = "https://files.pythonhosted.org/packages/f8/02/aa7ec01d1a5023c4b680ab7257f9bfde9defe8fdddfe40be096ac19e8177/coverage-7.13.4-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8041b6c5bfdc03257666e9881d33b1abc88daccaf73f7b6340fb7946655cd10f", size = 248229, upload-time = "2026-02-09T12:56:16.31Z" },
68
- { url = "https://files.pythonhosted.org/packages/35/98/85aba0aed5126d896162087ef3f0e789a225697245256fc6181b95f47207/coverage-7.13.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2a09cfa6a5862bc2fc6ca7c3def5b2926194a56b8ab78ffcf617d28911123012", size = 250106, upload-time = "2026-02-09T12:56:18.024Z" },
69
- { url = "https://files.pythonhosted.org/packages/96/72/1db59bd67494bc162e3e4cd5fbc7edba2c7026b22f7c8ef1496d58c2b94c/coverage-7.13.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:296f8b0af861d3970c2a4d8c91d48eb4dd4771bcef9baedec6a9b515d7de3def", size = 252021, upload-time = "2026-02-09T12:56:19.272Z" },
70
- { url = "https://files.pythonhosted.org/packages/9d/97/72899c59c7066961de6e3daa142d459d47d104956db43e057e034f015c8a/coverage-7.13.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e101609bcbbfb04605ea1027b10dc3735c094d12d40826a60f897b98b1c30256", size = 247114, upload-time = "2026-02-09T12:56:21.051Z" },
71
- { url = "https://files.pythonhosted.org/packages/39/1f/f1885573b5970235e908da4389176936c8933e86cb316b9620aab1585fa2/coverage-7.13.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:aa3feb8db2e87ff5e6d00d7e1480ae241876286691265657b500886c98f38bda", size = 248143, upload-time = "2026-02-09T12:56:22.585Z" },
72
- { url = "https://files.pythonhosted.org/packages/a8/cf/e80390c5b7480b722fa3e994f8202807799b85bc562aa4f1dde209fbb7be/coverage-7.13.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:4fc7fa81bbaf5a02801b65346c8b3e657f1d93763e58c0abdf7c992addd81a92", size = 246152, upload-time = "2026-02-09T12:56:23.748Z" },
73
- { url = "https://files.pythonhosted.org/packages/44/bf/f89a8350d85572f95412debb0fb9bb4795b1d5b5232bd652923c759e787b/coverage-7.13.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:33901f604424145c6e9c2398684b92e176c0b12df77d52db81c20abd48c3794c", size = 249959, upload-time = "2026-02-09T12:56:25.209Z" },
74
- { url = "https://files.pythonhosted.org/packages/f7/6e/612a02aece8178c818df273e8d1642190c4875402ca2ba74514394b27aba/coverage-7.13.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:bb28c0f2cf2782508a40cec377935829d5fcc3ad9a3681375af4e84eb34b6b58", size = 246416, upload-time = "2026-02-09T12:56:26.475Z" },
75
- { url = "https://files.pythonhosted.org/packages/cb/98/b5afc39af67c2fa6786b03c3a7091fc300947387ce8914b096db8a73d67a/coverage-7.13.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9d107aff57a83222ddbd8d9ee705ede2af2cc926608b57abed8ef96b50b7e8f9", size = 247025, upload-time = "2026-02-09T12:56:27.727Z" },
76
- { url = "https://files.pythonhosted.org/packages/51/30/2bba8ef0682d5bd210c38fe497e12a06c9f8d663f7025e9f5c2c31ce847d/coverage-7.13.4-cp310-cp310-win32.whl", hash = "sha256:a6f94a7d00eb18f1b6d403c91a88fd58cfc92d4b16080dfdb774afc8294469bf", size = 221758, upload-time = "2026-02-09T12:56:29.051Z" },
77
- { url = "https://files.pythonhosted.org/packages/78/13/331f94934cf6c092b8ea59ff868eb587bc8fe0893f02c55bc6c0183a192e/coverage-7.13.4-cp310-cp310-win_amd64.whl", hash = "sha256:2cb0f1e000ebc419632bbe04366a8990b6e32c4e0b51543a6484ffe15eaeda95", size = 222693, upload-time = "2026-02-09T12:56:30.366Z" },
78
63
  { url = "https://files.pythonhosted.org/packages/b4/ad/b59e5b451cf7172b8d1043dc0fa718f23aab379bc1521ee13d4bd9bfa960/coverage-7.13.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d490ba50c3f35dd7c17953c68f3270e7ccd1c6642e2d2afe2d8e720b98f5a053", size = 219278, upload-time = "2026-02-09T12:56:31.673Z" },
79
64
  { url = "https://files.pythonhosted.org/packages/f1/17/0cb7ca3de72e5f4ef2ec2fa0089beafbcaaaead1844e8b8a63d35173d77d/coverage-7.13.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:19bc3c88078789f8ef36acb014d7241961dbf883fd2533d18cb1e7a5b4e28b11", size = 219783, upload-time = "2026-02-09T12:56:33.104Z" },
80
65
  { url = "https://files.pythonhosted.org/packages/ab/63/325d8e5b11e0eaf6d0f6a44fad444ae58820929a9b0de943fa377fe73e85/coverage-7.13.4-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3998e5a32e62fdf410c0dbd3115df86297995d6e3429af80b8798aad894ca7aa", size = 250200, upload-time = "2026-02-09T12:56:34.474Z" },
@@ -168,18 +153,6 @@ wheels = [
168
153
  { url = "https://files.pythonhosted.org/packages/0d/4a/331fe2caf6799d591109bb9c08083080f6de90a823695d412a935622abb2/coverage-7.13.4-py3-none-any.whl", hash = "sha256:1af1641e57cf7ba1bd67d677c9abdbcd6cc2ab7da3bca7fa1e2b7e50e65f2ad0", size = 211242, upload-time = "2026-02-09T12:59:02.032Z" },
169
154
  ]
170
155
 
171
- [[package]]
172
- name = "exceptiongroup"
173
- version = "1.3.1"
174
- source = { registry = "https://pypi.org/simple" }
175
- dependencies = [
176
- { name = "typing-extensions", marker = "python_full_version < '3.13'" },
177
- ]
178
- sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
179
- wheels = [
180
- { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
181
- ]
182
-
183
156
  [[package]]
184
157
  name = "h11"
185
158
  version = "0.16.0"
@@ -241,16 +214,6 @@ version = "0.7.8"
241
214
  source = { registry = "https://pypi.org/simple" }
242
215
  sdist = { url = "https://files.pythonhosted.org/packages/e7/24/5f3646ff414285e0f7708fa4e946b9bf538345a41d1c375c439467721a5e/librt-0.7.8.tar.gz", hash = "sha256:1a4ede613941d9c3470b0368be851df6bb78ab218635512d0370b27a277a0862", size = 148323, upload-time = "2026-01-14T12:56:16.876Z" }
243
216
  wheels = [
244
- { url = "https://files.pythonhosted.org/packages/44/13/57b06758a13550c5f09563893b004f98e9537ee6ec67b7df85c3571c8832/librt-0.7.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b45306a1fc5f53c9330fbee134d8b3227fe5da2ab09813b892790400aa49352d", size = 56521, upload-time = "2026-01-14T12:54:40.066Z" },
245
- { url = "https://files.pythonhosted.org/packages/c2/24/bbea34d1452a10612fb45ac8356f95351ba40c2517e429602160a49d1fd0/librt-0.7.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:864c4b7083eeee250ed55135d2127b260d7eb4b5e953a9e5df09c852e327961b", size = 58456, upload-time = "2026-01-14T12:54:41.471Z" },
246
- { url = "https://files.pythonhosted.org/packages/04/72/a168808f92253ec3a810beb1eceebc465701197dbc7e865a1c9ceb3c22c7/librt-0.7.8-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6938cc2de153bc927ed8d71c7d2f2ae01b4e96359126c602721340eb7ce1a92d", size = 164392, upload-time = "2026-01-14T12:54:42.843Z" },
247
- { url = "https://files.pythonhosted.org/packages/14/5c/4c0d406f1b02735c2e7af8ff1ff03a6577b1369b91aa934a9fa2cc42c7ce/librt-0.7.8-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:66daa6ac5de4288a5bbfbe55b4caa7bf0cd26b3269c7a476ffe8ce45f837f87d", size = 172959, upload-time = "2026-01-14T12:54:44.602Z" },
248
- { url = "https://files.pythonhosted.org/packages/82/5f/3e85351c523f73ad8d938989e9a58c7f59fb9c17f761b9981b43f0025ce7/librt-0.7.8-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4864045f49dc9c974dadb942ac56a74cd0479a2aafa51ce272c490a82322ea3c", size = 186717, upload-time = "2026-01-14T12:54:45.986Z" },
249
- { url = "https://files.pythonhosted.org/packages/08/f8/18bfe092e402d00fe00d33aa1e01dda1bd583ca100b393b4373847eade6d/librt-0.7.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a36515b1328dc5b3ffce79fe204985ca8572525452eacabee2166f44bb387b2c", size = 184585, upload-time = "2026-01-14T12:54:47.139Z" },
250
- { url = "https://files.pythonhosted.org/packages/4e/fc/f43972ff56fd790a9fa55028a52ccea1875100edbb856b705bd393b601e3/librt-0.7.8-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b7e7f140c5169798f90b80d6e607ed2ba5059784968a004107c88ad61fb3641d", size = 180497, upload-time = "2026-01-14T12:54:48.946Z" },
251
- { url = "https://files.pythonhosted.org/packages/e1/3a/25e36030315a410d3ad0b7d0f19f5f188e88d1613d7d3fd8150523ea1093/librt-0.7.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ff71447cb778a4f772ddc4ce360e6ba9c95527ed84a52096bd1bbf9fee2ec7c0", size = 200052, upload-time = "2026-01-14T12:54:50.382Z" },
252
- { url = "https://files.pythonhosted.org/packages/fc/b8/f3a5a1931ae2a6ad92bf6893b9ef44325b88641d58723529e2c2935e8abe/librt-0.7.8-cp310-cp310-win32.whl", hash = "sha256:047164e5f68b7a8ebdf9fae91a3c2161d3192418aadd61ddd3a86a56cbe3dc85", size = 43477, upload-time = "2026-01-14T12:54:51.815Z" },
253
- { url = "https://files.pythonhosted.org/packages/fe/91/c4202779366bc19f871b4ad25db10fcfa1e313c7893feb942f32668e8597/librt-0.7.8-cp310-cp310-win_amd64.whl", hash = "sha256:d6f254d096d84156a46a84861183c183d30734e52383602443292644d895047c", size = 49806, upload-time = "2026-01-14T12:54:53.149Z" },
254
217
  { url = "https://files.pythonhosted.org/packages/1b/a3/87ea9c1049f2c781177496ebee29430e4631f439b8553a4969c88747d5d8/librt-0.7.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ff3e9c11aa260c31493d4b3197d1e28dd07768594a4f92bec4506849d736248f", size = 56507, upload-time = "2026-01-14T12:54:54.156Z" },
255
218
  { url = "https://files.pythonhosted.org/packages/5e/4a/23bcef149f37f771ad30203d561fcfd45b02bc54947b91f7a9ac34815747/librt-0.7.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ddb52499d0b3ed4aa88746aaf6f36a08314677d5c346234c3987ddc506404eac", size = 58455, upload-time = "2026-01-14T12:54:55.978Z" },
256
219
  { url = "https://files.pythonhosted.org/packages/22/6e/46eb9b85c1b9761e0f42b6e6311e1cc544843ac897457062b9d5d0b21df4/librt-0.7.8-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e9c0afebbe6ce177ae8edba0c7c4d626f2a0fc12c33bb993d163817c41a7a05c", size = 164956, upload-time = "2026-01-14T12:54:57.311Z" },
@@ -337,17 +300,10 @@ dependencies = [
337
300
  { name = "librt", marker = "platform_python_implementation != 'PyPy'" },
338
301
  { name = "mypy-extensions" },
339
302
  { name = "pathspec" },
340
- { name = "tomli", marker = "python_full_version < '3.11'" },
341
303
  { name = "typing-extensions" },
342
304
  ]
343
305
  sdist = { url = "https://files.pythonhosted.org/packages/f5/db/4efed9504bc01309ab9c2da7e352cc223569f05478012b5d9ece38fd44d2/mypy-1.19.1.tar.gz", hash = "sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba", size = 3582404, upload-time = "2025-12-15T05:03:48.42Z" }
344
306
  wheels = [
345
- { url = "https://files.pythonhosted.org/packages/2f/63/e499890d8e39b1ff2df4c0c6ce5d371b6844ee22b8250687a99fd2f657a8/mypy-1.19.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec", size = 13101333, upload-time = "2025-12-15T05:03:03.28Z" },
346
- { url = "https://files.pythonhosted.org/packages/72/4b/095626fc136fba96effc4fd4a82b41d688ab92124f8c4f7564bffe5cf1b0/mypy-1.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b", size = 12164102, upload-time = "2025-12-15T05:02:33.611Z" },
347
- { url = "https://files.pythonhosted.org/packages/0c/5b/952928dd081bf88a83a5ccd49aaecfcd18fd0d2710c7ff07b8fb6f7032b9/mypy-1.19.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6", size = 12765799, upload-time = "2025-12-15T05:03:28.44Z" },
348
- { url = "https://files.pythonhosted.org/packages/2a/0d/93c2e4a287f74ef11a66fb6d49c7a9f05e47b0a4399040e6719b57f500d2/mypy-1.19.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74", size = 13522149, upload-time = "2025-12-15T05:02:36.011Z" },
349
- { url = "https://files.pythonhosted.org/packages/7b/0e/33a294b56aaad2b338d203e3a1d8b453637ac36cb278b45005e0901cf148/mypy-1.19.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1", size = 13810105, upload-time = "2025-12-15T05:02:40.327Z" },
350
- { url = "https://files.pythonhosted.org/packages/0e/fd/3e82603a0cb66b67c5e7abababce6bf1a929ddf67bf445e652684af5c5a0/mypy-1.19.1-cp310-cp310-win_amd64.whl", hash = "sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac", size = 10057200, upload-time = "2025-12-15T05:02:51.012Z" },
351
307
  { url = "https://files.pythonhosted.org/packages/ef/47/6b3ebabd5474d9cdc170d1342fbf9dddc1b0ec13ec90bf9004ee6f391c31/mypy-1.19.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288", size = 13028539, upload-time = "2025-12-15T05:03:44.129Z" },
352
308
  { url = "https://files.pythonhosted.org/packages/5c/a6/ac7c7a88a3c9c54334f53a941b765e6ec6c4ebd65d3fe8cdcfbe0d0fd7db/mypy-1.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab", size = 12083163, upload-time = "2025-12-15T05:03:37.679Z" },
353
309
  { url = "https://files.pythonhosted.org/packages/67/af/3afa9cf880aa4a2c803798ac24f1d11ef72a0c8079689fac5cfd815e2830/mypy-1.19.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6", size = 12687629, upload-time = "2025-12-15T05:02:31.526Z" },
@@ -435,12 +391,10 @@ version = "9.0.2"
435
391
  source = { registry = "https://pypi.org/simple" }
436
392
  dependencies = [
437
393
  { name = "colorama", marker = "sys_platform == 'win32'" },
438
- { name = "exceptiongroup", marker = "python_full_version < '3.11'" },
439
394
  { name = "iniconfig" },
440
395
  { name = "packaging" },
441
396
  { name = "pluggy" },
442
397
  { name = "pygments" },
443
- { name = "tomli", marker = "python_full_version < '3.11'" },
444
398
  ]
445
399
  sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" }
446
400
  wheels = [
@@ -509,7 +463,7 @@ wheels = [
509
463
 
510
464
  [[package]]
511
465
  name = "sweatstack-cli"
512
- version = "0.4.1"
466
+ version = "0.5.0"
513
467
  source = { editable = "." }
514
468
  dependencies = [
515
469
  { name = "httpx" },
@@ -539,60 +493,6 @@ requires-dist = [
539
493
  ]
540
494
  provides-extras = ["dev"]
541
495
 
542
- [[package]]
543
- name = "tomli"
544
- version = "2.4.0"
545
- source = { registry = "https://pypi.org/simple" }
546
- sdist = { url = "https://files.pythonhosted.org/packages/82/30/31573e9457673ab10aa432461bee537ce6cef177667deca369efb79df071/tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c", size = 17477, upload-time = "2026-01-11T11:22:38.165Z" }
547
- wheels = [
548
- { url = "https://files.pythonhosted.org/packages/3c/d9/3dc2289e1f3b32eb19b9785b6a006b28ee99acb37d1d47f78d4c10e28bf8/tomli-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867", size = 153663, upload-time = "2026-01-11T11:21:45.27Z" },
549
- { url = "https://files.pythonhosted.org/packages/51/32/ef9f6845e6b9ca392cd3f64f9ec185cc6f09f0a2df3db08cbe8809d1d435/tomli-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9", size = 148469, upload-time = "2026-01-11T11:21:46.873Z" },
550
- { url = "https://files.pythonhosted.org/packages/d6/c2/506e44cce89a8b1b1e047d64bd495c22c9f71f21e05f380f1a950dd9c217/tomli-2.4.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95", size = 236039, upload-time = "2026-01-11T11:21:48.503Z" },
551
- { url = "https://files.pythonhosted.org/packages/b3/40/e1b65986dbc861b7e986e8ec394598187fa8aee85b1650b01dd925ca0be8/tomli-2.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76", size = 243007, upload-time = "2026-01-11T11:21:49.456Z" },
552
- { url = "https://files.pythonhosted.org/packages/9c/6f/6e39ce66b58a5b7ae572a0f4352ff40c71e8573633deda43f6a379d56b3e/tomli-2.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d", size = 240875, upload-time = "2026-01-11T11:21:50.755Z" },
553
- { url = "https://files.pythonhosted.org/packages/aa/ad/cb089cb190487caa80204d503c7fd0f4d443f90b95cf4ef5cf5aa0f439b0/tomli-2.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576", size = 246271, upload-time = "2026-01-11T11:21:51.81Z" },
554
- { url = "https://files.pythonhosted.org/packages/0b/63/69125220e47fd7a3a27fd0de0c6398c89432fec41bc739823bcc66506af6/tomli-2.4.0-cp311-cp311-win32.whl", hash = "sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a", size = 96770, upload-time = "2026-01-11T11:21:52.647Z" },
555
- { url = "https://files.pythonhosted.org/packages/1e/0d/a22bb6c83f83386b0008425a6cd1fa1c14b5f3dd4bad05e98cf3dbbf4a64/tomli-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa", size = 107626, upload-time = "2026-01-11T11:21:53.459Z" },
556
- { url = "https://files.pythonhosted.org/packages/2f/6d/77be674a3485e75cacbf2ddba2b146911477bd887dda9d8c9dfb2f15e871/tomli-2.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614", size = 94842, upload-time = "2026-01-11T11:21:54.831Z" },
557
- { url = "https://files.pythonhosted.org/packages/3c/43/7389a1869f2f26dba52404e1ef13b4784b6b37dac93bac53457e3ff24ca3/tomli-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1", size = 154894, upload-time = "2026-01-11T11:21:56.07Z" },
558
- { url = "https://files.pythonhosted.org/packages/e9/05/2f9bf110b5294132b2edf13fe6ca6ae456204f3d749f623307cbb7a946f2/tomli-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8", size = 149053, upload-time = "2026-01-11T11:21:57.467Z" },
559
- { url = "https://files.pythonhosted.org/packages/e8/41/1eda3ca1abc6f6154a8db4d714a4d35c4ad90adc0bcf700657291593fbf3/tomli-2.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a", size = 243481, upload-time = "2026-01-11T11:21:58.661Z" },
560
- { url = "https://files.pythonhosted.org/packages/d2/6d/02ff5ab6c8868b41e7d4b987ce2b5f6a51d3335a70aa144edd999e055a01/tomli-2.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1", size = 251720, upload-time = "2026-01-11T11:22:00.178Z" },
561
- { url = "https://files.pythonhosted.org/packages/7b/57/0405c59a909c45d5b6f146107c6d997825aa87568b042042f7a9c0afed34/tomli-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b", size = 247014, upload-time = "2026-01-11T11:22:01.238Z" },
562
- { url = "https://files.pythonhosted.org/packages/2c/0e/2e37568edd944b4165735687cbaf2fe3648129e440c26d02223672ee0630/tomli-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51", size = 251820, upload-time = "2026-01-11T11:22:02.727Z" },
563
- { url = "https://files.pythonhosted.org/packages/5a/1c/ee3b707fdac82aeeb92d1a113f803cf6d0f37bdca0849cb489553e1f417a/tomli-2.4.0-cp312-cp312-win32.whl", hash = "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729", size = 97712, upload-time = "2026-01-11T11:22:03.777Z" },
564
- { url = "https://files.pythonhosted.org/packages/69/13/c07a9177d0b3bab7913299b9278845fc6eaaca14a02667c6be0b0a2270c8/tomli-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da", size = 108296, upload-time = "2026-01-11T11:22:04.86Z" },
565
- { url = "https://files.pythonhosted.org/packages/18/27/e267a60bbeeee343bcc279bb9e8fbed0cbe224bc7b2a3dc2975f22809a09/tomli-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3", size = 94553, upload-time = "2026-01-11T11:22:05.854Z" },
566
- { url = "https://files.pythonhosted.org/packages/34/91/7f65f9809f2936e1f4ce6268ae1903074563603b2a2bd969ebbda802744f/tomli-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0", size = 154915, upload-time = "2026-01-11T11:22:06.703Z" },
567
- { url = "https://files.pythonhosted.org/packages/20/aa/64dd73a5a849c2e8f216b755599c511badde80e91e9bc2271baa7b2cdbb1/tomli-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e", size = 149038, upload-time = "2026-01-11T11:22:07.56Z" },
568
- { url = "https://files.pythonhosted.org/packages/9e/8a/6d38870bd3d52c8d1505ce054469a73f73a0fe62c0eaf5dddf61447e32fa/tomli-2.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4", size = 242245, upload-time = "2026-01-11T11:22:08.344Z" },
569
- { url = "https://files.pythonhosted.org/packages/59/bb/8002fadefb64ab2669e5b977df3f5e444febea60e717e755b38bb7c41029/tomli-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e", size = 250335, upload-time = "2026-01-11T11:22:09.951Z" },
570
- { url = "https://files.pythonhosted.org/packages/a5/3d/4cdb6f791682b2ea916af2de96121b3cb1284d7c203d97d92d6003e91c8d/tomli-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c", size = 245962, upload-time = "2026-01-11T11:22:11.27Z" },
571
- { url = "https://files.pythonhosted.org/packages/f2/4a/5f25789f9a460bd858ba9756ff52d0830d825b458e13f754952dd15fb7bb/tomli-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f", size = 250396, upload-time = "2026-01-11T11:22:12.325Z" },
572
- { url = "https://files.pythonhosted.org/packages/aa/2f/b73a36fea58dfa08e8b3a268750e6853a6aac2a349241a905ebd86f3047a/tomli-2.4.0-cp313-cp313-win32.whl", hash = "sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86", size = 97530, upload-time = "2026-01-11T11:22:13.865Z" },
573
- { url = "https://files.pythonhosted.org/packages/3b/af/ca18c134b5d75de7e8dc551c5234eaba2e8e951f6b30139599b53de9c187/tomli-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87", size = 108227, upload-time = "2026-01-11T11:22:15.224Z" },
574
- { url = "https://files.pythonhosted.org/packages/22/c3/b386b832f209fee8073c8138ec50f27b4460db2fdae9ffe022df89a57f9b/tomli-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132", size = 94748, upload-time = "2026-01-11T11:22:16.009Z" },
575
- { url = "https://files.pythonhosted.org/packages/f3/c4/84047a97eb1004418bc10bdbcfebda209fca6338002eba2dc27cc6d13563/tomli-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6", size = 154725, upload-time = "2026-01-11T11:22:17.269Z" },
576
- { url = "https://files.pythonhosted.org/packages/a8/5d/d39038e646060b9d76274078cddf146ced86dc2b9e8bbf737ad5983609a0/tomli-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc", size = 148901, upload-time = "2026-01-11T11:22:18.287Z" },
577
- { url = "https://files.pythonhosted.org/packages/73/e5/383be1724cb30f4ce44983d249645684a48c435e1cd4f8b5cded8a816d3c/tomli-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66", size = 243375, upload-time = "2026-01-11T11:22:19.154Z" },
578
- { url = "https://files.pythonhosted.org/packages/31/f0/bea80c17971c8d16d3cc109dc3585b0f2ce1036b5f4a8a183789023574f2/tomli-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d", size = 250639, upload-time = "2026-01-11T11:22:20.168Z" },
579
- { url = "https://files.pythonhosted.org/packages/2c/8f/2853c36abbb7608e3f945d8a74e32ed3a74ee3a1f468f1ffc7d1cb3abba6/tomli-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702", size = 246897, upload-time = "2026-01-11T11:22:21.544Z" },
580
- { url = "https://files.pythonhosted.org/packages/49/f0/6c05e3196ed5337b9fe7ea003e95fd3819a840b7a0f2bf5a408ef1dad8ed/tomli-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8", size = 254697, upload-time = "2026-01-11T11:22:23.058Z" },
581
- { url = "https://files.pythonhosted.org/packages/f3/f5/2922ef29c9f2951883525def7429967fc4d8208494e5ab524234f06b688b/tomli-2.4.0-cp314-cp314-win32.whl", hash = "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776", size = 98567, upload-time = "2026-01-11T11:22:24.033Z" },
582
- { url = "https://files.pythonhosted.org/packages/7b/31/22b52e2e06dd2a5fdbc3ee73226d763b184ff21fc24e20316a44ccc4d96b/tomli-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475", size = 108556, upload-time = "2026-01-11T11:22:25.378Z" },
583
- { url = "https://files.pythonhosted.org/packages/48/3d/5058dff3255a3d01b705413f64f4306a141a8fd7a251e5a495e3f192a998/tomli-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2", size = 96014, upload-time = "2026-01-11T11:22:26.138Z" },
584
- { url = "https://files.pythonhosted.org/packages/b8/4e/75dab8586e268424202d3a1997ef6014919c941b50642a1682df43204c22/tomli-2.4.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9", size = 163339, upload-time = "2026-01-11T11:22:27.143Z" },
585
- { url = "https://files.pythonhosted.org/packages/06/e3/b904d9ab1016829a776d97f163f183a48be6a4deb87304d1e0116a349519/tomli-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0", size = 159490, upload-time = "2026-01-11T11:22:28.399Z" },
586
- { url = "https://files.pythonhosted.org/packages/e3/5a/fc3622c8b1ad823e8ea98a35e3c632ee316d48f66f80f9708ceb4f2a0322/tomli-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df", size = 269398, upload-time = "2026-01-11T11:22:29.345Z" },
587
- { url = "https://files.pythonhosted.org/packages/fd/33/62bd6152c8bdd4c305ad9faca48f51d3acb2df1f8791b1477d46ff86e7f8/tomli-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d", size = 276515, upload-time = "2026-01-11T11:22:30.327Z" },
588
- { url = "https://files.pythonhosted.org/packages/4b/ff/ae53619499f5235ee4211e62a8d7982ba9e439a0fb4f2f351a93d67c1dd2/tomli-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f", size = 273806, upload-time = "2026-01-11T11:22:32.56Z" },
589
- { url = "https://files.pythonhosted.org/packages/47/71/cbca7787fa68d4d0a9f7072821980b39fbb1b6faeb5f5cf02f4a5559fa28/tomli-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b", size = 281340, upload-time = "2026-01-11T11:22:33.505Z" },
590
- { url = "https://files.pythonhosted.org/packages/f5/00/d595c120963ad42474cf6ee7771ad0d0e8a49d0f01e29576ee9195d9ecdf/tomli-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087", size = 108106, upload-time = "2026-01-11T11:22:34.451Z" },
591
- { url = "https://files.pythonhosted.org/packages/de/69/9aa0c6a505c2f80e519b43764f8b4ba93b5a0bbd2d9a9de6e2b24271b9a5/tomli-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd", size = 120504, upload-time = "2026-01-11T11:22:35.764Z" },
592
- { url = "https://files.pythonhosted.org/packages/b3/9f/f1668c281c58cfae01482f7114a4b88d345e4c140386241a1a24dcc9e7bc/tomli-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4", size = 99561, upload-time = "2026-01-11T11:22:36.624Z" },
593
- { url = "https://files.pythonhosted.org/packages/23/d1/136eb2cb77520a31e1f64cbae9d33ec6df0d78bdf4160398e86eec8a8754/tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a", size = 14477, upload-time = "2026-01-11T11:22:37.446Z" },
594
- ]
595
-
596
496
  [[package]]
597
497
  name = "typer"
598
498
  version = "0.21.2"
File without changes
File without changes
File without changes