chzzk-python 0.13.0__tar.gz → 0.14.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 (117) hide show
  1. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/PKG-INFO +1 -1
  2. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/pyproject.toml +9 -1
  3. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/_version.py +2 -2
  4. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/cli/commands/auth.py +1 -1
  5. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/cli/commands/chat.py +99 -3
  6. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/cli/writers.py +34 -0
  7. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/realtime/client.py +15 -13
  8. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/uv.lock +55 -129
  9. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/.dockerignore +0 -0
  10. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/.env.example +0 -0
  11. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/.github/workflows/build.yml +0 -0
  12. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/.github/workflows/ci.yml +0 -0
  13. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/.github/workflows/docker.yml +0 -0
  14. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/.github/workflows/publish.yml +0 -0
  15. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/.gitignore +0 -0
  16. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/.python-version +0 -0
  17. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/Dockerfile +0 -0
  18. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/LICENSE +0 -0
  19. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/README.md +0 -0
  20. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/README_KO.md +0 -0
  21. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/chzzk.spec +0 -0
  22. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/docker-compose.yml +0 -0
  23. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/docs/unofficial-chat-websocket-protocol.md +0 -0
  24. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/examples/.env.example +0 -0
  25. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/examples/oauth_server.py +0 -0
  26. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/examples/realtime_chat.py +0 -0
  27. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/examples/realtime_chat_async.py +0 -0
  28. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/examples/session_management.py +0 -0
  29. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/examples/unofficial_chat.py +0 -0
  30. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/examples/unofficial_chat_async.py +0 -0
  31. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/main.py +0 -0
  32. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/scripts/build.py +0 -0
  33. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/__init__.py +0 -0
  34. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/api/__init__.py +0 -0
  35. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/api/base.py +0 -0
  36. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/api/category.py +0 -0
  37. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/api/channel.py +0 -0
  38. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/api/chat.py +0 -0
  39. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/api/live.py +0 -0
  40. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/api/restriction.py +0 -0
  41. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/api/session.py +0 -0
  42. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/api/user.py +0 -0
  43. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/auth/__init__.py +0 -0
  44. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/auth/models.py +0 -0
  45. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/auth/oauth.py +0 -0
  46. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/auth/token.py +0 -0
  47. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/cli/__init__.py +0 -0
  48. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/cli/commands/__init__.py +0 -0
  49. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/cli/commands/live.py +0 -0
  50. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/cli/config.py +0 -0
  51. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/cli/formatter.py +0 -0
  52. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/cli/logging.py +0 -0
  53. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/cli/main.py +0 -0
  54. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/cli/timezone.py +0 -0
  55. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/client.py +0 -0
  56. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/constants.py +0 -0
  57. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/exceptions/__init__.py +0 -0
  58. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/exceptions/errors.py +0 -0
  59. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/http/__init__.py +0 -0
  60. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/http/_base.py +0 -0
  61. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/http/client.py +0 -0
  62. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/http/endpoints.py +0 -0
  63. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/logging.py +0 -0
  64. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/models/__init__.py +0 -0
  65. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/models/category.py +0 -0
  66. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/models/channel.py +0 -0
  67. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/models/chat.py +0 -0
  68. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/models/common.py +0 -0
  69. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/models/live.py +0 -0
  70. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/models/restriction.py +0 -0
  71. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/models/session.py +0 -0
  72. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/models/user.py +0 -0
  73. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/py.typed +0 -0
  74. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/realtime/__init__.py +0 -0
  75. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/__init__.py +0 -0
  76. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/api/__init__.py +0 -0
  77. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/api/base.py +0 -0
  78. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/api/chat.py +0 -0
  79. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/api/live.py +0 -0
  80. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/api/user.py +0 -0
  81. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/auth/__init__.py +0 -0
  82. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/auth/cookie.py +0 -0
  83. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/chat/__init__.py +0 -0
  84. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/chat/client.py +0 -0
  85. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/chat/connection.py +0 -0
  86. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/chat/handler.py +0 -0
  87. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/chat/monitor.py +0 -0
  88. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/client.py +0 -0
  89. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/http/__init__.py +0 -0
  90. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/http/_base.py +0 -0
  91. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/http/client.py +0 -0
  92. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/http/endpoints.py +0 -0
  93. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/models/__init__.py +0 -0
  94. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/models/chat.py +0 -0
  95. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/models/live.py +0 -0
  96. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/models/reconnect.py +0 -0
  97. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/src/chzzk/unofficial/models/user.py +0 -0
  98. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/tests/__init__.py +0 -0
  99. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/tests/api/__init__.py +0 -0
  100. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/tests/api/test_category.py +0 -0
  101. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/tests/api/test_channel.py +0 -0
  102. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/tests/api/test_chat.py +0 -0
  103. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/tests/api/test_live.py +0 -0
  104. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/tests/api/test_restriction.py +0 -0
  105. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/tests/api/test_session.py +0 -0
  106. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/tests/api/test_user.py +0 -0
  107. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/tests/auth/__init__.py +0 -0
  108. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/tests/auth/test_oauth.py +0 -0
  109. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/tests/cli/__init__.py +0 -0
  110. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/tests/cli/test_formatter.py +0 -0
  111. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/tests/cli/test_writers.py +0 -0
  112. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/tests/realtime/__init__.py +0 -0
  113. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/tests/realtime/test_client.py +0 -0
  114. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/tests/test_client.py +0 -0
  115. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/tests/unofficial/__init__.py +0 -0
  116. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/tests/unofficial/test_client.py +0 -0
  117. {chzzk_python-0.13.0 → chzzk_python-0.14.0}/tests/unofficial/test_monitor.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chzzk-python
3
- Version: 0.13.0
3
+ Version: 0.14.0
4
4
  Summary: Unofficial Python SDK for Chzzk (NAVER Live Streaming Platform) API
5
5
  Project-URL: Homepage, https://github.com/hypn4/chzzk-python
6
6
  Project-URL: Repository, https://github.com/hypn4/chzzk-python
@@ -54,14 +54,18 @@ Changelog = "https://github.com/hypn4/chzzk-python/blob/main/CHANGELOG.md"
54
54
  [dependency-groups]
55
55
  dev = [
56
56
  "flask>=3.1.2",
57
- "mypy>=1.19.1",
57
+ "prompt-toolkit>=3.0.52",
58
58
  "pyinstaller>=6.18.0",
59
+ "pyright>=1.1.408",
59
60
  "pytest>=9.0.2",
60
61
  "pytest-asyncio>=1.3.0",
61
62
  "pytest-httpx>=0.35.0",
62
63
  "python-dotenv>=1.2.1",
63
64
  "pyzbar>=0.1.9",
65
+ "qrcode>=8.2",
66
+ "rich>=14.3.1",
64
67
  "ruff>=0.14.13",
68
+ "typer>=0.15.0",
65
69
  ]
66
70
 
67
71
  [build-system]
@@ -94,6 +98,10 @@ asyncio_mode = "auto"
94
98
  asyncio_default_fixture_loop_scope = "function"
95
99
  testpaths = ["tests"]
96
100
 
101
+ [tool.pyright]
102
+ pythonVersion = "3.12"
103
+ typeCheckingMode = "standard"
104
+
97
105
  [tool.ruff]
98
106
  line-length = 100
99
107
  target-version = "py312"
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.13.0'
32
- __version_tuple__ = version_tuple = (0, 13, 0)
31
+ __version__ = version = '0.14.0'
32
+ __version_tuple__ = version_tuple = (0, 14, 0)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -297,7 +297,7 @@ def _generate_qr_ascii(session: str) -> str:
297
297
 
298
298
  qr = qrcode.QRCode(
299
299
  version=1,
300
- error_correction=qrcode.constants.ERROR_CORRECT_L,
300
+ error_correction=qrcode.constants.ERROR_CORRECT_L, # type: ignore[reportAttributeAccessIssue]
301
301
  box_size=1,
302
302
  border=1,
303
303
  )
@@ -17,7 +17,13 @@ from rich.console import Console
17
17
 
18
18
  from chzzk.cli import timezone as tz
19
19
  from chzzk.cli.formatter import ChatFormatter, FormatConfig
20
- from chzzk.cli.writers import ChatWriter, OutputFormat, create_writer, generate_chat_log_filename
20
+ from chzzk.cli.writers import (
21
+ ChatWriter,
22
+ OutputFormat,
23
+ create_writer,
24
+ generate_chat_log_filename,
25
+ rotate_writer,
26
+ )
21
27
  from chzzk.constants import StatusText
22
28
  from chzzk.exceptions import ChatConnectionError, ChatNotLiveError
23
29
  from chzzk.unofficial import (
@@ -216,6 +222,7 @@ def _run_watch_console(
216
222
  formatter = ChatFormatter(format_config)
217
223
  # Track writer created from output_dir (needs to be closed on exit)
218
224
  output_dir_writer: ChatWriter | None = None
225
+ current_live_id: int | None = None
219
226
 
220
227
  async def run_chat() -> None:
221
228
  async with AsyncUnofficialChzzkClient(nid_aut=nid_aut, nid_ses=nid_ses) as client:
@@ -244,6 +251,49 @@ def _run_watch_console(
244
251
 
245
252
  @chat.on_live
246
253
  async def handle_live(event: StatusChangeEvent) -> None:
254
+ nonlocal writer, output_dir_writer, current_live_id
255
+
256
+ # Rotate log file when live_id changes in output_dir mode
257
+ if output_dir and event.live_id != current_live_id:
258
+ try:
259
+ open_date: str | None = None
260
+ try:
261
+ new_live_detail = await client.live.get_live_detail(channel_id)
262
+ open_date = new_live_detail.open_date
263
+ except Exception:
264
+ logger.warning(
265
+ "Failed to get live detail for log rotation, using local date"
266
+ )
267
+
268
+ new_writer, new_path = rotate_writer(
269
+ old_writer=output_dir_writer,
270
+ output_dir=output_dir,
271
+ channel_id=channel_id,
272
+ new_live_id=event.live_id,
273
+ open_date=open_date,
274
+ output_format=output_format,
275
+ )
276
+ output_dir_writer = new_writer
277
+ writer = new_writer
278
+ current_live_id = event.live_id
279
+
280
+ if json_output:
281
+ console.print(
282
+ json.dumps(
283
+ {
284
+ "event": "log_rotated",
285
+ "new_file": str(new_path),
286
+ "live_id": event.live_id,
287
+ }
288
+ )
289
+ )
290
+ else:
291
+ console.print(f"[dim]Log rotated: {new_path}[/dim]")
292
+ except OSError as e:
293
+ logger.warning(f"Failed to rotate log file: {e}")
294
+ if not json_output:
295
+ console.print(f"[yellow]Warning:[/yellow] Log rotation failed: {e}")
296
+
247
297
  if json_output:
248
298
  console.print(
249
299
  json.dumps(
@@ -316,7 +366,7 @@ def _run_watch_console(
316
366
  raise typer.Exit(1) from None
317
367
 
318
368
  # Create writer from output_dir if specified (after getting live_detail)
319
- nonlocal writer, output_dir_writer
369
+ nonlocal writer, output_dir_writer, current_live_id
320
370
  if output_dir and not writer:
321
371
  try:
322
372
  output_dir.mkdir(parents=True, exist_ok=True)
@@ -329,6 +379,7 @@ def _run_watch_console(
329
379
  )
330
380
  output_dir_writer = create_writer(output_path, output_format)
331
381
  writer = output_dir_writer
382
+ current_live_id = live_detail.live_id
332
383
  if not json_output:
333
384
  console.print(f"[dim]Saving chat to: {output_path}[/dim]")
334
385
  except OSError as e:
@@ -652,6 +703,7 @@ def _run_interactive_chat_console(
652
703
  formatter = ChatFormatter(format_config)
653
704
  # Track writer created from output_dir (needs to be closed on exit)
654
705
  output_dir_writer: ChatWriter | None = None
706
+ current_live_id: int | None = None
655
707
 
656
708
  async def run_chat() -> None:
657
709
  async with AsyncUnofficialChzzkClient(nid_aut=nid_aut, nid_ses=nid_ses) as client:
@@ -680,6 +732,49 @@ def _run_interactive_chat_console(
680
732
 
681
733
  @chat.on_live
682
734
  async def handle_live(event: StatusChangeEvent) -> None:
735
+ nonlocal writer, output_dir_writer, current_live_id
736
+
737
+ # Rotate log file when live_id changes in output_dir mode
738
+ if output_dir and event.live_id != current_live_id:
739
+ try:
740
+ open_date: str | None = None
741
+ try:
742
+ new_live_detail = await client.live.get_live_detail(channel_id)
743
+ open_date = new_live_detail.open_date
744
+ except Exception:
745
+ logger.warning(
746
+ "Failed to get live detail for log rotation, using local date"
747
+ )
748
+
749
+ new_writer, new_path = rotate_writer(
750
+ old_writer=output_dir_writer,
751
+ output_dir=output_dir,
752
+ channel_id=channel_id,
753
+ new_live_id=event.live_id,
754
+ open_date=open_date,
755
+ output_format=output_format,
756
+ )
757
+ output_dir_writer = new_writer
758
+ writer = new_writer
759
+ current_live_id = event.live_id
760
+
761
+ if json_output:
762
+ console.print(
763
+ json.dumps(
764
+ {
765
+ "event": "log_rotated",
766
+ "new_file": str(new_path),
767
+ "live_id": event.live_id,
768
+ }
769
+ )
770
+ )
771
+ else:
772
+ console.print(f"[dim]Log rotated: {new_path}[/dim]")
773
+ except OSError as e:
774
+ logger.warning(f"Failed to rotate log file: {e}")
775
+ if not json_output:
776
+ console.print(f"[yellow]Warning:[/yellow] Log rotation failed: {e}")
777
+
683
778
  if json_output:
684
779
  console.print(
685
780
  json.dumps(
@@ -752,7 +847,7 @@ def _run_interactive_chat_console(
752
847
  raise typer.Exit(1) from None
753
848
 
754
849
  # Create writer from output_dir if specified (after getting live_detail)
755
- nonlocal writer, output_dir_writer
850
+ nonlocal writer, output_dir_writer, current_live_id
756
851
  if output_dir and not writer:
757
852
  try:
758
853
  output_dir.mkdir(parents=True, exist_ok=True)
@@ -765,6 +860,7 @@ def _run_interactive_chat_console(
765
860
  )
766
861
  output_dir_writer = create_writer(output_path, output_format)
767
862
  writer = output_dir_writer
863
+ current_live_id = live_detail.live_id
768
864
  if not json_output:
769
865
  console.print(f"[dim]Saving chat to: {output_path}[/dim]")
770
866
  except OSError as e:
@@ -231,6 +231,40 @@ def generate_chat_log_filename(
231
231
  return output_dir / filename
232
232
 
233
233
 
234
+ def rotate_writer(
235
+ old_writer: ChatWriter | None,
236
+ output_dir: Path,
237
+ channel_id: str,
238
+ new_live_id: int | None,
239
+ open_date: str | None,
240
+ output_format: OutputFormat,
241
+ ) -> tuple[ChatWriter, Path]:
242
+ """Close old writer and create a new one with updated filename.
243
+
244
+ Args:
245
+ old_writer: The existing writer to close (if any).
246
+ output_dir: Directory to save the chat log.
247
+ channel_id: Channel ID.
248
+ new_live_id: New live ID for the filename.
249
+ open_date: Broadcast open date string.
250
+ output_format: Output format (jsonl or txt).
251
+
252
+ Returns:
253
+ A tuple of (new ChatWriter, new file Path).
254
+ """
255
+ if old_writer:
256
+ old_writer.close()
257
+
258
+ new_path = generate_chat_log_filename(
259
+ output_dir=output_dir,
260
+ channel_id=channel_id,
261
+ live_id=new_live_id,
262
+ open_date=open_date,
263
+ format=output_format,
264
+ )
265
+ return create_writer(new_path, output_format), new_path
266
+
267
+
234
268
  def create_writer(path: Path, format: OutputFormat | str) -> ChatWriter:
235
269
  """Create a chat writer for the specified format.
236
270
 
@@ -87,16 +87,13 @@ class ChzzkEventClient:
87
87
  def _setup_handlers(self) -> None:
88
88
  """Set up Socket.IO event handlers."""
89
89
 
90
- @self._sio.on("connect")
91
90
  def on_connect() -> None:
92
91
  pass
93
92
 
94
- @self._sio.on("disconnect")
95
93
  def on_disconnect() -> None:
96
94
  self._connected.clear()
97
95
  self._session_key = None
98
96
 
99
- @self._sio.on("SYSTEM")
100
97
  def on_system(data: str | dict[str, Any]) -> None:
101
98
  event = SystemEvent.model_validate(_parse_event_data(data))
102
99
 
@@ -109,24 +106,28 @@ class ChzzkEventClient:
109
106
  for handler in self._system_handlers:
110
107
  handler(event)
111
108
 
112
- @self._sio.on("CHAT")
113
109
  def on_chat(data: str | dict[str, Any]) -> None:
114
110
  event = ChatEvent.model_validate(_parse_event_data(data))
115
111
  for handler in self._chat_handlers:
116
112
  handler(event)
117
113
 
118
- @self._sio.on("DONATION")
119
114
  def on_donation(data: str | dict[str, Any]) -> None:
120
115
  event = DonationEvent.model_validate(_parse_event_data(data))
121
116
  for handler in self._donation_handlers:
122
117
  handler(event)
123
118
 
124
- @self._sio.on("SUBSCRIPTION")
125
119
  def on_subscription(data: str | dict[str, Any]) -> None:
126
120
  event = SubscriptionEvent.model_validate(_parse_event_data(data))
127
121
  for handler in self._subscription_handlers:
128
122
  handler(event)
129
123
 
124
+ self._sio.on("connect", on_connect)
125
+ self._sio.on("disconnect", on_disconnect)
126
+ self._sio.on("SYSTEM", on_system)
127
+ self._sio.on("CHAT", on_chat)
128
+ self._sio.on("DONATION", on_donation)
129
+ self._sio.on("SUBSCRIPTION", on_subscription)
130
+
130
131
  @property
131
132
  def session_key(self) -> str | None:
132
133
  """Get the current session key."""
@@ -246,7 +247,7 @@ class ChzzkEventClient:
246
247
  self._stop_event.clear()
247
248
  try:
248
249
  while self._sio.connected and not self._stop_event.is_set():
249
- self._sio.sleep(0.1)
250
+ self._sio.sleep(0.1) # type: ignore[reportArgumentType]
250
251
  except KeyboardInterrupt:
251
252
  pass
252
253
  finally:
@@ -379,17 +380,14 @@ class AsyncChzzkEventClient:
379
380
  def _setup_handlers(self) -> None:
380
381
  """Set up Socket.IO event handlers."""
381
382
 
382
- @self._sio.on("connect")
383
383
  async def on_connect() -> None:
384
384
  pass
385
385
 
386
- @self._sio.on("disconnect")
387
386
  async def on_disconnect() -> None:
388
387
  if self._connected_event:
389
388
  self._connected_event.clear()
390
389
  self._session_key = None
391
390
 
392
- @self._sio.on("SYSTEM")
393
391
  async def on_system(data: str | dict[str, Any]) -> None:
394
392
  event = SystemEvent.model_validate(_parse_event_data(data))
395
393
 
@@ -405,7 +403,6 @@ class AsyncChzzkEventClient:
405
403
  if hasattr(result, "__await__"):
406
404
  await result
407
405
 
408
- @self._sio.on("CHAT")
409
406
  async def on_chat(data: str | dict[str, Any]) -> None:
410
407
  event = ChatEvent.model_validate(_parse_event_data(data))
411
408
  for handler in self._chat_handlers:
@@ -413,7 +410,6 @@ class AsyncChzzkEventClient:
413
410
  if hasattr(result, "__await__"):
414
411
  await result
415
412
 
416
- @self._sio.on("DONATION")
417
413
  async def on_donation(data: str | dict[str, Any]) -> None:
418
414
  event = DonationEvent.model_validate(_parse_event_data(data))
419
415
  for handler in self._donation_handlers:
@@ -421,7 +417,6 @@ class AsyncChzzkEventClient:
421
417
  if hasattr(result, "__await__"):
422
418
  await result
423
419
 
424
- @self._sio.on("SUBSCRIPTION")
425
420
  async def on_subscription(data: str | dict[str, Any]) -> None:
426
421
  event = SubscriptionEvent.model_validate(_parse_event_data(data))
427
422
  for handler in self._subscription_handlers:
@@ -429,6 +424,13 @@ class AsyncChzzkEventClient:
429
424
  if hasattr(result, "__await__"):
430
425
  await result
431
426
 
427
+ self._sio.on("connect", on_connect)
428
+ self._sio.on("disconnect", on_disconnect)
429
+ self._sio.on("SYSTEM", on_system)
430
+ self._sio.on("CHAT", on_chat)
431
+ self._sio.on("DONATION", on_donation)
432
+ self._sio.on("SUBSCRIPTION", on_subscription)
433
+
432
434
  @property
433
435
  def session_key(self) -> str | None:
434
436
  """Get the current session key."""
@@ -190,14 +190,18 @@ cli = [
190
190
  [package.dev-dependencies]
191
191
  dev = [
192
192
  { name = "flask" },
193
- { name = "mypy" },
193
+ { name = "prompt-toolkit" },
194
194
  { name = "pyinstaller" },
195
+ { name = "pyright" },
195
196
  { name = "pytest" },
196
197
  { name = "pytest-asyncio" },
197
198
  { name = "pytest-httpx" },
198
199
  { name = "python-dotenv" },
199
200
  { name = "pyzbar" },
201
+ { name = "qrcode" },
202
+ { name = "rich" },
200
203
  { name = "ruff" },
204
+ { name = "typer" },
201
205
  ]
202
206
 
203
207
  [package.metadata]
@@ -218,14 +222,18 @@ provides-extras = ["cli"]
218
222
  [package.metadata.requires-dev]
219
223
  dev = [
220
224
  { name = "flask", specifier = ">=3.1.2" },
221
- { name = "mypy", specifier = ">=1.19.1" },
225
+ { name = "prompt-toolkit", specifier = ">=3.0.52" },
222
226
  { name = "pyinstaller", specifier = ">=6.18.0" },
227
+ { name = "pyright", specifier = ">=1.1.408" },
223
228
  { name = "pytest", specifier = ">=9.0.2" },
224
229
  { name = "pytest-asyncio", specifier = ">=1.3.0" },
225
230
  { name = "pytest-httpx", specifier = ">=0.35.0" },
226
231
  { name = "python-dotenv", specifier = ">=1.2.1" },
227
232
  { name = "pyzbar", specifier = ">=0.1.9" },
233
+ { name = "qrcode", specifier = ">=8.2" },
234
+ { name = "rich", specifier = ">=14.3.1" },
228
235
  { name = "ruff", specifier = ">=0.14.13" },
236
+ { name = "typer", specifier = ">=0.15.0" },
229
237
  ]
230
238
 
231
239
  [[package]]
@@ -431,58 +439,6 @@ wheels = [
431
439
  { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" },
432
440
  ]
433
441
 
434
- [[package]]
435
- name = "librt"
436
- version = "0.7.8"
437
- source = { registry = "https://pypi.org/simple" }
438
- 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" }
439
- wheels = [
440
- { url = "https://files.pythonhosted.org/packages/56/04/79d8fcb43cae376c7adbab7b2b9f65e48432c9eced62ac96703bcc16e09b/librt-0.7.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9b6943885b2d49c48d0cff23b16be830ba46b0152d98f62de49e735c6e655a63", size = 57472, upload-time = "2026-01-14T12:55:08.528Z" },
441
- { url = "https://files.pythonhosted.org/packages/b4/ba/60b96e93043d3d659da91752689023a73981336446ae82078cddf706249e/librt-0.7.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:46ef1f4b9b6cc364b11eea0ecc0897314447a66029ee1e55859acb3dd8757c93", size = 58986, upload-time = "2026-01-14T12:55:09.466Z" },
442
- { url = "https://files.pythonhosted.org/packages/7c/26/5215e4cdcc26e7be7eee21955a7e13cbf1f6d7d7311461a6014544596fac/librt-0.7.8-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:907ad09cfab21e3c86e8f1f87858f7049d1097f77196959c033612f532b4e592", size = 168422, upload-time = "2026-01-14T12:55:10.499Z" },
443
- { url = "https://files.pythonhosted.org/packages/0f/84/e8d1bc86fa0159bfc24f3d798d92cafd3897e84c7fea7fe61b3220915d76/librt-0.7.8-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2991b6c3775383752b3ca0204842743256f3ad3deeb1d0adc227d56b78a9a850", size = 177478, upload-time = "2026-01-14T12:55:11.577Z" },
444
- { url = "https://files.pythonhosted.org/packages/57/11/d0268c4b94717a18aa91df1100e767b010f87b7ae444dafaa5a2d80f33a6/librt-0.7.8-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03679b9856932b8c8f674e87aa3c55ea11c9274301f76ae8dc4d281bda55cf62", size = 192439, upload-time = "2026-01-14T12:55:12.7Z" },
445
- { url = "https://files.pythonhosted.org/packages/8d/56/1e8e833b95fe684f80f8894ae4d8b7d36acc9203e60478fcae599120a975/librt-0.7.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3968762fec1b2ad34ce57458b6de25dbb4142713e9ca6279a0d352fa4e9f452b", size = 191483, upload-time = "2026-01-14T12:55:13.838Z" },
446
- { url = "https://files.pythonhosted.org/packages/17/48/f11cf28a2cb6c31f282009e2208312aa84a5ee2732859f7856ee306176d5/librt-0.7.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:bb7a7807523a31f03061288cc4ffc065d684c39db7644c676b47d89553c0d714", size = 185376, upload-time = "2026-01-14T12:55:15.017Z" },
447
- { url = "https://files.pythonhosted.org/packages/b8/6a/d7c116c6da561b9155b184354a60a3d5cdbf08fc7f3678d09c95679d13d9/librt-0.7.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad64a14b1e56e702e19b24aae108f18ad1bf7777f3af5fcd39f87d0c5a814449", size = 206234, upload-time = "2026-01-14T12:55:16.571Z" },
448
- { url = "https://files.pythonhosted.org/packages/61/de/1975200bb0285fc921c5981d9978ce6ce11ae6d797df815add94a5a848a3/librt-0.7.8-cp312-cp312-win32.whl", hash = "sha256:0241a6ed65e6666236ea78203a73d800dbed896cf12ae25d026d75dc1fcd1dac", size = 44057, upload-time = "2026-01-14T12:55:18.077Z" },
449
- { url = "https://files.pythonhosted.org/packages/8e/cd/724f2d0b3461426730d4877754b65d39f06a41ac9d0a92d5c6840f72b9ae/librt-0.7.8-cp312-cp312-win_amd64.whl", hash = "sha256:6db5faf064b5bab9675c32a873436b31e01d66ca6984c6f7f92621656033a708", size = 50293, upload-time = "2026-01-14T12:55:19.179Z" },
450
- { url = "https://files.pythonhosted.org/packages/bd/cf/7e899acd9ee5727ad8160fdcc9994954e79fab371c66535c60e13b968ffc/librt-0.7.8-cp312-cp312-win_arm64.whl", hash = "sha256:57175aa93f804d2c08d2edb7213e09276bd49097611aefc37e3fa38d1fb99ad0", size = 43574, upload-time = "2026-01-14T12:55:20.185Z" },
451
- { url = "https://files.pythonhosted.org/packages/a1/fe/b1f9de2829cf7fc7649c1dcd202cfd873837c5cc2fc9e526b0e7f716c3d2/librt-0.7.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4c3995abbbb60b3c129490fa985dfe6cac11d88fc3c36eeb4fb1449efbbb04fc", size = 57500, upload-time = "2026-01-14T12:55:21.219Z" },
452
- { url = "https://files.pythonhosted.org/packages/eb/d4/4a60fbe2e53b825f5d9a77325071d61cd8af8506255067bf0c8527530745/librt-0.7.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:44e0c2cbc9bebd074cf2cdbe472ca185e824be4e74b1c63a8e934cea674bebf2", size = 59019, upload-time = "2026-01-14T12:55:22.256Z" },
453
- { url = "https://files.pythonhosted.org/packages/6a/37/61ff80341ba5159afa524445f2d984c30e2821f31f7c73cf166dcafa5564/librt-0.7.8-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4d2f1e492cae964b3463a03dc77a7fe8742f7855d7258c7643f0ee32b6651dd3", size = 169015, upload-time = "2026-01-14T12:55:23.24Z" },
454
- { url = "https://files.pythonhosted.org/packages/1c/86/13d4f2d6a93f181ebf2fc953868826653ede494559da8268023fe567fca3/librt-0.7.8-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:451e7ffcef8f785831fdb791bd69211f47e95dc4c6ddff68e589058806f044c6", size = 178161, upload-time = "2026-01-14T12:55:24.826Z" },
455
- { url = "https://files.pythonhosted.org/packages/88/26/e24ef01305954fc4d771f1f09f3dd682f9eb610e1bec188ffb719374d26e/librt-0.7.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3469e1af9f1380e093ae06bedcbdd11e407ac0b303a56bbe9afb1d6824d4982d", size = 193015, upload-time = "2026-01-14T12:55:26.04Z" },
456
- { url = "https://files.pythonhosted.org/packages/88/a0/92b6bd060e720d7a31ed474d046a69bd55334ec05e9c446d228c4b806ae3/librt-0.7.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f11b300027ce19a34f6d24ebb0a25fd0e24a9d53353225a5c1e6cadbf2916b2e", size = 192038, upload-time = "2026-01-14T12:55:27.208Z" },
457
- { url = "https://files.pythonhosted.org/packages/06/bb/6f4c650253704279c3a214dad188101d1b5ea23be0606628bc6739456624/librt-0.7.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4adc73614f0d3c97874f02f2c7fd2a27854e7e24ad532ea6b965459c5b757eca", size = 186006, upload-time = "2026-01-14T12:55:28.594Z" },
458
- { url = "https://files.pythonhosted.org/packages/dc/00/1c409618248d43240cadf45f3efb866837fa77e9a12a71481912135eb481/librt-0.7.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:60c299e555f87e4c01b2eca085dfccda1dde87f5a604bb45c2906b8305819a93", size = 206888, upload-time = "2026-01-14T12:55:30.214Z" },
459
- { url = "https://files.pythonhosted.org/packages/d9/83/b2cfe8e76ff5c1c77f8a53da3d5de62d04b5ebf7cf913e37f8bca43b5d07/librt-0.7.8-cp313-cp313-win32.whl", hash = "sha256:b09c52ed43a461994716082ee7d87618096851319bf695d57ec123f2ab708951", size = 44126, upload-time = "2026-01-14T12:55:31.44Z" },
460
- { url = "https://files.pythonhosted.org/packages/a9/0b/c59d45de56a51bd2d3a401fc63449c0ac163e4ef7f523ea8b0c0dee86ec5/librt-0.7.8-cp313-cp313-win_amd64.whl", hash = "sha256:f8f4a901a3fa28969d6e4519deceab56c55a09d691ea7b12ca830e2fa3461e34", size = 50262, upload-time = "2026-01-14T12:55:33.01Z" },
461
- { url = "https://files.pythonhosted.org/packages/fc/b9/973455cec0a1ec592395250c474164c4a58ebf3e0651ee920fef1a2623f1/librt-0.7.8-cp313-cp313-win_arm64.whl", hash = "sha256:43d4e71b50763fcdcf64725ac680d8cfa1706c928b844794a7aa0fa9ac8e5f09", size = 43600, upload-time = "2026-01-14T12:55:34.054Z" },
462
- { url = "https://files.pythonhosted.org/packages/1a/73/fa8814c6ce2d49c3827829cadaa1589b0bf4391660bd4510899393a23ebc/librt-0.7.8-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:be927c3c94c74b05128089a955fba86501c3b544d1d300282cc1b4bd370cb418", size = 57049, upload-time = "2026-01-14T12:55:35.056Z" },
463
- { url = "https://files.pythonhosted.org/packages/53/fe/f6c70956da23ea235fd2e3cc16f4f0b4ebdfd72252b02d1164dd58b4e6c3/librt-0.7.8-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:7b0803e9008c62a7ef79058233db7ff6f37a9933b8f2573c05b07ddafa226611", size = 58689, upload-time = "2026-01-14T12:55:36.078Z" },
464
- { url = "https://files.pythonhosted.org/packages/1f/4d/7a2481444ac5fba63050d9abe823e6bc16896f575bfc9c1e5068d516cdce/librt-0.7.8-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:79feb4d00b2a4e0e05c9c56df707934f41fcb5fe53fd9efb7549068d0495b758", size = 166808, upload-time = "2026-01-14T12:55:37.595Z" },
465
- { url = "https://files.pythonhosted.org/packages/ac/3c/10901d9e18639f8953f57c8986796cfbf4c1c514844a41c9197cf87cb707/librt-0.7.8-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b9122094e3f24aa759c38f46bd8863433820654927370250f460ae75488b66ea", size = 175614, upload-time = "2026-01-14T12:55:38.756Z" },
466
- { url = "https://files.pythonhosted.org/packages/db/01/5cbdde0951a5090a80e5ba44e6357d375048123c572a23eecfb9326993a7/librt-0.7.8-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7e03bea66af33c95ce3addf87a9bf1fcad8d33e757bc479957ddbc0e4f7207ac", size = 189955, upload-time = "2026-01-14T12:55:39.939Z" },
467
- { url = "https://files.pythonhosted.org/packages/6a/b4/e80528d2f4b7eaf1d437fcbd6fc6ba4cbeb3e2a0cb9ed5a79f47c7318706/librt-0.7.8-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f1ade7f31675db00b514b98f9ab9a7698c7282dad4be7492589109471852d398", size = 189370, upload-time = "2026-01-14T12:55:41.057Z" },
468
- { url = "https://files.pythonhosted.org/packages/c1/ab/938368f8ce31a9787ecd4becb1e795954782e4312095daf8fd22420227c8/librt-0.7.8-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a14229ac62adcf1b90a15992f1ab9c69ae8b99ffb23cb64a90878a6e8a2f5b81", size = 183224, upload-time = "2026-01-14T12:55:42.328Z" },
469
- { url = "https://files.pythonhosted.org/packages/3c/10/559c310e7a6e4014ac44867d359ef8238465fb499e7eb31b6bfe3e3f86f5/librt-0.7.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5bcaaf624fd24e6a0cb14beac37677f90793a96864c67c064a91458611446e83", size = 203541, upload-time = "2026-01-14T12:55:43.501Z" },
470
- { url = "https://files.pythonhosted.org/packages/f8/db/a0db7acdb6290c215f343835c6efda5b491bb05c3ddc675af558f50fdba3/librt-0.7.8-cp314-cp314-win32.whl", hash = "sha256:7aa7d5457b6c542ecaed79cec4ad98534373c9757383973e638ccced0f11f46d", size = 40657, upload-time = "2026-01-14T12:55:44.668Z" },
471
- { url = "https://files.pythonhosted.org/packages/72/e0/4f9bdc2a98a798511e81edcd6b54fe82767a715e05d1921115ac70717f6f/librt-0.7.8-cp314-cp314-win_amd64.whl", hash = "sha256:3d1322800771bee4a91f3b4bd4e49abc7d35e65166821086e5afd1e6c0d9be44", size = 46835, upload-time = "2026-01-14T12:55:45.655Z" },
472
- { url = "https://files.pythonhosted.org/packages/f9/3d/59c6402e3dec2719655a41ad027a7371f8e2334aa794ed11533ad5f34969/librt-0.7.8-cp314-cp314-win_arm64.whl", hash = "sha256:5363427bc6a8c3b1719f8f3845ea53553d301382928a86e8fab7984426949bce", size = 39885, upload-time = "2026-01-14T12:55:47.138Z" },
473
- { url = "https://files.pythonhosted.org/packages/4e/9c/2481d80950b83085fb14ba3c595db56330d21bbc7d88a19f20165f3538db/librt-0.7.8-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:ca916919793a77e4a98d4a1701e345d337ce53be4a16620f063191f7322ac80f", size = 59161, upload-time = "2026-01-14T12:55:48.45Z" },
474
- { url = "https://files.pythonhosted.org/packages/96/79/108df2cfc4e672336765d54e3ff887294c1cc36ea4335c73588875775527/librt-0.7.8-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:54feb7b4f2f6706bb82325e836a01be805770443e2400f706e824e91f6441dde", size = 61008, upload-time = "2026-01-14T12:55:49.527Z" },
475
- { url = "https://files.pythonhosted.org/packages/46/f2/30179898f9994a5637459d6e169b6abdc982012c0a4b2d4c26f50c06f911/librt-0.7.8-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:39a4c76fee41007070f872b648cc2f711f9abf9a13d0c7162478043377b52c8e", size = 187199, upload-time = "2026-01-14T12:55:50.587Z" },
476
- { url = "https://files.pythonhosted.org/packages/b4/da/f7563db55cebdc884f518ba3791ad033becc25ff68eb70902b1747dc0d70/librt-0.7.8-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ac9c8a458245c7de80bc1b9765b177055efff5803f08e548dd4bb9ab9a8d789b", size = 198317, upload-time = "2026-01-14T12:55:51.991Z" },
477
- { url = "https://files.pythonhosted.org/packages/b3/6c/4289acf076ad371471fa86718c30ae353e690d3de6167f7db36f429272f1/librt-0.7.8-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:95b67aa7eff150f075fda09d11f6bfb26edffd300f6ab1666759547581e8f666", size = 210334, upload-time = "2026-01-14T12:55:53.682Z" },
478
- { url = "https://files.pythonhosted.org/packages/4a/7f/377521ac25b78ac0a5ff44127a0360ee6d5ddd3ce7327949876a30533daa/librt-0.7.8-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:535929b6eff670c593c34ff435d5440c3096f20fa72d63444608a5aef64dd581", size = 211031, upload-time = "2026-01-14T12:55:54.827Z" },
479
- { url = "https://files.pythonhosted.org/packages/c5/b1/e1e96c3e20b23d00cf90f4aad48f0deb4cdfec2f0ed8380d0d85acf98bbf/librt-0.7.8-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:63937bd0f4d1cb56653dc7ae900d6c52c41f0015e25aaf9902481ee79943b33a", size = 204581, upload-time = "2026-01-14T12:55:56.811Z" },
480
- { url = "https://files.pythonhosted.org/packages/43/71/0f5d010e92ed9747e14bef35e91b6580533510f1e36a8a09eb79ee70b2f0/librt-0.7.8-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cf243da9e42d914036fd362ac3fa77d80a41cadcd11ad789b1b5eec4daaf67ca", size = 224731, upload-time = "2026-01-14T12:55:58.175Z" },
481
- { url = "https://files.pythonhosted.org/packages/22/f0/07fb6ab5c39a4ca9af3e37554f9d42f25c464829254d72e4ebbd81da351c/librt-0.7.8-cp314-cp314t-win32.whl", hash = "sha256:171ca3a0a06c643bd0a2f62a8944e1902c94aa8e5da4db1ea9a8daf872685365", size = 41173, upload-time = "2026-01-14T12:55:59.315Z" },
482
- { url = "https://files.pythonhosted.org/packages/24/d4/7e4be20993dc6a782639625bd2f97f3c66125c7aa80c82426956811cfccf/librt-0.7.8-cp314-cp314t-win_amd64.whl", hash = "sha256:445b7304145e24c60288a2f172b5ce2ca35c0f81605f5299f3fa567e189d2e32", size = 47668, upload-time = "2026-01-14T12:56:00.261Z" },
483
- { url = "https://files.pythonhosted.org/packages/fc/85/69f92b2a7b3c0f88ffe107c86b952b397004b5b8ea5a81da3d9c04c04422/librt-0.7.8-cp314-cp314t-win_arm64.whl", hash = "sha256:8766ece9de08527deabcd7cb1b4f1a967a385d26e33e536d6d8913db6ef74f06", size = 40550, upload-time = "2026-01-14T12:56:01.542Z" },
484
- ]
485
-
486
442
  [[package]]
487
443
  name = "macholib"
488
444
  version = "1.16.4"
@@ -679,45 +635,12 @@ wheels = [
679
635
  ]
680
636
 
681
637
  [[package]]
682
- name = "mypy"
683
- version = "1.19.1"
684
- source = { registry = "https://pypi.org/simple" }
685
- dependencies = [
686
- { name = "librt", marker = "platform_python_implementation != 'PyPy'" },
687
- { name = "mypy-extensions" },
688
- { name = "pathspec" },
689
- { name = "typing-extensions" },
690
- ]
691
- 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" }
692
- wheels = [
693
- { 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" },
694
- { 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" },
695
- { 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" },
696
- { url = "https://files.pythonhosted.org/packages/00/be/dd56c1fd4807bc1eba1cf18b2a850d0de7bacb55e158755eb79f77c41f8e/mypy-1.19.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8", size = 13620847, upload-time = "2025-12-15T05:03:39.633Z" },
697
- { url = "https://files.pythonhosted.org/packages/6d/42/332951aae42b79329f743bf1da088cd75d8d4d9acc18fbcbd84f26c1af4e/mypy-1.19.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a", size = 13834976, upload-time = "2025-12-15T05:03:08.786Z" },
698
- { url = "https://files.pythonhosted.org/packages/6f/63/e7493e5f90e1e085c562bb06e2eb32cae27c5057b9653348d38b47daaecc/mypy-1.19.1-cp312-cp312-win_amd64.whl", hash = "sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13", size = 10118104, upload-time = "2025-12-15T05:03:10.834Z" },
699
- { url = "https://files.pythonhosted.org/packages/de/9f/a6abae693f7a0c697dbb435aac52e958dc8da44e92e08ba88d2e42326176/mypy-1.19.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250", size = 13201927, upload-time = "2025-12-15T05:02:29.138Z" },
700
- { url = "https://files.pythonhosted.org/packages/9a/a4/45c35ccf6e1c65afc23a069f50e2c66f46bd3798cbe0d680c12d12935caa/mypy-1.19.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b", size = 12206730, upload-time = "2025-12-15T05:03:01.325Z" },
701
- { url = "https://files.pythonhosted.org/packages/05/bb/cdcf89678e26b187650512620eec8368fded4cfd99cfcb431e4cdfd19dec/mypy-1.19.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e", size = 12724581, upload-time = "2025-12-15T05:03:20.087Z" },
702
- { url = "https://files.pythonhosted.org/packages/d1/32/dd260d52babf67bad8e6770f8e1102021877ce0edea106e72df5626bb0ec/mypy-1.19.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef", size = 13616252, upload-time = "2025-12-15T05:02:49.036Z" },
703
- { url = "https://files.pythonhosted.org/packages/71/d0/5e60a9d2e3bd48432ae2b454b7ef2b62a960ab51292b1eda2a95edd78198/mypy-1.19.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75", size = 13840848, upload-time = "2025-12-15T05:02:55.95Z" },
704
- { url = "https://files.pythonhosted.org/packages/98/76/d32051fa65ecf6cc8c6610956473abdc9b4c43301107476ac03559507843/mypy-1.19.1-cp313-cp313-win_amd64.whl", hash = "sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd", size = 10135510, upload-time = "2025-12-15T05:02:58.438Z" },
705
- { url = "https://files.pythonhosted.org/packages/de/eb/b83e75f4c820c4247a58580ef86fcd35165028f191e7e1ba57128c52782d/mypy-1.19.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1", size = 13199744, upload-time = "2025-12-15T05:03:30.823Z" },
706
- { url = "https://files.pythonhosted.org/packages/94/28/52785ab7bfa165f87fcbb61547a93f98bb20e7f82f90f165a1f69bce7b3d/mypy-1.19.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718", size = 12215815, upload-time = "2025-12-15T05:02:42.323Z" },
707
- { url = "https://files.pythonhosted.org/packages/0a/c6/bdd60774a0dbfb05122e3e925f2e9e846c009e479dcec4821dad881f5b52/mypy-1.19.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b", size = 12740047, upload-time = "2025-12-15T05:03:33.168Z" },
708
- { url = "https://files.pythonhosted.org/packages/32/2a/66ba933fe6c76bd40d1fe916a83f04fed253152f451a877520b3c4a5e41e/mypy-1.19.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045", size = 13601998, upload-time = "2025-12-15T05:03:13.056Z" },
709
- { url = "https://files.pythonhosted.org/packages/e3/da/5055c63e377c5c2418760411fd6a63ee2b96cf95397259038756c042574f/mypy-1.19.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957", size = 13807476, upload-time = "2025-12-15T05:03:17.977Z" },
710
- { url = "https://files.pythonhosted.org/packages/cd/09/4ebd873390a063176f06b0dbf1f7783dd87bd120eae7727fa4ae4179b685/mypy-1.19.1-cp314-cp314-win_amd64.whl", hash = "sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f", size = 10281872, upload-time = "2025-12-15T05:03:05.549Z" },
711
- { url = "https://files.pythonhosted.org/packages/8d/f4/4ce9a05ce5ded1de3ec1c1d96cf9f9504a04e54ce0ed55cfa38619a32b8d/mypy-1.19.1-py3-none-any.whl", hash = "sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247", size = 2471239, upload-time = "2025-12-15T05:03:07.248Z" },
712
- ]
713
-
714
- [[package]]
715
- name = "mypy-extensions"
716
- version = "1.1.0"
638
+ name = "nodeenv"
639
+ version = "1.10.0"
717
640
  source = { registry = "https://pypi.org/simple" }
718
- sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" }
641
+ sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" }
719
642
  wheels = [
720
- { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" },
643
+ { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" },
721
644
  ]
722
645
 
723
646
  [[package]]
@@ -729,15 +652,6 @@ wheels = [
729
652
  { url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529", size = 74366, upload-time = "2026-01-21T20:50:37.788Z" },
730
653
  ]
731
654
 
732
- [[package]]
733
- name = "pathspec"
734
- version = "1.0.4"
735
- source = { registry = "https://pypi.org/simple" }
736
- sdist = { url = "https://files.pythonhosted.org/packages/fa/36/e27608899f9b8d4dff0617b2d9ab17ca5608956ca44461ac14ac48b44015/pathspec-1.0.4.tar.gz", hash = "sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645", size = 131200, upload-time = "2026-01-27T03:59:46.938Z" }
737
- wheels = [
738
- { url = "https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723", size = 55206, upload-time = "2026-01-27T03:59:45.137Z" },
739
- ]
740
-
741
655
  [[package]]
742
656
  name = "pefile"
743
657
  version = "2024.8.26"
@@ -988,6 +902,19 @@ wheels = [
988
902
  { url = "https://files.pythonhosted.org/packages/d5/b1/9da6ec3e88696018ee7bb9dc4a7310c2cfaebf32923a19598cd342767c10/pyinstaller_hooks_contrib-2026.0-py3-none-any.whl", hash = "sha256:0590db8edeba3e6c30c8474937021f5cd39c0602b4d10f74a064c73911efaca5", size = 452318, upload-time = "2026-01-20T00:15:21.88Z" },
989
903
  ]
990
904
 
905
+ [[package]]
906
+ name = "pyright"
907
+ version = "1.1.408"
908
+ source = { registry = "https://pypi.org/simple" }
909
+ dependencies = [
910
+ { name = "nodeenv" },
911
+ { name = "typing-extensions" },
912
+ ]
913
+ sdist = { url = "https://files.pythonhosted.org/packages/74/b2/5db700e52554b8f025faa9c3c624c59f1f6c8841ba81ab97641b54322f16/pyright-1.1.408.tar.gz", hash = "sha256:f28f2321f96852fa50b5829ea492f6adb0e6954568d1caa3f3af3a5f555eb684", size = 4400578, upload-time = "2026-01-08T08:07:38.795Z" }
914
+ wheels = [
915
+ { url = "https://files.pythonhosted.org/packages/0c/82/a2c93e32800940d9573fb28c346772a14778b84ba7524e691b324620ab89/pyright-1.1.408-py3-none-any.whl", hash = "sha256:090b32865f4fdb1e0e6cd82bf5618480d48eecd2eb2e70f960982a3d9a4c17c1", size = 6399144, upload-time = "2026-01-08T08:07:37.082Z" },
916
+ ]
917
+
991
918
  [[package]]
992
919
  name = "pytest"
993
920
  version = "9.0.2"
@@ -1103,50 +1030,49 @@ wheels = [
1103
1030
 
1104
1031
  [[package]]
1105
1032
  name = "rich"
1106
- version = "14.3.1"
1033
+ version = "14.3.2"
1107
1034
  source = { registry = "https://pypi.org/simple" }
1108
1035
  dependencies = [
1109
1036
  { name = "markdown-it-py" },
1110
1037
  { name = "pygments" },
1111
1038
  ]
1112
- sdist = { url = "https://files.pythonhosted.org/packages/a1/84/4831f881aa6ff3c976f6d6809b58cdfa350593ffc0dc3c58f5f6586780fb/rich-14.3.1.tar.gz", hash = "sha256:b8c5f568a3a749f9290ec6bddedf835cec33696bfc1e48bcfecb276c7386e4b8", size = 230125, upload-time = "2026-01-24T21:40:44.847Z" }
1039
+ sdist = { url = "https://files.pythonhosted.org/packages/74/99/a4cab2acbb884f80e558b0771e97e21e939c5dfb460f488d19df485e8298/rich-14.3.2.tar.gz", hash = "sha256:e712f11c1a562a11843306f5ed999475f09ac31ffb64281f73ab29ffdda8b3b8", size = 230143, upload-time = "2026-02-01T16:20:47.908Z" }
1113
1040
  wheels = [
1114
- { url = "https://files.pythonhosted.org/packages/87/2a/a1810c8627b9ec8c57ec5ec325d306701ae7be50235e8fd81266e002a3cc/rich-14.3.1-py3-none-any.whl", hash = "sha256:da750b1aebbff0b372557426fb3f35ba56de8ef954b3190315eb64076d6fb54e", size = 309952, upload-time = "2026-01-24T21:40:42.969Z" },
1041
+ { url = "https://files.pythonhosted.org/packages/ef/45/615f5babd880b4bd7d405cc0dc348234c5ffb6ed1ea33e152ede08b2072d/rich-14.3.2-py3-none-any.whl", hash = "sha256:08e67c3e90884651da3239ea668222d19bea7b589149d8014a21c633420dbb69", size = 309963, upload-time = "2026-02-01T16:20:46.078Z" },
1115
1042
  ]
1116
1043
 
1117
1044
  [[package]]
1118
1045
  name = "ruff"
1119
- version = "0.14.14"
1046
+ version = "0.15.0"
1120
1047
  source = { registry = "https://pypi.org/simple" }
1121
- sdist = { url = "https://files.pythonhosted.org/packages/2e/06/f71e3a86b2df0dfa2d2f72195941cd09b44f87711cb7fa5193732cb9a5fc/ruff-0.14.14.tar.gz", hash = "sha256:2d0f819c9a90205f3a867dbbd0be083bee9912e170fd7d9704cc8ae45824896b", size = 4515732, upload-time = "2026-01-22T22:30:17.527Z" }
1048
+ sdist = { url = "https://files.pythonhosted.org/packages/c8/39/5cee96809fbca590abea6b46c6d1c586b49663d1d2830a751cc8fc42c666/ruff-0.15.0.tar.gz", hash = "sha256:6bdea47cdbea30d40f8f8d7d69c0854ba7c15420ec75a26f463290949d7f7e9a", size = 4524893, upload-time = "2026-02-03T17:53:35.357Z" }
1122
1049
  wheels = [
1123
- { url = "https://files.pythonhosted.org/packages/d2/89/20a12e97bc6b9f9f68343952da08a8099c57237aef953a56b82711d55edd/ruff-0.14.14-py3-none-linux_armv6l.whl", hash = "sha256:7cfe36b56e8489dee8fbc777c61959f60ec0f1f11817e8f2415f429552846aed", size = 10467650, upload-time = "2026-01-22T22:30:08.578Z" },
1124
- { url = "https://files.pythonhosted.org/packages/a3/b1/c5de3fd2d5a831fcae21beda5e3589c0ba67eec8202e992388e4b17a6040/ruff-0.14.14-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6006a0082336e7920b9573ef8a7f52eec837add1265cc74e04ea8a4368cd704c", size = 10883245, upload-time = "2026-01-22T22:30:04.155Z" },
1125
- { url = "https://files.pythonhosted.org/packages/b8/7c/3c1db59a10e7490f8f6f8559d1db8636cbb13dccebf18686f4e3c9d7c772/ruff-0.14.14-py3-none-macosx_11_0_arm64.whl", hash = "sha256:026c1d25996818f0bf498636686199d9bd0d9d6341c9c2c3b62e2a0198b758de", size = 10231273, upload-time = "2026-01-22T22:30:34.642Z" },
1126
- { url = "https://files.pythonhosted.org/packages/a1/6e/5e0e0d9674be0f8581d1f5e0f0a04761203affce3232c1a1189d0e3b4dad/ruff-0.14.14-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f666445819d31210b71e0a6d1c01e24447a20b85458eea25a25fe8142210ae0e", size = 10585753, upload-time = "2026-01-22T22:30:31.781Z" },
1127
- { url = "https://files.pythonhosted.org/packages/23/09/754ab09f46ff1884d422dc26d59ba18b4e5d355be147721bb2518aa2a014/ruff-0.14.14-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c0f18b922c6d2ff9a5e6c3ee16259adc513ca775bcf82c67ebab7cbd9da5bc8", size = 10286052, upload-time = "2026-01-22T22:30:24.827Z" },
1128
- { url = "https://files.pythonhosted.org/packages/c8/cc/e71f88dd2a12afb5f50733851729d6b571a7c3a35bfdb16c3035132675a0/ruff-0.14.14-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1629e67489c2dea43e8658c3dba659edbfd87361624b4040d1df04c9740ae906", size = 11043637, upload-time = "2026-01-22T22:30:13.239Z" },
1129
- { url = "https://files.pythonhosted.org/packages/67/b2/397245026352494497dac935d7f00f1468c03a23a0c5db6ad8fc49ca3fb2/ruff-0.14.14-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:27493a2131ea0f899057d49d303e4292b2cae2bb57253c1ed1f256fbcd1da480", size = 12194761, upload-time = "2026-01-22T22:30:22.542Z" },
1130
- { url = "https://files.pythonhosted.org/packages/5b/06/06ef271459f778323112c51b7587ce85230785cd64e91772034ddb88f200/ruff-0.14.14-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:01ff589aab3f5b539e35db38425da31a57521efd1e4ad1ae08fc34dbe30bd7df", size = 12005701, upload-time = "2026-01-22T22:30:20.499Z" },
1131
- { url = "https://files.pythonhosted.org/packages/41/d6/99364514541cf811ccc5ac44362f88df66373e9fec1b9d1c4cc830593fe7/ruff-0.14.14-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc12d74eef0f29f51775f5b755913eb523546b88e2d733e1d701fe65144e89b", size = 11282455, upload-time = "2026-01-22T22:29:59.679Z" },
1132
- { url = "https://files.pythonhosted.org/packages/ca/71/37daa46f89475f8582b7762ecd2722492df26421714a33e72ccc9a84d7a5/ruff-0.14.14-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb8481604b7a9e75eff53772496201690ce2687067e038b3cc31aaf16aa0b974", size = 11215882, upload-time = "2026-01-22T22:29:57.032Z" },
1133
- { url = "https://files.pythonhosted.org/packages/2c/10/a31f86169ec91c0705e618443ee74ede0bdd94da0a57b28e72db68b2dbac/ruff-0.14.14-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:14649acb1cf7b5d2d283ebd2f58d56b75836ed8c6f329664fa91cdea19e76e66", size = 11180549, upload-time = "2026-01-22T22:30:27.175Z" },
1134
- { url = "https://files.pythonhosted.org/packages/fd/1e/c723f20536b5163adf79bdd10c5f093414293cdf567eed9bdb7b83940f3f/ruff-0.14.14-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e8058d2145566510790eab4e2fad186002e288dec5e0d343a92fe7b0bc1b3e13", size = 10543416, upload-time = "2026-01-22T22:30:01.964Z" },
1135
- { url = "https://files.pythonhosted.org/packages/3e/34/8a84cea7e42c2d94ba5bde1d7a4fae164d6318f13f933d92da6d7c2041ff/ruff-0.14.14-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e651e977a79e4c758eb807f0481d673a67ffe53cfa92209781dfa3a996cf8412", size = 10285491, upload-time = "2026-01-22T22:30:29.51Z" },
1136
- { url = "https://files.pythonhosted.org/packages/55/ef/b7c5ea0be82518906c978e365e56a77f8de7678c8bb6651ccfbdc178c29f/ruff-0.14.14-py3-none-musllinux_1_2_i686.whl", hash = "sha256:cc8b22da8d9d6fdd844a68ae937e2a0adf9b16514e9a97cc60355e2d4b219fc3", size = 10733525, upload-time = "2026-01-22T22:30:06.499Z" },
1137
- { url = "https://files.pythonhosted.org/packages/6a/5b/aaf1dfbcc53a2811f6cc0a1759de24e4b03e02ba8762daabd9b6bd8c59e3/ruff-0.14.14-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:16bc890fb4cc9781bb05beb5ab4cd51be9e7cb376bf1dd3580512b24eb3fda2b", size = 11315626, upload-time = "2026-01-22T22:30:36.848Z" },
1138
- { url = "https://files.pythonhosted.org/packages/2c/aa/9f89c719c467dfaf8ad799b9bae0df494513fb21d31a6059cb5870e57e74/ruff-0.14.14-py3-none-win32.whl", hash = "sha256:b530c191970b143375b6a68e6f743800b2b786bbcf03a7965b06c4bf04568167", size = 10502442, upload-time = "2026-01-22T22:30:38.93Z" },
1139
- { url = "https://files.pythonhosted.org/packages/87/44/90fa543014c45560cae1fffc63ea059fb3575ee6e1cb654562197e5d16fb/ruff-0.14.14-py3-none-win_amd64.whl", hash = "sha256:3dde1435e6b6fe5b66506c1dff67a421d0b7f6488d466f651c07f4cab3bf20fd", size = 11630486, upload-time = "2026-01-22T22:30:10.852Z" },
1140
- { url = "https://files.pythonhosted.org/packages/9e/6a/40fee331a52339926a92e17ae748827270b288a35ef4a15c9c8f2ec54715/ruff-0.14.14-py3-none-win_arm64.whl", hash = "sha256:56e6981a98b13a32236a72a8da421d7839221fa308b223b9283312312e5ac76c", size = 10920448, upload-time = "2026-01-22T22:30:15.417Z" },
1050
+ { url = "https://files.pythonhosted.org/packages/bc/88/3fd1b0aa4b6330d6aaa63a285bc96c9f71970351579152d231ed90914586/ruff-0.15.0-py3-none-linux_armv6l.whl", hash = "sha256:aac4ebaa612a82b23d45964586f24ae9bc23ca101919f5590bdb368d74ad5455", size = 10354332, upload-time = "2026-02-03T17:52:54.892Z" },
1051
+ { url = "https://files.pythonhosted.org/packages/72/f6/62e173fbb7eb75cc29fe2576a1e20f0a46f671a2587b5f604bfb0eaf5f6f/ruff-0.15.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:dcd4be7cc75cfbbca24a98d04d0b9b36a270d0833241f776b788d59f4142b14d", size = 10767189, upload-time = "2026-02-03T17:53:19.778Z" },
1052
+ { url = "https://files.pythonhosted.org/packages/99/e4/968ae17b676d1d2ff101d56dc69cf333e3a4c985e1ec23803df84fc7bf9e/ruff-0.15.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d747e3319b2bce179c7c1eaad3d884dc0a199b5f4d5187620530adf9105268ce", size = 10075384, upload-time = "2026-02-03T17:53:29.241Z" },
1053
+ { url = "https://files.pythonhosted.org/packages/a2/bf/9843c6044ab9e20af879c751487e61333ca79a2c8c3058b15722386b8cae/ruff-0.15.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:650bd9c56ae03102c51a5e4b554d74d825ff3abe4db22b90fd32d816c2e90621", size = 10481363, upload-time = "2026-02-03T17:52:43.332Z" },
1054
+ { url = "https://files.pythonhosted.org/packages/55/d9/4ada5ccf4cd1f532db1c8d44b6f664f2208d3d93acbeec18f82315e15193/ruff-0.15.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a6664b7eac559e3048223a2da77769c2f92b43a6dfd4720cef42654299a599c9", size = 10187736, upload-time = "2026-02-03T17:53:00.522Z" },
1055
+ { url = "https://files.pythonhosted.org/packages/86/e2/f25eaecd446af7bb132af0a1d5b135a62971a41f5366ff41d06d25e77a91/ruff-0.15.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f811f97b0f092b35320d1556f3353bf238763420ade5d9e62ebd2b73f2ff179", size = 10968415, upload-time = "2026-02-03T17:53:15.705Z" },
1056
+ { url = "https://files.pythonhosted.org/packages/e7/dc/f06a8558d06333bf79b497d29a50c3a673d9251214e0d7ec78f90b30aa79/ruff-0.15.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:761ec0a66680fab6454236635a39abaf14198818c8cdf691e036f4bc0f406b2d", size = 11809643, upload-time = "2026-02-03T17:53:23.031Z" },
1057
+ { url = "https://files.pythonhosted.org/packages/dd/45/0ece8db2c474ad7df13af3a6d50f76e22a09d078af63078f005057ca59eb/ruff-0.15.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:940f11c2604d317e797b289f4f9f3fa5555ffe4fb574b55ed006c3d9b6f0eb78", size = 11234787, upload-time = "2026-02-03T17:52:46.432Z" },
1058
+ { url = "https://files.pythonhosted.org/packages/8a/d9/0e3a81467a120fd265658d127db648e4d3acfe3e4f6f5d4ea79fac47e587/ruff-0.15.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bcbca3d40558789126da91d7ef9a7c87772ee107033db7191edefa34e2c7f1b4", size = 11112797, upload-time = "2026-02-03T17:52:49.274Z" },
1059
+ { url = "https://files.pythonhosted.org/packages/b2/cb/8c0b3b0c692683f8ff31351dfb6241047fa873a4481a76df4335a8bff716/ruff-0.15.0-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:9a121a96db1d75fa3eb39c4539e607f628920dd72ff1f7c5ee4f1b768ac62d6e", size = 11033133, upload-time = "2026-02-03T17:53:33.105Z" },
1060
+ { url = "https://files.pythonhosted.org/packages/f8/5e/23b87370cf0f9081a8c89a753e69a4e8778805b8802ccfe175cc410e50b9/ruff-0.15.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5298d518e493061f2eabd4abd067c7e4fb89e2f63291c94332e35631c07c3662", size = 10442646, upload-time = "2026-02-03T17:53:06.278Z" },
1061
+ { url = "https://files.pythonhosted.org/packages/e1/9a/3c94de5ce642830167e6d00b5c75aacd73e6347b4c7fc6828699b150a5ee/ruff-0.15.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:afb6e603d6375ff0d6b0cee563fa21ab570fd15e65c852cb24922cef25050cf1", size = 10195750, upload-time = "2026-02-03T17:53:26.084Z" },
1062
+ { url = "https://files.pythonhosted.org/packages/30/15/e396325080d600b436acc970848d69df9c13977942fb62bb8722d729bee8/ruff-0.15.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:77e515f6b15f828b94dc17d2b4ace334c9ddb7d9468c54b2f9ed2b9c1593ef16", size = 10676120, upload-time = "2026-02-03T17:53:09.363Z" },
1063
+ { url = "https://files.pythonhosted.org/packages/8d/c9/229a23d52a2983de1ad0fb0ee37d36e0257e6f28bfd6b498ee2c76361874/ruff-0.15.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:6f6e80850a01eb13b3e42ee0ebdf6e4497151b48c35051aab51c101266d187a3", size = 11201636, upload-time = "2026-02-03T17:52:57.281Z" },
1064
+ { url = "https://files.pythonhosted.org/packages/6f/b0/69adf22f4e24f3677208adb715c578266842e6e6a3cc77483f48dd999ede/ruff-0.15.0-py3-none-win32.whl", hash = "sha256:238a717ef803e501b6d51e0bdd0d2c6e8513fe9eec14002445134d3907cd46c3", size = 10465945, upload-time = "2026-02-03T17:53:12.591Z" },
1065
+ { url = "https://files.pythonhosted.org/packages/51/ad/f813b6e2c97e9b4598be25e94a9147b9af7e60523b0cb5d94d307c15229d/ruff-0.15.0-py3-none-win_amd64.whl", hash = "sha256:dd5e4d3301dc01de614da3cdffc33d4b1b96fb89e45721f1598e5532ccf78b18", size = 11564657, upload-time = "2026-02-03T17:52:51.893Z" },
1066
+ { url = "https://files.pythonhosted.org/packages/f6/b0/2d823f6e77ebe560f4e397d078487e8d52c1516b331e3521bc75db4272ca/ruff-0.15.0-py3-none-win_arm64.whl", hash = "sha256:c480d632cc0ca3f0727acac8b7d053542d9e114a462a145d0b00e7cd658c515a", size = 10865753, upload-time = "2026-02-03T17:53:03.014Z" },
1141
1067
  ]
1142
1068
 
1143
1069
  [[package]]
1144
1070
  name = "setuptools"
1145
- version = "80.10.2"
1071
+ version = "81.0.0"
1146
1072
  source = { registry = "https://pypi.org/simple" }
1147
- sdist = { url = "https://files.pythonhosted.org/packages/76/95/faf61eb8363f26aa7e1d762267a8d602a1b26d4f3a1e758e92cb3cb8b054/setuptools-80.10.2.tar.gz", hash = "sha256:8b0e9d10c784bf7d262c4e5ec5d4ec94127ce206e8738f29a437945fbc219b70", size = 1200343, upload-time = "2026-01-25T22:38:17.252Z" }
1073
+ sdist = { url = "https://files.pythonhosted.org/packages/0d/1c/73e719955c59b8e424d015ab450f51c0af856ae46ea2da83eba51cc88de1/setuptools-81.0.0.tar.gz", hash = "sha256:487b53915f52501f0a79ccfd0c02c165ffe06631443a886740b91af4b7a5845a", size = 1198299, upload-time = "2026-02-06T21:10:39.601Z" }
1148
1074
  wheels = [
1149
- { url = "https://files.pythonhosted.org/packages/94/b8/f1f62a5e3c0ad2ff1d189590bfa4c46b4f3b6e49cef6f26c6ee4e575394d/setuptools-80.10.2-py3-none-any.whl", hash = "sha256:95b30ddfb717250edb492926c92b5221f7ef3fbcc2b07579bcd4a27da21d0173", size = 1064234, upload-time = "2026-01-25T22:38:15.216Z" },
1075
+ { url = "https://files.pythonhosted.org/packages/e1/e3/c164c88b2e5ce7b24d667b9bd83589cf4f3520d97cad01534cd3c4f55fdb/setuptools-81.0.0-py3-none-any.whl", hash = "sha256:fdd925d5c5d9f62e4b74b30d6dd7828ce236fd6ed998a08d81de62ce5a6310d6", size = 1062021, upload-time = "2026-02-06T21:10:37.175Z" },
1150
1076
  ]
1151
1077
 
1152
1078
  [[package]]
@@ -1205,11 +1131,11 @@ wheels = [
1205
1131
 
1206
1132
  [[package]]
1207
1133
  name = "wcwidth"
1208
- version = "0.5.0"
1134
+ version = "0.6.0"
1209
1135
  source = { registry = "https://pypi.org/simple" }
1210
- sdist = { url = "https://files.pythonhosted.org/packages/64/6e/62daec357285b927e82263a81f3b4c1790215bc77c42530ce4a69d501a43/wcwidth-0.5.0.tar.gz", hash = "sha256:f89c103c949a693bf563377b2153082bf58e309919dfb7f27b04d862a0089333", size = 246585, upload-time = "2026-01-27T01:31:44.942Z" }
1136
+ sdist = { url = "https://files.pythonhosted.org/packages/35/a2/8e3becb46433538a38726c948d3399905a4c7cabd0df578ede5dc51f0ec2/wcwidth-0.6.0.tar.gz", hash = "sha256:cdc4e4262d6ef9a1a57e018384cbeb1208d8abbc64176027e2c2455c81313159", size = 159684, upload-time = "2026-02-06T19:19:40.919Z" }
1211
1137
  wheels = [
1212
- { url = "https://files.pythonhosted.org/packages/f2/3e/45583b67c2ff08ad5a582d316fcb2f11d6cf0a50c7707ac09d212d25bc98/wcwidth-0.5.0-py3-none-any.whl", hash = "sha256:1efe1361b83b0ff7877b81ba57c8562c99cf812158b778988ce17ec061095695", size = 93772, upload-time = "2026-01-27T01:31:43.432Z" },
1138
+ { url = "https://files.pythonhosted.org/packages/68/5a/199c59e0a824a3db2b89c5d2dade7ab5f9624dbf6448dc291b46d5ec94d3/wcwidth-0.6.0-py3-none-any.whl", hash = "sha256:1a3a1e510b553315f8e146c54764f4fb6264ffad731b3d78088cdb1478ffbdad", size = 94189, upload-time = "2026-02-06T19:19:39.646Z" },
1213
1139
  ]
1214
1140
 
1215
1141
  [[package]]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes