overkill 0.4.1__tar.gz → 0.5.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 (86) hide show
  1. {overkill-0.4.1 → overkill-0.5.0}/.github/workflows/test.yml +1 -1
  2. {overkill-0.4.1 → overkill-0.5.0}/PKG-INFO +4 -3
  3. {overkill-0.4.1 → overkill-0.5.0}/README.md +1 -1
  4. {overkill-0.4.1 → overkill-0.5.0}/prompts/active/claude-review.prompt.md +2 -0
  5. {overkill-0.4.1 → overkill-0.5.0}/prompts/active/codex-review.prompt.md +2 -0
  6. {overkill-0.4.1 → overkill-0.5.0}/prompts/active/gemini-review.prompt.md +2 -0
  7. {overkill-0.4.1 → overkill-0.5.0}/pyproject.toml +5 -4
  8. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/agents.py +10 -0
  9. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/cli.py +17 -2
  10. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/loop_engine.py +1 -0
  11. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/models.py +14 -4
  12. {overkill-0.4.1 → overkill-0.5.0}/uv.lock +96 -3
  13. {overkill-0.4.1 → overkill-0.5.0}/.github/workflows/publish.yml +0 -0
  14. {overkill-0.4.1 → overkill-0.5.0}/.gitignore +0 -0
  15. {overkill-0.4.1 → overkill-0.5.0}/.overkillrc.example +0 -0
  16. {overkill-0.4.1 → overkill-0.5.0}/.python-version +0 -0
  17. {overkill-0.4.1 → overkill-0.5.0}/.refactorsuggestrc.example +0 -0
  18. {overkill-0.4.1 → overkill-0.5.0}/AGENTS.md +0 -0
  19. {overkill-0.4.1 → overkill-0.5.0}/CLAUDE.md +0 -0
  20. {overkill-0.4.1 → overkill-0.5.0}/GEMINI.md +0 -0
  21. {overkill-0.4.1 → overkill-0.5.0}/LICENSE +0 -0
  22. {overkill-0.4.1 → overkill-0.5.0}/install.sh +0 -0
  23. {overkill-0.4.1 → overkill-0.5.0}/prompts/active/claude-fix-execute.prompt.md +0 -0
  24. {overkill-0.4.1 → overkill-0.5.0}/prompts/active/claude-fix.prompt.md +0 -0
  25. {overkill-0.4.1 → overkill-0.5.0}/prompts/active/claude-refactor-fix-execute.prompt.md +0 -0
  26. {overkill-0.4.1 → overkill-0.5.0}/prompts/active/claude-refactor-fix.prompt.md +0 -0
  27. {overkill-0.4.1 → overkill-0.5.0}/prompts/active/claude-refactor-full.prompt.md +0 -0
  28. {overkill-0.4.1 → overkill-0.5.0}/prompts/active/claude-refactor-layer.prompt.md +0 -0
  29. {overkill-0.4.1 → overkill-0.5.0}/prompts/active/claude-refactor-micro.prompt.md +0 -0
  30. {overkill-0.4.1 → overkill-0.5.0}/prompts/active/claude-refactor-module.prompt.md +0 -0
  31. {overkill-0.4.1 → overkill-0.5.0}/prompts/active/claude-self-review.prompt.md +0 -0
  32. {overkill-0.4.1 → overkill-0.5.0}/prompts/active/codex-refactor-full.prompt.md +0 -0
  33. {overkill-0.4.1 → overkill-0.5.0}/prompts/active/codex-refactor-layer.prompt.md +0 -0
  34. {overkill-0.4.1 → overkill-0.5.0}/prompts/active/codex-refactor-micro.prompt.md +0 -0
  35. {overkill-0.4.1 → overkill-0.5.0}/prompts/active/codex-refactor-module.prompt.md +0 -0
  36. {overkill-0.4.1 → overkill-0.5.0}/prompts/active/gemini-refactor-full.prompt.md +0 -0
  37. {overkill-0.4.1 → overkill-0.5.0}/prompts/active/gemini-refactor-layer.prompt.md +0 -0
  38. {overkill-0.4.1 → overkill-0.5.0}/prompts/active/gemini-refactor-micro.prompt.md +0 -0
  39. {overkill-0.4.1 → overkill-0.5.0}/prompts/active/gemini-refactor-module.prompt.md +0 -0
  40. {overkill-0.4.1 → overkill-0.5.0}/prompts/reference/claude-code-review-plugin.md +0 -0
  41. {overkill-0.4.1 → overkill-0.5.0}/prompts/reference/claude-security-review.md +0 -0
  42. {overkill-0.4.1 → overkill-0.5.0}/prompts/reference/codex-review-original.md +0 -0
  43. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/__init__.py +0 -0
  44. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/__main__.py +0 -0
  45. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/budget/__init__.py +0 -0
  46. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/budget/claude.py +0 -0
  47. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/budget/codex.py +0 -0
  48. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/budget/gemini.py +0 -0
  49. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/budget_report.py +0 -0
  50. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/classify.py +0 -0
  51. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/data/__init__.py +0 -0
  52. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/git_ops.py +0 -0
  53. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/init.py +0 -0
  54. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/json_extract.py +0 -0
  55. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/refactor_suggest.py +0 -0
  56. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/reporting.py +0 -0
  57. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/resume.py +0 -0
  58. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/retry.py +0 -0
  59. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/review_loop.py +0 -0
  60. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/self_review.py +0 -0
  61. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/time_utils.py +0 -0
  62. {overkill-0.4.1 → overkill-0.5.0}/src/mr_overkill/two_step_fix.py +0 -0
  63. {overkill-0.4.1 → overkill-0.5.0}/tests/__init__.py +0 -0
  64. {overkill-0.4.1 → overkill-0.5.0}/tests/conftest.py +0 -0
  65. {overkill-0.4.1 → overkill-0.5.0}/tests/test_agents.py +0 -0
  66. {overkill-0.4.1 → overkill-0.5.0}/tests/test_budget_claude.py +0 -0
  67. {overkill-0.4.1 → overkill-0.5.0}/tests/test_budget_codex.py +0 -0
  68. {overkill-0.4.1 → overkill-0.5.0}/tests/test_budget_gemini.py +0 -0
  69. {overkill-0.4.1 → overkill-0.5.0}/tests/test_budget_policy.py +0 -0
  70. {overkill-0.4.1 → overkill-0.5.0}/tests/test_budget_report.py +0 -0
  71. {overkill-0.4.1 → overkill-0.5.0}/tests/test_classify.py +0 -0
  72. {overkill-0.4.1 → overkill-0.5.0}/tests/test_cli.py +0 -0
  73. {overkill-0.4.1 → overkill-0.5.0}/tests/test_git_ops.py +0 -0
  74. {overkill-0.4.1 → overkill-0.5.0}/tests/test_init.py +0 -0
  75. {overkill-0.4.1 → overkill-0.5.0}/tests/test_integration.py +0 -0
  76. {overkill-0.4.1 → overkill-0.5.0}/tests/test_json_extract.py +0 -0
  77. {overkill-0.4.1 → overkill-0.5.0}/tests/test_loop_engine.py +0 -0
  78. {overkill-0.4.1 → overkill-0.5.0}/tests/test_refactor_suggest.py +0 -0
  79. {overkill-0.4.1 → overkill-0.5.0}/tests/test_reporting.py +0 -0
  80. {overkill-0.4.1 → overkill-0.5.0}/tests/test_resume.py +0 -0
  81. {overkill-0.4.1 → overkill-0.5.0}/tests/test_retry.py +0 -0
  82. {overkill-0.4.1 → overkill-0.5.0}/tests/test_review_loop.py +0 -0
  83. {overkill-0.4.1 → overkill-0.5.0}/tests/test_self_review.py +0 -0
  84. {overkill-0.4.1 → overkill-0.5.0}/tests/test_time_utils.py +0 -0
  85. {overkill-0.4.1 → overkill-0.5.0}/tests/test_two_step_fix.py +0 -0
  86. {overkill-0.4.1 → overkill-0.5.0}/uninstall.sh +0 -0
@@ -11,7 +11,7 @@ jobs:
11
11
  runs-on: ubuntu-latest
12
12
  strategy:
13
13
  matrix:
14
- python-version: ["3.12", "3.13"]
14
+ python-version: ["3.11", "3.12", "3.13"]
15
15
 
16
16
  steps:
17
17
  - uses: actions/checkout@v6
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: overkill
3
- Version: 0.4.1
3
+ Version: 0.5.0
4
4
  Summary: AI-powered code review loop — automates Codex review + Claude fix cycles
5
5
  Project-URL: Repository, https://github.com/modocai/mr-overkill
6
6
  Project-URL: Issues, https://github.com/modocai/mr-overkill/issues
@@ -14,10 +14,11 @@ Classifier: Intended Audience :: Developers
14
14
  Classifier: License :: OSI Approved :: MIT License
15
15
  Classifier: Operating System :: OS Independent
16
16
  Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
17
18
  Classifier: Programming Language :: Python :: 3.12
18
19
  Classifier: Programming Language :: Python :: 3.13
19
20
  Classifier: Topic :: Software Development :: Quality Assurance
20
- Requires-Python: >=3.12
21
+ Requires-Python: >=3.11
21
22
  Description-Content-Type: text/markdown
22
23
 
23
24
  # :tophat: Mr. Overkill
@@ -72,7 +73,7 @@ You need these to participate in the madness:
72
73
 
73
74
  **Runtime**:
74
75
 
75
- - [Python](https://www.python.org/) 3.12+ — for the `overkill` CLI
76
+ - [Python](https://www.python.org/) 3.11+ — for the `overkill` CLI
76
77
  - [Node.js](https://nodejs.org/) v18+ — Codex and Claude Code CLI are npm packages, so yes, you need this
77
78
  - A fast credit card — essential
78
79
 
@@ -50,7 +50,7 @@ You need these to participate in the madness:
50
50
 
51
51
  **Runtime**:
52
52
 
53
- - [Python](https://www.python.org/) 3.12+ — for the `overkill` CLI
53
+ - [Python](https://www.python.org/) 3.11+ — for the `overkill` CLI
54
54
  - [Node.js](https://nodejs.org/) v18+ — Codex and Claude Code CLI are npm packages, so yes, you need this
55
55
  - A fast credit card — essential
56
56
 
@@ -6,6 +6,8 @@ You are a code reviewer analyzing a proposed change.
6
6
  - **Target branch**: ${TARGET_BRANCH}
7
7
  - **Review iteration**: ${ITERATION}
8
8
 
9
+ ${REVIEWER_CONTEXT}
10
+
9
11
  ## Instructions
10
12
 
11
13
  Start by running the following command to get the diff:
@@ -6,6 +6,8 @@ You are a code reviewer analyzing a proposed change.
6
6
  - **Target branch**: ${TARGET_BRANCH}
7
7
  - **Review iteration**: ${ITERATION}
8
8
 
9
+ ${REVIEWER_CONTEXT}
10
+
9
11
  ## Instructions
10
12
 
11
13
  Run the following command to get the diff:
@@ -6,6 +6,8 @@ You are a code reviewer analyzing a proposed change.
6
6
  - **Target branch**: ${TARGET_BRANCH}
7
7
  - **Review iteration**: ${ITERATION}
8
8
 
9
+ ${REVIEWER_CONTEXT}
10
+
9
11
  ## Instructions
10
12
 
11
13
  Start by running the following command to get the diff:
@@ -1,10 +1,10 @@
1
1
  [project]
2
2
  name = "overkill"
3
- version = "0.4.1"
3
+ version = "0.5.0"
4
4
  description = "AI-powered code review loop — automates Codex review + Claude fix cycles"
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
7
- requires-python = ">=3.12"
7
+ requires-python = ">=3.11"
8
8
  authors = [{ name = "ModocAI" }]
9
9
  keywords = ["code-review", "refactoring", "ai", "claude", "codex", "automation"]
10
10
  classifiers = [
@@ -14,6 +14,7 @@ classifiers = [
14
14
  "License :: OSI Approved :: MIT License",
15
15
  "Operating System :: OS Independent",
16
16
  "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.11",
17
18
  "Programming Language :: Python :: 3.12",
18
19
  "Programming Language :: Python :: 3.13",
19
20
  "Topic :: Software Development :: Quality Assurance",
@@ -44,14 +45,14 @@ testpaths = ["tests"]
44
45
  pythonpath = ["src"]
45
46
 
46
47
  [tool.ruff]
47
- target-version = "py312"
48
+ target-version = "py311"
48
49
  src = ["src", "tests"]
49
50
 
50
51
  [tool.ruff.lint]
51
52
  select = ["E", "F", "I", "UP", "B", "SIM", "RUF"]
52
53
 
53
54
  [tool.mypy]
54
- python_version = "3.12"
55
+ python_version = "3.11"
55
56
  strict = true
56
57
  warn_return_any = true
57
58
  warn_unused_configs = true
@@ -38,6 +38,13 @@ from mr_overkill.two_step_fix import claude_two_step_fix
38
38
  logger = logging.getLogger(__name__)
39
39
 
40
40
 
41
+ def _format_reviewer_context(raw: str) -> str:
42
+ """Wrap non-empty reviewer context in a markdown section."""
43
+ if not raw:
44
+ return ""
45
+ return f"## Author Context\n\n{raw}"
46
+
47
+
41
48
  # ── Budget / retry helpers (moved from review_loop.py) ───────────────
42
49
 
43
50
 
@@ -167,6 +174,7 @@ class CodexReviewAgent(ReviewAgent):
167
174
  "CURRENT_BRANCH": config.current_branch,
168
175
  "TARGET_BRANCH": config.target_branch,
169
176
  "ITERATION": str(iteration),
177
+ "REVIEWER_CONTEXT": _format_reviewer_context(config.reviewer_context),
170
178
  })
171
179
 
172
180
  if not self._budget_fn("codex", config.budget_scope, 0):
@@ -268,6 +276,7 @@ class ClaudeReviewAgent(ReviewAgent):
268
276
  "CURRENT_BRANCH": config.current_branch,
269
277
  "TARGET_BRANCH": config.target_branch,
270
278
  "ITERATION": str(iteration),
279
+ "REVIEWER_CONTEXT": _format_reviewer_context(config.reviewer_context),
271
280
  })
272
281
 
273
282
  if not self._budget_fn("claude", config.budget_scope, 0):
@@ -365,6 +374,7 @@ class GeminiReviewAgent(ReviewAgent):
365
374
  "CURRENT_BRANCH": config.current_branch,
366
375
  "TARGET_BRANCH": config.target_branch,
367
376
  "ITERATION": str(iteration),
377
+ "REVIEWER_CONTEXT": _format_reviewer_context(config.reviewer_context),
368
378
  })
369
379
 
370
380
  if not self._budget_fn("gemini", config.budget_scope, 0):
@@ -108,13 +108,14 @@ def _load_rc_file(rc_name: str) -> dict[str, str]:
108
108
  "RETRY_INITIAL_WAIT", "BUDGET_SCOPE", "DIAGNOSTIC_LOG",
109
109
  "SCOPE", "AUTO_APPROVE", "CREATE_PR", "WITH_REVIEW",
110
110
  "REVIEW_LOOPS", "FIX_NITS", "REVIEWER_BACKEND",
111
+ "REVIEWER_CONTEXT",
111
112
  }
112
113
  boolean_keys = {
113
114
  "DRY_RUN", "AUTO_COMMIT", "DIAGNOSTIC_LOG",
114
115
  "AUTO_APPROVE", "CREATE_PR", "WITH_REVIEW", "FIX_NITS",
115
116
  }
116
117
  kv_re = re.compile(
117
- r"^\s*(\w+)=[\"']?([^\"']*)[\"']?\s*$"
118
+ r"""^\s*(\w+)=(?:"([^"]*)"|'([^']*)'|(.*?))\s*$"""
118
119
  )
119
120
  values: dict[str, str] = {}
120
121
 
@@ -124,7 +125,7 @@ def _load_rc_file(rc_name: str) -> dict[str, str]:
124
125
  continue
125
126
  m = kv_re.match(line)
126
127
  if m and m.group(1) in allowed_keys:
127
- key, val = m.group(1), m.group(2).strip()
128
+ key, val = m.group(1), (m.group(2) or m.group(3) or m.group(4) or "").strip()
128
129
  if key in boolean_keys and val.lower() not in ("true", "false"):
129
130
  msg = f"{rc_path.name}: {key} must be 'true' or 'false', got '{val}'."
130
131
  raise SystemExit(f"Error: {msg}")
@@ -299,6 +300,11 @@ def parse_review_loop_args(
299
300
  choices=["claude", "codex", "gemini"],
300
301
  help="Backend for code review (default: codex)",
301
302
  )
303
+ parser.add_argument(
304
+ "--context",
305
+ default=None,
306
+ help="Additional context for the reviewer (e.g. design intent, constraints)",
307
+ )
302
308
 
303
309
  args = parser.parse_args(argv)
304
310
 
@@ -394,6 +400,10 @@ def parse_review_loop_args(
394
400
  saved = log_dir / "reviewer-backend.txt"
395
401
  if saved.is_file():
396
402
  args.reviewer_backend = saved.read_text().strip()
403
+ if args.context is None:
404
+ saved = log_dir / "reviewer-context.txt"
405
+ if saved.is_file():
406
+ args.context = saved.read_text().strip()
397
407
 
398
408
  if max_loop is not None and max_loop < 1:
399
409
  parser.error("--max-loop must be a positive integer")
@@ -405,6 +415,10 @@ def parse_review_loop_args(
405
415
  f" got {reviewer_backend!r}"
406
416
  )
407
417
 
418
+ reviewer_context = (
419
+ args.context if args.context is not None else rc.get("REVIEWER_CONTEXT", "")
420
+ )
421
+
408
422
  return LoopConfig(
409
423
  current_branch=current_branch,
410
424
  target_branch=target,
@@ -425,6 +439,7 @@ def parse_review_loop_args(
425
439
  prompts_dir=prompts_dir,
426
440
  pr_number=pr_number,
427
441
  reviewer_backend=reviewer_backend,
442
+ reviewer_context=reviewer_context,
428
443
  )
429
444
 
430
445
 
@@ -635,6 +635,7 @@ def _save_metadata(config: LoopConfig, cwd: Path | None) -> None:
635
635
  (log_dir / "target-branch.txt").write_text(config.target_branch)
636
636
  (log_dir / "max-loop.txt").write_text(str(config.max_loop))
637
637
  (log_dir / "reviewer-backend.txt").write_text(config.reviewer_backend)
638
+ (log_dir / "reviewer-context.txt").write_text(config.reviewer_context)
638
639
  if config.scope:
639
640
  (log_dir / "scope.txt").write_text(config.scope)
640
641
 
@@ -8,7 +8,7 @@ in Wave 2 (retry, two_step_fix, loop_engine) without mutual imports.
8
8
  from __future__ import annotations
9
9
 
10
10
  from dataclasses import dataclass, field
11
- from enum import StrEnum
11
+ from enum import Enum
12
12
  from pathlib import Path
13
13
  from typing import Protocol
14
14
 
@@ -22,7 +22,14 @@ class BudgetTimeoutError(Exception):
22
22
  # ── Enums ────────────────────────────────────────────────────────────
23
23
 
24
24
 
25
- class ErrorClass(StrEnum):
25
+ class _StrEnum(str, Enum):
26
+ """Python 3.10-compatible base that preserves StrEnum value-style str()."""
27
+
28
+ def __str__(self) -> str:
29
+ return self.value
30
+
31
+
32
+ class ErrorClass(_StrEnum):
26
33
  """Classification of a CLI error for retry decisions."""
27
34
 
28
35
  TRANSIENT = "transient"
@@ -30,7 +37,7 @@ class ErrorClass(StrEnum):
30
37
  UNKNOWN = "unknown"
31
38
 
32
39
 
33
- class BudgetScope(StrEnum):
40
+ class BudgetScope(_StrEnum):
34
41
  """Granularity of a budget check — determines the usage threshold."""
35
42
 
36
43
  MICRO = "micro"
@@ -39,7 +46,7 @@ class BudgetScope(StrEnum):
39
46
  FULL = "full"
40
47
 
41
48
 
42
- class FinalStatus(StrEnum):
49
+ class FinalStatus(_StrEnum):
43
50
  """Terminal states for a review/refactor loop run."""
44
51
 
45
52
  ALL_CLEAR = "all_clear"
@@ -174,6 +181,9 @@ class LoopConfig:
174
181
  # Reviewer backend
175
182
  reviewer_backend: str = "codex" # "codex" | "claude" | "gemini"
176
183
 
184
+ # Additional context for the reviewer
185
+ reviewer_context: str = ""
186
+
177
187
  # Refactor-specific
178
188
  scope: str | None = None # micro | module | layer | full
179
189
  skip_initial_no_diff: bool = False # refactor: 1st iteration has no diff
@@ -1,6 +1,6 @@
1
1
  version = 1
2
2
  revision = 2
3
- requires-python = ">=3.12"
3
+ requires-python = ">=3.11"
4
4
 
5
5
  [[package]]
6
6
  name = "colorama"
@@ -17,6 +17,21 @@ version = "7.13.4"
17
17
  source = { registry = "https://pypi.org/simple" }
18
18
  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" }
19
19
  wheels = [
20
+ { 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" },
21
+ { 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" },
22
+ { 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" },
23
+ { url = "https://files.pythonhosted.org/packages/76/53/c16972708cbb79f2942922571a687c52bd109a7bd51175aeb7558dff2236/coverage-7.13.4-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8e264226ec98e01a8e1054314af91ee6cde0eacac4f465cc93b03dbe0bce2fd7", size = 252114, upload-time = "2026-02-09T12:56:35.749Z" },
24
+ { url = "https://files.pythonhosted.org/packages/eb/c2/7ab36d8b8cc412bec9ea2d07c83c48930eb4ba649634ba00cb7e4e0f9017/coverage-7.13.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a3aa4e7b9e416774b21797365b358a6e827ffadaaca81b69ee02946852449f00", size = 254220, upload-time = "2026-02-09T12:56:37.796Z" },
25
+ { url = "https://files.pythonhosted.org/packages/d6/4d/cf52c9a3322c89a0e6febdfbc83bb45c0ed3c64ad14081b9503adee702e7/coverage-7.13.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:71ca20079dd8f27fcf808817e281e90220475cd75115162218d0e27549f95fef", size = 256164, upload-time = "2026-02-09T12:56:39.016Z" },
26
+ { url = "https://files.pythonhosted.org/packages/78/e9/eb1dd17bd6de8289df3580e967e78294f352a5df8a57ff4671ee5fc3dcd0/coverage-7.13.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e2f25215f1a359ab17320b47bcdaca3e6e6356652e8256f2441e4ef972052903", size = 250325, upload-time = "2026-02-09T12:56:40.668Z" },
27
+ { url = "https://files.pythonhosted.org/packages/71/07/8c1542aa873728f72267c07278c5cc0ec91356daf974df21335ccdb46368/coverage-7.13.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d65b2d373032411e86960604dc4edac91fdfb5dca539461cf2cbe78327d1e64f", size = 251913, upload-time = "2026-02-09T12:56:41.97Z" },
28
+ { url = "https://files.pythonhosted.org/packages/74/d7/c62e2c5e4483a748e27868e4c32ad3daa9bdddbba58e1bc7a15e252baa74/coverage-7.13.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94eb63f9b363180aff17de3e7c8760c3ba94664ea2695c52f10111244d16a299", size = 249974, upload-time = "2026-02-09T12:56:43.323Z" },
29
+ { url = "https://files.pythonhosted.org/packages/98/9f/4c5c015a6e98ced54efd0f5cf8d31b88e5504ecb6857585fc0161bb1e600/coverage-7.13.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e856bf6616714c3a9fbc270ab54103f4e685ba236fa98c054e8f87f266c93505", size = 253741, upload-time = "2026-02-09T12:56:45.155Z" },
30
+ { url = "https://files.pythonhosted.org/packages/bd/59/0f4eef89b9f0fcd9633b5d350016f54126ab49426a70ff4c4e87446cabdc/coverage-7.13.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:65dfcbe305c3dfe658492df2d85259e0d79ead4177f9ae724b6fb245198f55d6", size = 249695, upload-time = "2026-02-09T12:56:46.636Z" },
31
+ { url = "https://files.pythonhosted.org/packages/b5/2c/b7476f938deb07166f3eb281a385c262675d688ff4659ad56c6c6b8e2e70/coverage-7.13.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b507778ae8a4c915436ed5c2e05b4a6cecfa70f734e19c22a005152a11c7b6a9", size = 250599, upload-time = "2026-02-09T12:56:48.13Z" },
32
+ { url = "https://files.pythonhosted.org/packages/b8/34/c3420709d9846ee3785b9f2831b4d94f276f38884032dca1457fa83f7476/coverage-7.13.4-cp311-cp311-win32.whl", hash = "sha256:784fc3cf8be001197b652d51d3fd259b1e2262888693a4636e18879f613a62a9", size = 221780, upload-time = "2026-02-09T12:56:50.479Z" },
33
+ { url = "https://files.pythonhosted.org/packages/61/08/3d9c8613079d2b11c185b865de9a4c1a68850cfda2b357fae365cf609f29/coverage-7.13.4-cp311-cp311-win_amd64.whl", hash = "sha256:2421d591f8ca05b308cf0092807308b2facbefe54af7c02ac22548b88b95c98f", size = 222715, upload-time = "2026-02-09T12:56:51.815Z" },
34
+ { url = "https://files.pythonhosted.org/packages/18/1a/54c3c80b2f056164cc0a6cdcb040733760c7c4be9d780fe655f356f433e4/coverage-7.13.4-cp311-cp311-win_arm64.whl", hash = "sha256:79e73a76b854d9c6088fe5d8b2ebe745f8681c55f7397c3c0a016192d681045f", size = 221385, upload-time = "2026-02-09T12:56:53.194Z" },
20
35
  { url = "https://files.pythonhosted.org/packages/d1/81/4ce2fdd909c5a0ed1f6dedb88aa57ab79b6d1fbd9b588c1ac7ef45659566/coverage-7.13.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:02231499b08dabbe2b96612993e5fc34217cdae907a51b906ac7fca8027a4459", size = 219449, upload-time = "2026-02-09T12:56:54.889Z" },
21
36
  { url = "https://files.pythonhosted.org/packages/5d/96/5238b1efc5922ddbdc9b0db9243152c09777804fb7c02ad1741eb18a11c0/coverage-7.13.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40aa8808140e55dc022b15d8aa7f651b6b3d68b365ea0398f1441e0b04d859c3", size = 219810, upload-time = "2026-02-09T12:56:56.33Z" },
22
37
  { url = "https://files.pythonhosted.org/packages/78/72/2f372b726d433c9c35e56377cf1d513b4c16fe51841060d826b95caacec1/coverage-7.13.4-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5b856a8ccf749480024ff3bd7310adaef57bf31fd17e1bfc404b7940b6986634", size = 251308, upload-time = "2026-02-09T12:56:57.858Z" },
@@ -95,6 +110,11 @@ wheels = [
95
110
  { 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" },
96
111
  ]
97
112
 
113
+ [package.optional-dependencies]
114
+ toml = [
115
+ { name = "tomli", marker = "python_full_version <= '3.11'" },
116
+ ]
117
+
98
118
  [[package]]
99
119
  name = "iniconfig"
100
120
  version = "2.3.0"
@@ -110,6 +130,19 @@ version = "0.8.1"
110
130
  source = { registry = "https://pypi.org/simple" }
111
131
  sdist = { url = "https://files.pythonhosted.org/packages/56/9c/b4b0c54d84da4a94b37bd44151e46d5e583c9534c7e02250b961b1b6d8a8/librt-0.8.1.tar.gz", hash = "sha256:be46a14693955b3bd96014ccbdb8339ee8c9346fbe11c1b78901b55125f14c73", size = 177471, upload-time = "2026-02-17T16:13:06.101Z" }
112
132
  wheels = [
133
+ { url = "https://files.pythonhosted.org/packages/1d/01/0e748af5e4fee180cf7cd12bd12b0513ad23b045dccb2a83191bde82d168/librt-0.8.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:681dc2451d6d846794a828c16c22dc452d924e9f700a485b7ecb887a30aad1fd", size = 65315, upload-time = "2026-02-17T16:11:25.152Z" },
134
+ { url = "https://files.pythonhosted.org/packages/9d/4d/7184806efda571887c798d573ca4134c80ac8642dcdd32f12c31b939c595/librt-0.8.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a3b4350b13cc0e6f5bec8fa7caf29a8fb8cdc051a3bae45cfbfd7ce64f009965", size = 68021, upload-time = "2026-02-17T16:11:26.129Z" },
135
+ { url = "https://files.pythonhosted.org/packages/ae/88/c3c52d2a5d5101f28d3dc89298444626e7874aa904eed498464c2af17627/librt-0.8.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ac1e7817fd0ed3d14fd7c5df91daed84c48e4c2a11ee99c0547f9f62fdae13da", size = 194500, upload-time = "2026-02-17T16:11:27.177Z" },
136
+ { url = "https://files.pythonhosted.org/packages/d6/5d/6fb0a25b6a8906e85b2c3b87bee1d6ed31510be7605b06772f9374ca5cb3/librt-0.8.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:747328be0c5b7075cde86a0e09d7a9196029800ba75a1689332348e998fb85c0", size = 205622, upload-time = "2026-02-17T16:11:28.242Z" },
137
+ { url = "https://files.pythonhosted.org/packages/b2/a6/8006ae81227105476a45691f5831499e4d936b1c049b0c1feb17c11b02d1/librt-0.8.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f0af2bd2bc204fa27f3d6711d0f360e6b8c684a035206257a81673ab924aa11e", size = 218304, upload-time = "2026-02-17T16:11:29.344Z" },
138
+ { url = "https://files.pythonhosted.org/packages/ee/19/60e07886ad16670aae57ef44dada41912c90906a6fe9f2b9abac21374748/librt-0.8.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d480de377f5b687b6b1bc0c0407426da556e2a757633cc7e4d2e1a057aa688f3", size = 211493, upload-time = "2026-02-17T16:11:30.445Z" },
139
+ { url = "https://files.pythonhosted.org/packages/9c/cf/f666c89d0e861d05600438213feeb818c7514d3315bae3648b1fc145d2b6/librt-0.8.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d0ee06b5b5291f609ddb37b9750985b27bc567791bc87c76a569b3feed8481ac", size = 219129, upload-time = "2026-02-17T16:11:32.021Z" },
140
+ { url = "https://files.pythonhosted.org/packages/8f/ef/f1bea01e40b4a879364c031476c82a0dc69ce068daad67ab96302fed2d45/librt-0.8.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9e2c6f77b9ad48ce5603b83b7da9ee3e36b3ab425353f695cba13200c5d96596", size = 213113, upload-time = "2026-02-17T16:11:33.192Z" },
141
+ { url = "https://files.pythonhosted.org/packages/9b/80/cdab544370cc6bc1b72ea369525f547a59e6938ef6863a11ab3cd24759af/librt-0.8.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:439352ba9373f11cb8e1933da194dcc6206daf779ff8df0ed69c5e39113e6a99", size = 212269, upload-time = "2026-02-17T16:11:34.373Z" },
142
+ { url = "https://files.pythonhosted.org/packages/9d/9c/48d6ed8dac595654f15eceab2035131c136d1ae9a1e3548e777bb6dbb95d/librt-0.8.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:82210adabbc331dbb65d7868b105185464ef13f56f7f76688565ad79f648b0fe", size = 234673, upload-time = "2026-02-17T16:11:36.063Z" },
143
+ { url = "https://files.pythonhosted.org/packages/16/01/35b68b1db517f27a01be4467593292eb5315def8900afad29fabf56304ba/librt-0.8.1-cp311-cp311-win32.whl", hash = "sha256:52c224e14614b750c0a6d97368e16804a98c684657c7518752c356834fff83bb", size = 54597, upload-time = "2026-02-17T16:11:37.544Z" },
144
+ { url = "https://files.pythonhosted.org/packages/71/02/796fe8f02822235966693f257bf2c79f40e11337337a657a8cfebba5febc/librt-0.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:c00e5c884f528c9932d278d5c9cbbea38a6b81eb62c02e06ae53751a83a4d52b", size = 61733, upload-time = "2026-02-17T16:11:38.691Z" },
145
+ { url = "https://files.pythonhosted.org/packages/28/ad/232e13d61f879a42a4e7117d65e4984bb28371a34bb6fb9ca54ec2c8f54e/librt-0.8.1-cp311-cp311-win_arm64.whl", hash = "sha256:f7cdf7f26c2286ffb02e46d7bac56c94655540b26347673bea15fa52a6af17e9", size = 52273, upload-time = "2026-02-17T16:11:40.308Z" },
113
146
  { url = "https://files.pythonhosted.org/packages/95/21/d39b0a87ac52fc98f621fb6f8060efb017a767ebbbac2f99fbcbc9ddc0d7/librt-0.8.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a28f2612ab566b17f3698b0da021ff9960610301607c9a5e8eaca62f5e1c350a", size = 66516, upload-time = "2026-02-17T16:11:41.604Z" },
114
147
  { url = "https://files.pythonhosted.org/packages/69/f1/46375e71441c43e8ae335905e069f1c54febee63a146278bcee8782c84fd/librt-0.8.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:60a78b694c9aee2a0f1aaeaa7d101cf713e92e8423a941d2897f4fa37908dab9", size = 68634, upload-time = "2026-02-17T16:11:43.268Z" },
115
148
  { url = "https://files.pythonhosted.org/packages/0a/33/c510de7f93bf1fa19e13423a606d8189a02624a800710f6e6a0a0f0784b3/librt-0.8.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:758509ea3f1eba2a57558e7e98f4659d0ea7670bff49673b0dde18a3c7e6c0eb", size = 198941, upload-time = "2026-02-17T16:11:44.28Z" },
@@ -176,6 +209,12 @@ dependencies = [
176
209
  ]
177
210
  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" }
178
211
  wheels = [
212
+ { 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" },
213
+ { 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" },
214
+ { 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" },
215
+ { url = "https://files.pythonhosted.org/packages/2d/46/20f8a7114a56484ab268b0ab372461cb3a8f7deed31ea96b83a4e4cfcfca/mypy-1.19.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331", size = 13436933, upload-time = "2025-12-15T05:03:15.606Z" },
216
+ { url = "https://files.pythonhosted.org/packages/5b/f8/33b291ea85050a21f15da910002460f1f445f8007adb29230f0adea279cb/mypy-1.19.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925", size = 13661754, upload-time = "2025-12-15T05:02:26.731Z" },
217
+ { url = "https://files.pythonhosted.org/packages/fd/a3/47cbd4e85bec4335a9cd80cf67dbc02be21b5d4c9c23ad6b95d6c5196bac/mypy-1.19.1-cp311-cp311-win_amd64.whl", hash = "sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042", size = 10055772, upload-time = "2025-12-15T05:03:26.179Z" },
179
218
  { url = "https://files.pythonhosted.org/packages/06/8a/19bfae96f6615aa8a0604915512e0289b1fad33d5909bf7244f02935d33a/mypy-1.19.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1", size = 13206053, upload-time = "2025-12-15T05:03:46.622Z" },
180
219
  { url = "https://files.pythonhosted.org/packages/a5/34/3e63879ab041602154ba2a9f99817bb0c85c4df19a23a1443c8986e4d565/mypy-1.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e", size = 12219134, upload-time = "2025-12-15T05:03:24.367Z" },
181
220
  { url = "https://files.pythonhosted.org/packages/89/cc/2db6f0e95366b630364e09845672dbee0cbf0bbe753a204b29a944967cd9/mypy-1.19.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2", size = 12731616, upload-time = "2025-12-15T05:02:44.725Z" },
@@ -208,7 +247,7 @@ wheels = [
208
247
 
209
248
  [[package]]
210
249
  name = "overkill"
211
- version = "0.3.0"
250
+ version = "0.4.1"
212
251
  source = { editable = "." }
213
252
 
214
253
  [package.dev-dependencies]
@@ -288,7 +327,7 @@ name = "pytest-cov"
288
327
  version = "7.0.0"
289
328
  source = { registry = "https://pypi.org/simple" }
290
329
  dependencies = [
291
- { name = "coverage" },
330
+ { name = "coverage", extra = ["toml"] },
292
331
  { name = "pluggy" },
293
332
  { name = "pytest" },
294
333
  ]
@@ -334,6 +373,60 @@ wheels = [
334
373
  { url = "https://files.pythonhosted.org/packages/3e/0a/9e1be9035b37448ce2e68c978f0591da94389ade5a5abafa4cf99985d1b2/ruff-0.15.4-py3-none-win_arm64.whl", hash = "sha256:60d5177e8cfc70e51b9c5fad936c634872a74209f934c1e79107d11787ad5453", size = 10966776, upload-time = "2026-02-26T20:03:56.908Z" },
335
374
  ]
336
375
 
376
+ [[package]]
377
+ name = "tomli"
378
+ version = "2.4.1"
379
+ source = { registry = "https://pypi.org/simple" }
380
+ sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" }
381
+ wheels = [
382
+ { url = "https://files.pythonhosted.org/packages/f4/11/db3d5885d8528263d8adc260bb2d28ebf1270b96e98f0e0268d32b8d9900/tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30", size = 154704, upload-time = "2026-03-25T20:21:10.473Z" },
383
+ { url = "https://files.pythonhosted.org/packages/6d/f7/675db52c7e46064a9aa928885a9b20f4124ecb9bc2e1ce74c9106648d202/tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a", size = 149454, upload-time = "2026-03-25T20:21:12.036Z" },
384
+ { url = "https://files.pythonhosted.org/packages/61/71/81c50943cf953efa35bce7646caab3cf457a7d8c030b27cfb40d7235f9ee/tomli-2.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076", size = 237561, upload-time = "2026-03-25T20:21:13.098Z" },
385
+ { url = "https://files.pythonhosted.org/packages/48/c1/f41d9cb618acccca7df82aaf682f9b49013c9397212cb9f53219e3abac37/tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9", size = 243824, upload-time = "2026-03-25T20:21:14.569Z" },
386
+ { url = "https://files.pythonhosted.org/packages/22/e4/5a816ecdd1f8ca51fb756ef684b90f2780afc52fc67f987e3c61d800a46d/tomli-2.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c", size = 242227, upload-time = "2026-03-25T20:21:15.712Z" },
387
+ { url = "https://files.pythonhosted.org/packages/6b/49/2b2a0ef529aa6eec245d25f0c703e020a73955ad7edf73e7f54ddc608aa5/tomli-2.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc", size = 247859, upload-time = "2026-03-25T20:21:17.001Z" },
388
+ { url = "https://files.pythonhosted.org/packages/83/bd/6c1a630eaca337e1e78c5903104f831bda934c426f9231429396ce3c3467/tomli-2.4.1-cp311-cp311-win32.whl", hash = "sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049", size = 97204, upload-time = "2026-03-25T20:21:18.079Z" },
389
+ { url = "https://files.pythonhosted.org/packages/42/59/71461df1a885647e10b6bb7802d0b8e66480c61f3f43079e0dcd315b3954/tomli-2.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e", size = 108084, upload-time = "2026-03-25T20:21:18.978Z" },
390
+ { url = "https://files.pythonhosted.org/packages/b8/83/dceca96142499c069475b790e7913b1044c1a4337e700751f48ed723f883/tomli-2.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece", size = 95285, upload-time = "2026-03-25T20:21:20.309Z" },
391
+ { url = "https://files.pythonhosted.org/packages/c1/ba/42f134a3fe2b370f555f44b1d72feebb94debcab01676bf918d0cb70e9aa/tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a", size = 155924, upload-time = "2026-03-25T20:21:21.626Z" },
392
+ { url = "https://files.pythonhosted.org/packages/dc/c7/62d7a17c26487ade21c5422b646110f2162f1fcc95980ef7f63e73c68f14/tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085", size = 150018, upload-time = "2026-03-25T20:21:23.002Z" },
393
+ { url = "https://files.pythonhosted.org/packages/5c/05/79d13d7c15f13bdef410bdd49a6485b1c37d28968314eabee452c22a7fda/tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9", size = 244948, upload-time = "2026-03-25T20:21:24.04Z" },
394
+ { url = "https://files.pythonhosted.org/packages/10/90/d62ce007a1c80d0b2c93e02cab211224756240884751b94ca72df8a875ca/tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5", size = 253341, upload-time = "2026-03-25T20:21:25.177Z" },
395
+ { url = "https://files.pythonhosted.org/packages/1a/7e/caf6496d60152ad4ed09282c1885cca4eea150bfd007da84aea07bcc0a3e/tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585", size = 248159, upload-time = "2026-03-25T20:21:26.364Z" },
396
+ { url = "https://files.pythonhosted.org/packages/99/e7/c6f69c3120de34bbd882c6fba7975f3d7a746e9218e56ab46a1bc4b42552/tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1", size = 253290, upload-time = "2026-03-25T20:21:27.46Z" },
397
+ { url = "https://files.pythonhosted.org/packages/d6/2f/4a3c322f22c5c66c4b836ec58211641a4067364f5dcdd7b974b4c5da300c/tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917", size = 98141, upload-time = "2026-03-25T20:21:28.492Z" },
398
+ { url = "https://files.pythonhosted.org/packages/24/22/4daacd05391b92c55759d55eaee21e1dfaea86ce5c571f10083360adf534/tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9", size = 108847, upload-time = "2026-03-25T20:21:29.386Z" },
399
+ { url = "https://files.pythonhosted.org/packages/68/fd/70e768887666ddd9e9f5d85129e84910f2db2796f9096aa02b721a53098d/tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257", size = 95088, upload-time = "2026-03-25T20:21:30.677Z" },
400
+ { url = "https://files.pythonhosted.org/packages/07/06/b823a7e818c756d9a7123ba2cda7d07bc2dd32835648d1a7b7b7a05d848d/tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54", size = 155866, upload-time = "2026-03-25T20:21:31.65Z" },
401
+ { url = "https://files.pythonhosted.org/packages/14/6f/12645cf7f08e1a20c7eb8c297c6f11d31c1b50f316a7e7e1e1de6e2e7b7e/tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a", size = 149887, upload-time = "2026-03-25T20:21:33.028Z" },
402
+ { url = "https://files.pythonhosted.org/packages/5c/e0/90637574e5e7212c09099c67ad349b04ec4d6020324539297b634a0192b0/tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897", size = 243704, upload-time = "2026-03-25T20:21:34.51Z" },
403
+ { url = "https://files.pythonhosted.org/packages/10/8f/d3ddb16c5a4befdf31a23307f72828686ab2096f068eaf56631e136c1fdd/tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f", size = 251628, upload-time = "2026-03-25T20:21:36.012Z" },
404
+ { url = "https://files.pythonhosted.org/packages/e3/f1/dbeeb9116715abee2485bf0a12d07a8f31af94d71608c171c45f64c0469d/tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d", size = 247180, upload-time = "2026-03-25T20:21:37.136Z" },
405
+ { url = "https://files.pythonhosted.org/packages/d3/74/16336ffd19ed4da28a70959f92f506233bd7cfc2332b20bdb01591e8b1d1/tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5", size = 251674, upload-time = "2026-03-25T20:21:38.298Z" },
406
+ { url = "https://files.pythonhosted.org/packages/16/f9/229fa3434c590ddf6c0aa9af64d3af4b752540686cace29e6281e3458469/tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd", size = 97976, upload-time = "2026-03-25T20:21:39.316Z" },
407
+ { url = "https://files.pythonhosted.org/packages/6a/1e/71dfd96bcc1c775420cb8befe7a9d35f2e5b1309798f009dca17b7708c1e/tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36", size = 108755, upload-time = "2026-03-25T20:21:40.248Z" },
408
+ { url = "https://files.pythonhosted.org/packages/83/7a/d34f422a021d62420b78f5c538e5b102f62bea616d1d75a13f0a88acb04a/tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd", size = 95265, upload-time = "2026-03-25T20:21:41.219Z" },
409
+ { url = "https://files.pythonhosted.org/packages/3c/fb/9a5c8d27dbab540869f7c1f8eb0abb3244189ce780ba9cd73f3770662072/tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf", size = 155726, upload-time = "2026-03-25T20:21:42.23Z" },
410
+ { url = "https://files.pythonhosted.org/packages/62/05/d2f816630cc771ad836af54f5001f47a6f611d2d39535364f148b6a92d6b/tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac", size = 149859, upload-time = "2026-03-25T20:21:43.386Z" },
411
+ { url = "https://files.pythonhosted.org/packages/ce/48/66341bdb858ad9bd0ceab5a86f90eddab127cf8b046418009f2125630ecb/tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662", size = 244713, upload-time = "2026-03-25T20:21:44.474Z" },
412
+ { url = "https://files.pythonhosted.org/packages/df/6d/c5fad00d82b3c7a3ab6189bd4b10e60466f22cfe8a08a9394185c8a8111c/tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853", size = 252084, upload-time = "2026-03-25T20:21:45.62Z" },
413
+ { url = "https://files.pythonhosted.org/packages/00/71/3a69e86f3eafe8c7a59d008d245888051005bd657760e96d5fbfb0b740c2/tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15", size = 247973, upload-time = "2026-03-25T20:21:46.937Z" },
414
+ { url = "https://files.pythonhosted.org/packages/67/50/361e986652847fec4bd5e4a0208752fbe64689c603c7ae5ea7cb16b1c0ca/tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba", size = 256223, upload-time = "2026-03-25T20:21:48.467Z" },
415
+ { url = "https://files.pythonhosted.org/packages/8c/9a/b4173689a9203472e5467217e0154b00e260621caa227b6fa01feab16998/tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6", size = 98973, upload-time = "2026-03-25T20:21:49.526Z" },
416
+ { url = "https://files.pythonhosted.org/packages/14/58/640ac93bf230cd27d002462c9af0d837779f8773bc03dee06b5835208214/tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7", size = 109082, upload-time = "2026-03-25T20:21:50.506Z" },
417
+ { url = "https://files.pythonhosted.org/packages/d5/2f/702d5e05b227401c1068f0d386d79a589bb12bf64c3d2c72ce0631e3bc49/tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232", size = 96490, upload-time = "2026-03-25T20:21:51.474Z" },
418
+ { url = "https://files.pythonhosted.org/packages/45/4b/b877b05c8ba62927d9865dd980e34a755de541eb65fffba52b4cc495d4d2/tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4", size = 164263, upload-time = "2026-03-25T20:21:52.543Z" },
419
+ { url = "https://files.pythonhosted.org/packages/24/79/6ab420d37a270b89f7195dec5448f79400d9e9c1826df982f3f8e97b24fd/tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c", size = 160736, upload-time = "2026-03-25T20:21:53.674Z" },
420
+ { url = "https://files.pythonhosted.org/packages/02/e0/3630057d8eb170310785723ed5adcdfb7d50cb7e6455f85ba8a3deed642b/tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d", size = 270717, upload-time = "2026-03-25T20:21:55.129Z" },
421
+ { url = "https://files.pythonhosted.org/packages/7a/b4/1613716072e544d1a7891f548d8f9ec6ce2faf42ca65acae01d76ea06bb0/tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41", size = 278461, upload-time = "2026-03-25T20:21:56.228Z" },
422
+ { url = "https://files.pythonhosted.org/packages/05/38/30f541baf6a3f6df77b3df16b01ba319221389e2da59427e221ef417ac0c/tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c", size = 274855, upload-time = "2026-03-25T20:21:57.653Z" },
423
+ { url = "https://files.pythonhosted.org/packages/77/a3/ec9dd4fd2c38e98de34223b995a3b34813e6bdadf86c75314c928350ed14/tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f", size = 283144, upload-time = "2026-03-25T20:21:59.089Z" },
424
+ { url = "https://files.pythonhosted.org/packages/ef/be/605a6261cac79fba2ec0c9827e986e00323a1945700969b8ee0b30d85453/tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8", size = 108683, upload-time = "2026-03-25T20:22:00.214Z" },
425
+ { url = "https://files.pythonhosted.org/packages/12/64/da524626d3b9cc40c168a13da8335fe1c51be12c0a63685cc6db7308daae/tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26", size = 121196, upload-time = "2026-03-25T20:22:01.169Z" },
426
+ { url = "https://files.pythonhosted.org/packages/5a/cd/e80b62269fc78fc36c9af5a6b89c835baa8af28ff5ad28c7028d60860320/tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396", size = 100393, upload-time = "2026-03-25T20:22:02.137Z" },
427
+ { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" },
428
+ ]
429
+
337
430
  [[package]]
338
431
  name = "typing-extensions"
339
432
  version = "4.15.0"
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
File without changes
File without changes
File without changes