chutils 3.4.2__tar.gz → 3.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 (677) hide show
  1. {chutils-3.4.2 → chutils-3.5.0}/PKG-INFO +5 -1
  2. {chutils-3.4.2 → chutils-3.5.0}/ai-lint.toml +9 -0
  3. {chutils-3.4.2 → chutils-3.5.0}/api_map.md +38 -8
  4. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/ai_context_opt_20260728/plan.md +8 -8
  5. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/async_lifecycle_20260728/plan.md +7 -7
  6. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/browser_profiles_20260728/plan.md +12 -12
  7. chutils-3.5.0/conductor/archive/plugins_extension_20260805/plan.md +15 -0
  8. chutils-3.5.0/conductor/archive/plugins_extension_20260805/spec.md +22 -0
  9. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/queue_monitoring_20260728/plan.md +7 -7
  10. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/stream_crypto_20260728/plan.md +7 -7
  11. chutils-3.5.0/conductor/archive/telegram_access_20260729/plan.md +18 -0
  12. chutils-3.5.0/conductor/archive/telegram_formatting_20260729/plan.md +17 -0
  13. chutils-3.5.0/conductor/archive/telegram_keyboard_20260729/plan.md +18 -0
  14. chutils-3.5.0/conductor/archive/telegram_logging_20260729/plan.md +17 -0
  15. chutils-3.5.0/conductor/archive/telegram_media_20260729/plan.md +18 -0
  16. chutils-3.5.0/conductor/archive/telegram_notifier_20260729/plan.md +17 -0
  17. chutils-3.5.0/conductor/archive/telegram_ratelimit_20260729/plan.md +19 -0
  18. chutils-3.5.0/conductor/archive/telegram_send_file_20260729/plan.md +18 -0
  19. chutils-3.5.0/conductor/archive/telegram_whitelist_20260729/plan.md +17 -0
  20. chutils-3.5.0/conductor/archive/vk_callback_20260807/index.md +5 -0
  21. chutils-3.5.0/conductor/archive/vk_callback_20260807/metadata.json +8 -0
  22. chutils-3.5.0/conductor/archive/vk_callback_20260807/plan.md +19 -0
  23. chutils-3.5.0/conductor/archive/vk_callback_20260807/spec.md +27 -0
  24. chutils-3.5.0/conductor/archive/vk_scaffold_20260807/index.md +5 -0
  25. chutils-3.5.0/conductor/archive/vk_scaffold_20260807/metadata.json +8 -0
  26. chutils-3.5.0/conductor/archive/vk_scaffold_20260807/plan.md +19 -0
  27. chutils-3.5.0/conductor/archive/vk_scaffold_20260807/spec.md +27 -0
  28. chutils-3.5.0/conductor/archive/vk_testing_20260807/index.md +5 -0
  29. chutils-3.5.0/conductor/archive/vk_testing_20260807/metadata.json +8 -0
  30. chutils-3.5.0/conductor/archive/vk_testing_20260807/plan.md +18 -0
  31. chutils-3.5.0/conductor/archive/vk_testing_20260807/spec.md +23 -0
  32. chutils-3.5.0/conductor/archive/vkma_20260807/index.md +5 -0
  33. chutils-3.5.0/conductor/archive/vkma_20260807/metadata.json +8 -0
  34. chutils-3.5.0/conductor/archive/vkma_20260807/plan.md +22 -0
  35. chutils-3.5.0/conductor/archive/vkma_20260807/spec.md +29 -0
  36. {chutils-3.4.2 → chutils-3.5.0}/conductor/product.md +11 -0
  37. chutils-3.5.0/conductor/tracks.md +31 -0
  38. {chutils-3.4.2 → chutils-3.5.0}/docs/ai_lint.md +28 -1
  39. {chutils-3.4.2 → chutils-3.5.0}/docs/api.md +42 -0
  40. {chutils-3.4.2 → chutils-3.5.0}/docs/cli/check.md +97 -97
  41. {chutils-3.4.2 → chutils-3.5.0}/docs/cli/dev.md +5 -2
  42. {chutils-3.4.2 → chutils-3.5.0}/docs/plugins.md +3 -1
  43. {chutils-3.4.2 → chutils-3.5.0}/docs/scraping.md +25 -3
  44. chutils-3.5.0/docs/telegram.md +323 -0
  45. chutils-3.5.0/docs/vk_bot.md +43 -0
  46. chutils-3.5.0/docs/vk_testing.md +17 -0
  47. chutils-3.5.0/docs/vkma.md +129 -0
  48. {chutils-3.4.2 → chutils-3.5.0}/project_index.json +6895 -2562
  49. {chutils-3.4.2 → chutils-3.5.0}/pyproject.toml +7 -1
  50. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/__init__.py +32 -0
  51. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/audit/backends/postgres.py +39 -7
  52. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/cache/decorator.py +2 -1
  53. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/cli_booster.py +1 -1
  54. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/check.py +238 -238
  55. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/db.py +1 -1
  56. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/dev/__init__.py +50 -0
  57. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/dev/clean.py +5 -1
  58. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/dev/generate_context.py +117 -19
  59. chutils-3.5.0/src/chutils/commands/dev/lock.py +129 -0
  60. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/init.py +13 -1
  61. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/config/__init__.py +2 -4
  62. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/config/core.py +6 -6
  63. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/config/custom_providers.py +2 -2
  64. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/config/dev.py +1 -1
  65. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/config/diagnostics.py +1 -1
  66. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/config/getters.py +2 -2
  67. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/config/manager.py +89 -21
  68. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/config/providers.py +2 -2
  69. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/config/utils.py +3 -3
  70. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/config/watcher.py +2 -2
  71. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/context.py +1 -1
  72. chutils-3.5.0/src/chutils/crypto.py +384 -0
  73. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/db.py +1 -3
  74. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/decorators.py +2 -2
  75. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/ast_indexer.py +9 -124
  76. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/changelog_parser.py +5 -2
  77. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/cleaner.py +1 -1
  78. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/constants.py +1 -1
  79. chutils-3.5.0/src/chutils/dev/context/__init__.py +6 -0
  80. chutils-3.5.0/src/chutils/dev/context/gitignore.py +151 -0
  81. chutils-3.5.0/src/chutils/dev/context/incremental.py +126 -0
  82. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/few_shot/writer.py +7 -1
  83. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/profile_imports.py +6 -2
  84. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/project_metadata.py +31 -9
  85. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/rules/linter_coverage.py +13 -2
  86. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/rules/upgrade_check.py +46 -14
  87. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/scaffold.py +1 -1
  88. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/version_detector.py +58 -2
  89. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/diagnostics/manager.py +1 -1
  90. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/events/core.py +3 -1
  91. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/exceptions/__init__.py +5 -0
  92. chutils-3.5.0/src/chutils/exceptions/telegram.py +17 -0
  93. chutils-3.5.0/src/chutils/exceptions/vkma.py +13 -0
  94. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/http/client.py +1 -1
  95. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/http/resilience.py +1 -1
  96. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/http/streaming.py +2 -2
  97. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/lifecycle.py +106 -3
  98. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/logger/formatters.py +9 -1
  99. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/logger/internal/builder.py +25 -8
  100. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/logger/internal/utils.py +2 -2
  101. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/plugins/__init__.py +4 -0
  102. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/plugins/core.py +42 -0
  103. chutils-3.5.0/src/chutils/plugins/interfaces.py +165 -0
  104. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/qt/__init__.py +1 -1
  105. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/qt/logging.py +1 -1
  106. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/qt/shim.py +1 -1
  107. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/qt/signals.py +7 -1
  108. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/qt/widgets.py +1 -1
  109. chutils-3.5.0/src/chutils/scaffold.py +53 -0
  110. chutils-3.5.0/src/chutils/scraping/__init__.py +33 -0
  111. chutils-3.5.0/src/chutils/scraping/concurrency/metrics.py +65 -0
  112. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/scraping/concurrency/pool.py +15 -0
  113. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/scraping/concurrency/queues.py +21 -4
  114. chutils-3.5.0/src/chutils/scraping/profiles/__init__.py +23 -0
  115. chutils-3.5.0/src/chutils/scraping/profiles/adapters/__init__.py +23 -0
  116. chutils-3.5.0/src/chutils/scraping/profiles/adapters/nodriver.py +98 -0
  117. chutils-3.5.0/src/chutils/scraping/profiles/adapters/playwright.py +104 -0
  118. chutils-3.5.0/src/chutils/scraping/profiles/adapters/selenium.py +85 -0
  119. chutils-3.5.0/src/chutils/scraping/profiles/manager.py +128 -0
  120. chutils-3.5.0/src/chutils/scraping/profiles/models.py +45 -0
  121. chutils-3.5.0/src/chutils/scraping/profiles/storage.py +82 -0
  122. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/secret_manager/providers/gcp.py +4 -2
  123. chutils-3.5.0/src/chutils/telegram/__init__.py +37 -0
  124. chutils-3.5.0/src/chutils/telegram/access.py +173 -0
  125. chutils-3.5.0/src/chutils/telegram/aiogram.py +191 -0
  126. chutils-3.5.0/src/chutils/telegram/formatting.py +165 -0
  127. chutils-3.5.0/src/chutils/telegram/keyboard.py +193 -0
  128. chutils-3.5.0/src/chutils/telegram/logging.py +97 -0
  129. chutils-3.5.0/src/chutils/telegram/media.py +211 -0
  130. chutils-3.5.0/src/chutils/telegram/notifier.py +204 -0
  131. chutils-3.5.0/src/chutils/telegram/rate_limit.py +166 -0
  132. chutils-3.5.0/src/chutils/telegram/whitelist.py +266 -0
  133. chutils-3.5.0/src/chutils/templates/vk/vk-miniapp/backend/config.yml.template +9 -0
  134. chutils-3.5.0/src/chutils/templates/vk/vk-miniapp/backend/main.py.template +42 -0
  135. chutils-3.5.0/src/chutils/templates/vk/vk-miniapp/docker-compose.yml.template +14 -0
  136. chutils-3.5.0/src/chutils/templates/vk/vk-miniapp/frontend/App.jsx.template +56 -0
  137. chutils-3.5.0/src/chutils/vk/__init__.py +8 -0
  138. chutils-3.5.0/src/chutils/vk/callback/__init__.py +8 -0
  139. chutils-3.5.0/src/chutils/vk/callback/router.py +211 -0
  140. chutils-3.5.0/src/chutils/vk/testing/__init__.py +16 -0
  141. chutils-3.5.0/src/chutils/vk/testing/fixtures.py +107 -0
  142. chutils-3.5.0/src/chutils/vk/testing/generators.py +121 -0
  143. chutils-3.5.0/src/chutils/vkma/__init__.py +14 -0
  144. chutils-3.5.0/src/chutils/vkma/exceptions.py +5 -0
  145. chutils-3.5.0/src/chutils/vkma/integrations/__init__.py +12 -0
  146. chutils-3.5.0/src/chutils/vkma/integrations/aiohttp.py +65 -0
  147. chutils-3.5.0/src/chutils/vkma/integrations/fastapi.py +124 -0
  148. chutils-3.5.0/src/chutils/vkma/integrations/flask.py +62 -0
  149. chutils-3.5.0/src/chutils/vkma/models.py +60 -0
  150. chutils-3.5.0/src/chutils/vkma/testing.py +17 -0
  151. chutils-3.5.0/src/chutils/vkma/validator.py +167 -0
  152. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli_check.py +60 -60
  153. chutils-3.5.0/tests/unit/cli/test_cli_dev_lock.py +67 -0
  154. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/core/test_lifecycle.py +35 -0
  155. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/dev/test_changelog_parser.py +13 -0
  156. chutils-3.5.0/tests/unit/dev/test_context_generator.py +46 -0
  157. chutils-3.5.0/tests/unit/dev/test_upgrade_check_rule.py +101 -0
  158. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/plugins/test_plugins.py +38 -0
  159. chutils-3.5.0/tests/unit/scraping/test_profile_adapters.py +108 -0
  160. chutils-3.5.0/tests/unit/scraping/test_profile_manager.py +70 -0
  161. chutils-3.5.0/tests/unit/scraping/test_profile_storage.py +75 -0
  162. chutils-3.5.0/tests/unit/scraping/test_queue_metrics.py +52 -0
  163. chutils-3.5.0/tests/unit/scraping/test_worker_metrics.py +25 -0
  164. chutils-3.5.0/tests/unit/telegram/test_access.py +72 -0
  165. chutils-3.5.0/tests/unit/telegram/test_aiogram_filter.py +46 -0
  166. chutils-3.5.0/tests/unit/telegram/test_aiogram_middleware.py +40 -0
  167. chutils-3.5.0/tests/unit/telegram/test_formatting.py +64 -0
  168. chutils-3.5.0/tests/unit/telegram/test_keyboard.py +56 -0
  169. chutils-3.5.0/tests/unit/telegram/test_logging.py +28 -0
  170. chutils-3.5.0/tests/unit/telegram/test_notifier.py +59 -0
  171. chutils-3.5.0/tests/unit/telegram/test_telegram_rate_limit.py +53 -0
  172. chutils-3.5.0/tests/unit/telegram/test_whitelist.py +43 -0
  173. chutils-3.5.0/tests/unit/test_crypto_stream.py +77 -0
  174. chutils-3.5.0/tests/unit/test_init_templates.py +23 -0
  175. chutils-3.5.0/tests/unit/test_telegram_media.py +82 -0
  176. chutils-3.5.0/tests/unit/test_telegram_send_file.py +71 -0
  177. chutils-3.5.0/tests/unit/test_vk_callback_fastapi.py +52 -0
  178. chutils-3.5.0/tests/unit/test_vk_callback_router.py +40 -0
  179. chutils-3.5.0/tests/unit/test_vk_testing_fixtures.py +31 -0
  180. chutils-3.5.0/tests/unit/test_vk_testing_generators.py +42 -0
  181. chutils-3.5.0/tests/unit/test_vkma_core.py +111 -0
  182. chutils-3.5.0/tests/unit/test_vkma_integrations.py +120 -0
  183. {chutils-3.4.2 → chutils-3.5.0}/uv.lock +10 -2
  184. chutils-3.4.2/conductor/tracks/telegram_access_20260729/plan.md +0 -18
  185. chutils-3.4.2/conductor/tracks/telegram_formatting_20260729/plan.md +0 -17
  186. chutils-3.4.2/conductor/tracks/telegram_keyboard_20260729/plan.md +0 -18
  187. chutils-3.4.2/conductor/tracks/telegram_logging_20260729/plan.md +0 -17
  188. chutils-3.4.2/conductor/tracks/telegram_media_20260729/plan.md +0 -18
  189. chutils-3.4.2/conductor/tracks/telegram_notifier_20260729/plan.md +0 -17
  190. chutils-3.4.2/conductor/tracks/telegram_ratelimit_20260729/plan.md +0 -19
  191. chutils-3.4.2/conductor/tracks/telegram_send_file_20260729/plan.md +0 -18
  192. chutils-3.4.2/conductor/tracks/telegram_whitelist_20260729/plan.md +0 -17
  193. chutils-3.4.2/conductor/tracks.md +0 -91
  194. chutils-3.4.2/src/chutils/crypto.py +0 -179
  195. chutils-3.4.2/src/chutils/plugins/interfaces.py +0 -88
  196. chutils-3.4.2/src/chutils/scraping/__init__.py +0 -5
  197. chutils-3.4.2/tests/unit/dev/test_upgrade_check_rule.py +0 -55
  198. {chutils-3.4.2 → chutils-3.5.0}/.chutilsignore +0 -0
  199. {chutils-3.4.2 → chutils-3.5.0}/.gitattributes +0 -0
  200. {chutils-3.4.2 → chutils-3.5.0}/.github/workflows/ci.yml +0 -0
  201. {chutils-3.4.2 → chutils-3.5.0}/.github/workflows/publish-docs.yml +0 -0
  202. {chutils-3.4.2 → chutils-3.5.0}/.gitignore +0 -0
  203. {chutils-3.4.2 → chutils-3.5.0}/CODE_OF_CONDUCT.md +0 -0
  204. {chutils-3.4.2 → chutils-3.5.0}/CONTRIBUTING.md +0 -0
  205. {chutils-3.4.2 → chutils-3.5.0}/GEMINI.md +0 -0
  206. {chutils-3.4.2 → chutils-3.5.0}/LICENSE +0 -0
  207. {chutils-3.4.2 → chutils-3.5.0}/README.md +0 -0
  208. {chutils-3.4.2 → chutils-3.5.0}/benchmarks/cold_start.py +0 -0
  209. {chutils-3.4.2 → chutils-3.5.0}/conductor/.gitignore +0 -0
  210. {chutils-3.4.2 → chutils-3.5.0}/conductor/GEMINI.md +0 -0
  211. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/ai_context_opt_20260728/index.md +0 -0
  212. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/ai_context_opt_20260728/metadata.json +0 -0
  213. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/ai_context_opt_20260728/spec.md +0 -0
  214. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/async_lifecycle_20260728/index.md +0 -0
  215. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/async_lifecycle_20260728/metadata.json +0 -0
  216. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/async_lifecycle_20260728/spec.md +0 -0
  217. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/browser_profiles_20260728/index.md +0 -0
  218. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/browser_profiles_20260728/metadata.json +0 -0
  219. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/browser_profiles_20260728/spec.md +0 -0
  220. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/queue_monitoring_20260728/index.md +0 -0
  221. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/queue_monitoring_20260728/metadata.json +0 -0
  222. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/queue_monitoring_20260728/spec.md +0 -0
  223. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/stream_crypto_20260728/index.md +0 -0
  224. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/stream_crypto_20260728/metadata.json +0 -0
  225. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/stream_crypto_20260728/spec.md +0 -0
  226. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_access_20260729/index.md +0 -0
  227. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_access_20260729/metadata.json +0 -0
  228. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_access_20260729/spec.md +0 -0
  229. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_formatting_20260729/index.md +0 -0
  230. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_formatting_20260729/metadata.json +0 -0
  231. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_formatting_20260729/spec.md +0 -0
  232. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_keyboard_20260729/index.md +0 -0
  233. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_keyboard_20260729/metadata.json +0 -0
  234. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_keyboard_20260729/spec.md +0 -0
  235. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_logging_20260729/index.md +0 -0
  236. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_logging_20260729/metadata.json +0 -0
  237. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_logging_20260729/spec.md +0 -0
  238. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_media_20260729/index.md +0 -0
  239. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_media_20260729/metadata.json +0 -0
  240. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_media_20260729/spec.md +0 -0
  241. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_notifier_20260729/index.md +0 -0
  242. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_notifier_20260729/metadata.json +0 -0
  243. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_notifier_20260729/spec.md +0 -0
  244. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_ratelimit_20260729/index.md +0 -0
  245. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_ratelimit_20260729/metadata.json +0 -0
  246. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_ratelimit_20260729/spec.md +0 -0
  247. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_send_file_20260729/index.md +0 -0
  248. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_send_file_20260729/metadata.json +0 -0
  249. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_send_file_20260729/spec.md +0 -0
  250. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_whitelist_20260729/index.md +0 -0
  251. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_whitelist_20260729/metadata.json +0 -0
  252. {chutils-3.4.2/conductor/tracks → chutils-3.5.0/conductor/archive}/telegram_whitelist_20260729/spec.md +0 -0
  253. {chutils-3.4.2 → chutils-3.5.0}/conductor/code_styleguides/python.md +0 -0
  254. {chutils-3.4.2 → chutils-3.5.0}/conductor/index.md +0 -0
  255. {chutils-3.4.2 → chutils-3.5.0}/conductor/product-guidelines.md +0 -0
  256. {chutils-3.4.2 → chutils-3.5.0}/conductor/setup_state.json +0 -0
  257. {chutils-3.4.2 → chutils-3.5.0}/conductor/tech-stack.md +0 -0
  258. {chutils-3.4.2 → chutils-3.5.0}/conductor/workflow.md +0 -0
  259. {chutils-3.4.2 → chutils-3.5.0}/docs/CODE_OF_CONDUCT_RU.md +0 -0
  260. {chutils-3.4.2 → chutils-3.5.0}/docs/CONTRIBUTING_RU.md +0 -0
  261. {chutils-3.4.2 → chutils-3.5.0}/docs/INTEGRATION_AI.md +0 -0
  262. {chutils-3.4.2 → chutils-3.5.0}/docs/README_RU.md +0 -0
  263. {chutils-3.4.2 → chutils-3.5.0}/docs/ai_examples/README.md +0 -0
  264. {chutils-3.4.2 → chutils-3.5.0}/docs/ai_examples/configuration/README.md +0 -0
  265. {chutils-3.4.2 → chutils-3.5.0}/docs/ai_examples/configuration/bad_pattern.py +0 -0
  266. {chutils-3.4.2 → chutils-3.5.0}/docs/ai_examples/configuration/good_pattern.py +0 -0
  267. {chutils-3.4.2 → chutils-3.5.0}/docs/ai_examples/error_handling/README.md +0 -0
  268. {chutils-3.4.2 → chutils-3.5.0}/docs/ai_examples/error_handling/bad_pattern.py +0 -0
  269. {chutils-3.4.2 → chutils-3.5.0}/docs/ai_examples/error_handling/good_pattern.py +0 -0
  270. {chutils-3.4.2 → chutils-3.5.0}/docs/ai_examples/logging/README.md +0 -0
  271. {chutils-3.4.2 → chutils-3.5.0}/docs/ai_examples/logging/bad_pattern.py +0 -0
  272. {chutils-3.4.2 → chutils-3.5.0}/docs/ai_examples/logging/good_pattern.py +0 -0
  273. {chutils-3.4.2 → chutils-3.5.0}/docs/ai_examples/optional_deps/README.md +0 -0
  274. {chutils-3.4.2 → chutils-3.5.0}/docs/ai_examples/optional_deps/bad_pattern.py +0 -0
  275. {chutils-3.4.2 → chutils-3.5.0}/docs/ai_examples/optional_deps/good_pattern.py +0 -0
  276. {chutils-3.4.2 → chutils-3.5.0}/docs/ai_examples/secrets/README.md +0 -0
  277. {chutils-3.4.2 → chutils-3.5.0}/docs/ai_examples/secrets/bad_pattern.py +0 -0
  278. {chutils-3.4.2 → chutils-3.5.0}/docs/ai_examples/secrets/good_pattern.py +0 -0
  279. {chutils-3.4.2 → chutils-3.5.0}/docs/ai_hints.md +0 -0
  280. {chutils-3.4.2 → chutils-3.5.0}/docs/audit.md +0 -0
  281. {chutils-3.4.2 → chutils-3.5.0}/docs/captcha.md +0 -0
  282. {chutils-3.4.2 → chutils-3.5.0}/docs/cli/config.md +0 -0
  283. {chutils-3.4.2 → chutils-3.5.0}/docs/cli/db.md +0 -0
  284. {chutils-3.4.2 → chutils-3.5.0}/docs/cli/env.md +0 -0
  285. {chutils-3.4.2 → chutils-3.5.0}/docs/cli/index.md +0 -0
  286. {chutils-3.4.2 → chutils-3.5.0}/docs/cli/init.md +0 -0
  287. {chutils-3.4.2 → chutils-3.5.0}/docs/cli/pypi.md +0 -0
  288. {chutils-3.4.2 → chutils-3.5.0}/docs/cli/secrets.md +0 -0
  289. {chutils-3.4.2 → chutils-3.5.0}/docs/cli/show_paths.md +0 -0
  290. {chutils-3.4.2 → chutils-3.5.0}/docs/cli/template.md +0 -0
  291. {chutils-3.4.2 → chutils-3.5.0}/docs/cli/validate.md +0 -0
  292. {chutils-3.4.2 → chutils-3.5.0}/docs/custom_config_providers.md +0 -0
  293. {chutils-3.4.2 → chutils-3.5.0}/docs/dependencies.md +0 -0
  294. {chutils-3.4.2 → chutils-3.5.0}/docs/http.md +0 -0
  295. {chutils-3.4.2 → chutils-3.5.0}/docs/index.md +0 -0
  296. {chutils-3.4.2 → chutils-3.5.0}/docs/migration.md +0 -0
  297. {chutils-3.4.2 → chutils-3.5.0}/docs/qt.md +0 -0
  298. {chutils-3.4.2 → chutils-3.5.0}/docs/recipes.md +0 -0
  299. {chutils-3.4.2 → chutils-3.5.0}/docs/store.md +0 -0
  300. {chutils-3.4.2 → chutils-3.5.0}/docs/testing.md +0 -0
  301. {chutils-3.4.2 → chutils-3.5.0}/docs/web.md +0 -0
  302. {chutils-3.4.2 → chutils-3.5.0}/examples/.env +0 -0
  303. {chutils-3.4.2 → chutils-3.5.0}/examples/01_configuration.py +0 -0
  304. {chutils-3.4.2 → chutils-3.5.0}/examples/02_logging.py +0 -0
  305. {chutils-3.4.2 → chutils-3.5.0}/examples/03_secrets.py +0 -0
  306. {chutils-3.4.2 → chutils-3.5.0}/examples/04_full_example.py +0 -0
  307. {chutils-3.4.2 → chutils-3.5.0}/examples/05_different_log_levels.py +0 -0
  308. {chutils-3.4.2 → chutils-3.5.0}/examples/06_local_config_override.py +0 -0
  309. {chutils-3.4.2 → chutils-3.5.0}/examples/07_decorators_example.py +0 -0
  310. {chutils-3.4.2 → chutils-3.5.0}/examples/08_multiple_loggers_example.py +0 -0
  311. {chutils-3.4.2 → chutils-3.5.0}/examples/09_disable_keyring.py +0 -0
  312. {chutils-3.4.2 → chutils-3.5.0}/examples/10_universal_env_override.py +0 -0
  313. {chutils-3.4.2 → chutils-3.5.0}/examples/11_retry_decorator.py +0 -0
  314. {chutils-3.4.2 → chutils-3.5.0}/examples/12_secret_masking.py +0 -0
  315. {chutils-3.4.2 → chutils-3.5.0}/examples/13_pydantic_validation.py +0 -0
  316. {chutils-3.4.2 → chutils-3.5.0}/examples/15_context_logging.py +0 -0
  317. {chutils-3.4.2 → chutils-3.5.0}/examples/16_cloud_secret_managers.py +0 -0
  318. {chutils-3.4.2 → chutils-3.5.0}/examples/17_timeout_decorator.py +0 -0
  319. {chutils-3.4.2 → chutils-3.5.0}/examples/18_config_hot_reload.py +0 -0
  320. {chutils-3.4.2 → chutils-3.5.0}/examples/19_remote_config.py +0 -0
  321. {chutils-3.4.2 → chutils-3.5.0}/examples/20_opentelemetry_tracing.py +0 -0
  322. {chutils-3.4.2 → chutils-3.5.0}/examples/21_config_diagnostics.py +0 -0
  323. {chutils-3.4.2 → chutils-3.5.0}/examples/22_circuit_breaker_decorator.py +0 -0
  324. {chutils-3.4.2 → chutils-3.5.0}/examples/22_qt_logging.py +0 -0
  325. {chutils-3.4.2 → chutils-3.5.0}/examples/22_safe_path_resolution.py +0 -0
  326. {chutils-3.4.2 → chutils-3.5.0}/examples/23_event_bus.py +0 -0
  327. {chutils-3.4.2 → chutils-3.5.0}/examples/23_qt_async.py +0 -0
  328. {chutils-3.4.2 → chutils-3.5.0}/examples/24_qt_typed_signals.py +0 -0
  329. {chutils-3.4.2 → chutils-3.5.0}/examples/24_task_scheduler.py +0 -0
  330. {chutils-3.4.2 → chutils-3.5.0}/examples/25_testing_fixtures_example.py +0 -0
  331. {chutils-3.4.2 → chutils-3.5.0}/examples/26_metrics_prometheus.py +0 -0
  332. {chutils-3.4.2 → chutils-3.5.0}/examples/27_rate_limiting.py +0 -0
  333. {chutils-3.4.2 → chutils-3.5.0}/examples/28_dependency_injection.py +0 -0
  334. {chutils-3.4.2 → chutils-3.5.0}/examples/captcha_solvers_usage.py +0 -0
  335. {chutils-3.4.2 → chutils-3.5.0}/examples/concurrency_scraping_usage.py +0 -0
  336. {chutils-3.4.2 → chutils-3.5.0}/examples/config.yml +0 -0
  337. {chutils-3.4.2 → chutils-3.5.0}/examples/scraping_humanize_usage.py +0 -0
  338. {chutils-3.4.2 → chutils-3.5.0}/examples/web_client_usage.py +0 -0
  339. {chutils-3.4.2 → chutils-3.5.0}/mkdocs.yml +0 -0
  340. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/__init__.pyi +0 -0
  341. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/__main__.py +0 -0
  342. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/antigravity.md +0 -0
  343. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/audit/__init__.py +0 -0
  344. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/audit/_hash.py +0 -0
  345. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/audit/api.py +0 -0
  346. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/audit/backends/__init__.py +0 -0
  347. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/audit/backends/base.py +0 -0
  348. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/audit/backends/file.py +0 -0
  349. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/audit/backends/sqlite.py +0 -0
  350. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/audit/schema.py +0 -0
  351. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/cache/__init__.py +0 -0
  352. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/cache/base.py +0 -0
  353. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/cache/in_memory.py +0 -0
  354. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/cache/utils.py +0 -0
  355. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/cli.py +0 -0
  356. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/cli_utils.py +0 -0
  357. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/__init__.py +0 -0
  358. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/base.py +0 -0
  359. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/config.py +0 -0
  360. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/dev/ai_lint.py +0 -0
  361. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/dev/base.py +0 -0
  362. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/dev/chat_context.py +0 -0
  363. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/dev/dashboard.py +0 -0
  364. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/dev/diagnostics.py +0 -0
  365. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/dev/few_shot.py +0 -0
  366. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/dev/hooks.py +0 -0
  367. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/dev/mock.py +0 -0
  368. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/dev/profile_imports.py +0 -0
  369. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/dev/scaffold.py +0 -0
  370. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/dev/setup_github_actions.py +0 -0
  371. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/dev/sync_env.py +0 -0
  372. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/dev/watch.py +0 -0
  373. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/env.py +0 -0
  374. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/paths.py +0 -0
  375. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/pypi.py +0 -0
  376. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/secrets.py +0 -0
  377. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/template.py +0 -0
  378. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/utils.py +0 -0
  379. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/commands/validate.py +0 -0
  380. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/config/GEMINI.md +0 -0
  381. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/config/ast_fallback_parser.py +0 -0
  382. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/config/generator.py +0 -0
  383. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/config/integrations.py +0 -0
  384. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/config/schema.py +0 -0
  385. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/config/sse.py +0 -0
  386. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/config/webhook_server.py +0 -0
  387. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/__init__.py +0 -0
  388. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/ai_lint.py +0 -0
  389. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/chat_context.py +0 -0
  390. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/dashboard/__init__.py +0 -0
  391. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/dashboard/indexer.py +0 -0
  392. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/dashboard/input.py +0 -0
  393. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/dashboard/tui.py +0 -0
  394. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/env_parser.py +0 -0
  395. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/env_sync.py +0 -0
  396. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/few_shot/__init__.py +0 -0
  397. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/few_shot/detector.py +0 -0
  398. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/few_shot/models.py +0 -0
  399. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/few_shot/renderer.py +0 -0
  400. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/github_actions.py +0 -0
  401. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/mock_server.py +0 -0
  402. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/models/__init__.py +0 -0
  403. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/models/base.py +0 -0
  404. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/models/index.py +0 -0
  405. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/models/node.py +0 -0
  406. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/models/symbol.py +0 -0
  407. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/rules/__init__.py +0 -0
  408. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/rules/api_map.py +0 -0
  409. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/rules/decomposition.py +0 -0
  410. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/rules/dependency_sync.py +0 -0
  411. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/rules/docstring.py +0 -0
  412. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/rules/env.py +0 -0
  413. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/rules/integration.py +0 -0
  414. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/rules/manifest.py +0 -0
  415. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/rules/security.py +0 -0
  416. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/runners.py +0 -0
  417. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/upgrade_client.py +0 -0
  418. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/dev/watcher.py +0 -0
  419. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/di/__init__.py +0 -0
  420. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/di/__init__.pyi +0 -0
  421. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/di/container.py +0 -0
  422. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/diagnostics/__init__.py +0 -0
  423. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/diagnostics/models.py +0 -0
  424. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/diagnostics/web.py +0 -0
  425. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/env.py +0 -0
  426. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/env.pyi +0 -0
  427. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/events/__init__.py +0 -0
  428. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/exceptions/audit.py +0 -0
  429. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/exceptions/base.py +0 -0
  430. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/exceptions/cache.py +0 -0
  431. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/exceptions/config.py +0 -0
  432. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/exceptions/di.py +0 -0
  433. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/exceptions/events.py +0 -0
  434. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/exceptions/logger.py +0 -0
  435. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/exceptions/resilience.py +0 -0
  436. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/exceptions/secrets.py +0 -0
  437. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/exceptions/system.py +0 -0
  438. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/exceptions/validation.py +0 -0
  439. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/exceptions/watcher.py +0 -0
  440. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/features.py +0 -0
  441. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/fs.py +0 -0
  442. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/http/__init__.py +0 -0
  443. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/http/api.py +0 -0
  444. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/http/fallback.py +0 -0
  445. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/http/tracing.py +0 -0
  446. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/logger/GEMINI.md +0 -0
  447. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/logger/__init__.py +0 -0
  448. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/logger/core.py +0 -0
  449. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/logger/handlers.py +0 -0
  450. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/logger/internal/levels.py +0 -0
  451. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/logger/masking.py +0 -0
  452. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/metrics/__init__.py +0 -0
  453. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/metrics/base.py +0 -0
  454. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/metrics/in_memory.py +0 -0
  455. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/metrics/prometheus.py +0 -0
  456. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/metrics/timer.py +0 -0
  457. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/qt/asyncio.py +0 -0
  458. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/scraping/captcha/__init__.py +0 -0
  459. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/scraping/captcha/anticaptcha.py +0 -0
  460. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/scraping/captcha/base.py +0 -0
  461. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/scraping/captcha/capmonster.py +0 -0
  462. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/scraping/captcha/exceptions.py +0 -0
  463. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/scraping/captcha/rucaptcha.py +0 -0
  464. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/scraping/concurrency/__init__.py +0 -0
  465. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/scraping/concurrency/base.py +0 -0
  466. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/scraping/concurrency/limiter.py +0 -0
  467. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/scraping/concurrency/models.py +0 -0
  468. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/scraping/humanize/__init__.py +0 -0
  469. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/scraping/humanize/actions.py +0 -0
  470. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/scraping/humanize/antidetect.py +0 -0
  471. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/scraping/humanize/math_utils.py +0 -0
  472. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/scraping/humanize/warmer.py +0 -0
  473. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/secret_manager/GEMINI.md +0 -0
  474. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/secret_manager/__init__.py +0 -0
  475. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/secret_manager/core.py +0 -0
  476. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/secret_manager/providers/__init__.py +0 -0
  477. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/secret_manager/providers/aws.py +0 -0
  478. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/secret_manager/providers/base.py +0 -0
  479. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/secret_manager/providers/dotenv.py +0 -0
  480. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/secret_manager/providers/env.py +0 -0
  481. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/secret_manager/providers/keyring_provider.py +0 -0
  482. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/store/__init__.py +0 -0
  483. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/store/backends/__init__.py +0 -0
  484. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/store/backends/base.py +0 -0
  485. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/store/backends/memcached.py +0 -0
  486. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/store/backends/memory.py +0 -0
  487. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/store/backends/redis.py +0 -0
  488. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/store/decorator.py +0 -0
  489. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/store/manager.py +0 -0
  490. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/tasks/__init__.py +0 -0
  491. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/tasks/__init__.pyi +0 -0
  492. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/tasks/core.py +0 -0
  493. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/testing/__init__.py +0 -0
  494. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/testing/fixtures.py +0 -0
  495. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/text.py +0 -0
  496. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/time.py +0 -0
  497. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/tracing.py +0 -0
  498. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/typing.py +0 -0
  499. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/validation.py +0 -0
  500. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/validation.pyi +0 -0
  501. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/web/__init__.py +0 -0
  502. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/web/client.py +0 -0
  503. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/web/proxy_pool.py +0 -0
  504. {chutils-3.4.2 → chutils-3.5.0}/src/chutils/web/user_agent.py +0 -0
  505. {chutils-3.4.2 → chutils-3.5.0}/tests/conftest.py +0 -0
  506. {chutils-3.4.2 → chutils-3.5.0}/tests/integration/__init__.py +0 -0
  507. {chutils-3.4.2 → chutils-3.5.0}/tests/integration/test_ai_lint_integration.py +0 -0
  508. {chutils-3.4.2 → chutils-3.5.0}/tests/integration/test_cli_e2e.py +0 -0
  509. {chutils-3.4.2 → chutils-3.5.0}/tests/integration/test_db_migrations.py +0 -0
  510. {chutils-3.4.2 → chutils-3.5.0}/tests/integration/test_event_loops.py +0 -0
  511. {chutils-3.4.2 → chutils-3.5.0}/tests/integration/test_examples.py +0 -0
  512. {chutils-3.4.2 → chutils-3.5.0}/tests/integration/test_hooks_integration.py +0 -0
  513. {chutils-3.4.2 → chutils-3.5.0}/tests/integration/test_masking_integration.py +0 -0
  514. {chutils-3.4.2 → chutils-3.5.0}/tests/integration/test_otel_tracing.py +0 -0
  515. {chutils-3.4.2 → chutils-3.5.0}/tests/integration/test_remote_config_integration.py +0 -0
  516. {chutils-3.4.2 → chutils-3.5.0}/tests/integration/test_setup_github_actions_integration.py +0 -0
  517. {chutils-3.4.2 → chutils-3.5.0}/tests/manual/manual_test_cli_booster.py +0 -0
  518. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/conftest.py +0 -0
  519. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli.py +0 -0
  520. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli_booster.py +0 -0
  521. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli_config.py +0 -0
  522. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli_config_cmd.py +0 -0
  523. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli_config_schema.py +0 -0
  524. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli_dev.py +0 -0
  525. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli_dev_cmd.py +0 -0
  526. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli_dev_tree.py +0 -0
  527. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli_dev_watch.py +0 -0
  528. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli_diagnostics.py +0 -0
  529. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli_extras_suggestion.py +0 -0
  530. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli_init.py +0 -0
  531. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli_init_interactive.py +0 -0
  532. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli_paths.py +0 -0
  533. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli_pypi.py +0 -0
  534. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli_rich.py +0 -0
  535. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli_rich_width.py +0 -0
  536. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli_secrets.py +0 -0
  537. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli_setup_github_actions.py +0 -0
  538. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli_template.py +0 -0
  539. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli_utils_internal.py +0 -0
  540. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/cli/test_cli_validate.py +0 -0
  541. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_config.py +0 -0
  542. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_config_ast_parser.py +0 -0
  543. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_config_dev.py +0 -0
  544. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_config_diagnostics.py +0 -0
  545. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_config_env.py +0 -0
  546. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_config_env_loading.py +0 -0
  547. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_config_generator.py +0 -0
  548. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_config_integrations.py +0 -0
  549. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_config_json.py +0 -0
  550. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_config_pydantic.py +0 -0
  551. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_config_required.py +0 -0
  552. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_config_schema.py +0 -0
  553. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_config_sse.py +0 -0
  554. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_config_sse_integration.py +0 -0
  555. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_config_tracing.py +0 -0
  556. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_config_universal_env.py +0 -0
  557. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_config_utils.py +0 -0
  558. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_config_validation_group.py +0 -0
  559. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_config_watcher.py +0 -0
  560. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_config_webhook.py +0 -0
  561. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_custom_config_providers.py +0 -0
  562. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_priority_unification.py +0 -0
  563. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/config/test_remote_config.py +0 -0
  564. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/core/test_ast_indexer.py +0 -0
  565. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/core/test_ast_indexer_abstract.py +0 -0
  566. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/core/test_ast_indexer_graph.py +0 -0
  567. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/core/test_ast_indexer_layers.py +0 -0
  568. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/core/test_ast_indexer_metadata.py +0 -0
  569. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/core/test_cache.py +0 -0
  570. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/core/test_dev_models.py +0 -0
  571. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/core/test_exceptions.py +0 -0
  572. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/core/test_features.py +0 -0
  573. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/core/test_fs.py +0 -0
  574. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/core/test_thread_safety.py +0 -0
  575. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/core/test_time.py +0 -0
  576. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/decorators/test_decorator_circuit_breaker.py +0 -0
  577. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/decorators/test_decorator_retry.py +0 -0
  578. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/decorators/test_decorator_timeout.py +0 -0
  579. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/decorators/test_decorators.py +0 -0
  580. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/decorators/test_rate_limit.py +0 -0
  581. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/dev/test_ai_lint.py +0 -0
  582. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/dev/test_ai_lint_staged.py +0 -0
  583. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/dev/test_chat_context.py +0 -0
  584. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/dev/test_cleaner.py +0 -0
  585. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/dev/test_env_parser.py +0 -0
  586. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/dev/test_env_sync.py +0 -0
  587. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/dev/test_generate_few_shot.py +0 -0
  588. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/dev/test_linter_coverage_rule.py +0 -0
  589. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/dev/test_mock_server.py +0 -0
  590. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/dev/test_runners.py +0 -0
  591. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/dev/test_scaffold.py +0 -0
  592. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/dev/test_setup_github_actions.py +0 -0
  593. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/dev/test_upgrade_client.py +0 -0
  594. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/dev/test_version_detector.py +0 -0
  595. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/dev/test_watcher.py +0 -0
  596. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/di/test_di.py +0 -0
  597. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/events/test_event_bus.py +0 -0
  598. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/logger/conftest.py +0 -0
  599. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/logger/test_basics.py +0 -0
  600. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/logger/test_compression.py +0 -0
  601. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/logger/test_config_sections.py +0 -0
  602. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/logger/test_configuration.py +0 -0
  603. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/logger/test_context.py +0 -0
  604. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/logger/test_env_control.py +0 -0
  605. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/logger/test_files.py +0 -0
  606. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/logger/test_json_format.py +0 -0
  607. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/logger/test_logger_rich_width.py +0 -0
  608. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/logger/test_masking.py +0 -0
  609. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/logger/test_performance_security.py +0 -0
  610. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/logger/test_rich.py +0 -0
  611. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/logger/test_rotation.py +0 -0
  612. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/metrics/test_metrics.py +0 -0
  613. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/plugins/test_integration.py +0 -0
  614. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/plugins/test_interfaces.py +0 -0
  615. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/secret_manager/test_secret_manager.py +0 -0
  616. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/secret_manager/test_secret_manager_env.py +0 -0
  617. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/secret_manager/test_secret_manager_providers.py +0 -0
  618. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/secret_manager/test_secrets_required.py +0 -0
  619. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/tasks/test_scheduler.py +0 -0
  620. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_ai_lint_ignore.py +0 -0
  621. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_anticaptcha.py +0 -0
  622. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_antidetect.py +0 -0
  623. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_async_web_client.py +0 -0
  624. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_audit.py +0 -0
  625. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_audit_phase2.py +0 -0
  626. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_capmonster.py +0 -0
  627. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_captcha_base.py +0 -0
  628. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_captcha_imports.py +0 -0
  629. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_cli_db.py +0 -0
  630. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_concurrency_imports.py +0 -0
  631. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_concurrency_limiter.py +0 -0
  632. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_concurrency_pool.py +0 -0
  633. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_concurrency_queues.py +0 -0
  634. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_config_alias_choices.py +0 -0
  635. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_config_fallback.py +0 -0
  636. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_crypto.py +0 -0
  637. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_crypto_dependencies.py +0 -0
  638. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_dashboard.py +0 -0
  639. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_db_init.py +0 -0
  640. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_db_operations.py +0 -0
  641. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_decorators_bulkhead.py +0 -0
  642. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_diagnostics.py +0 -0
  643. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_env.py +0 -0
  644. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_events_exception_group.py +0 -0
  645. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_http_api.py +0 -0
  646. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_http_client.py +0 -0
  647. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_http_fallback.py +0 -0
  648. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_http_resilience.py +0 -0
  649. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_http_streaming.py +0 -0
  650. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_http_tracing.py +0 -0
  651. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_humanize_math.py +0 -0
  652. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_install_hooks.py +0 -0
  653. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_minimal_imports.py +0 -0
  654. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_nodriver_humanize.py +0 -0
  655. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_playwright_humanize.py +0 -0
  656. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_profile_imports.py +0 -0
  657. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_profile_warmer.py +0 -0
  658. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_proxy_pool.py +0 -0
  659. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_qt_asyncio.py +0 -0
  660. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_qt_logging.py +0 -0
  661. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_qt_shim.py +0 -0
  662. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_qt_signals.py +0 -0
  663. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_qt_widgets.py +0 -0
  664. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_rucaptcha.py +0 -0
  665. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_scraping_imports.py +0 -0
  666. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_selenium_humanize.py +0 -0
  667. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_store_backends_external.py +0 -0
  668. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_store_integrations.py +0 -0
  669. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_store_manager.py +0 -0
  670. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_store_memory.py +0 -0
  671. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_text.py +0 -0
  672. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_text_dependencies.py +0 -0
  673. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_user_agent.py +0 -0
  674. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_validation.py +0 -0
  675. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_web_client.py +0 -0
  676. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/test_web_imports.py +0 -0
  677. {chutils-3.4.2 → chutils-3.5.0}/tests/unit/testing/test_fixtures.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chutils
3
- Version: 3.4.2
3
+ Version: 3.5.0
4
4
  Summary: Набор простых и удобных утилит для Python, который избавляет от рутины при работе с конфигурацией и логированием в новых проектах.
5
5
  Author-email: Chu4hel <sergeiivanov636@gmail.com>
6
6
  License-Expression: MIT
@@ -71,6 +71,10 @@ Provides-Extra: testing
71
71
  Requires-Dist: pytest>=9.0.3; extra == 'testing'
72
72
  Provides-Extra: text
73
73
  Requires-Dist: rapidfuzz>=3.9.0; extra == 'text'
74
+ Provides-Extra: vk
75
+ Requires-Dist: pydantic<3.0.0,>=2.13.4; extra == 'vk'
76
+ Provides-Extra: vkma
77
+ Requires-Dist: pydantic<3.0.0,>=2.13.4; extra == 'vkma'
74
78
  Provides-Extra: watch
75
79
  Requires-Dist: watchdog>=6.0.0; extra == 'watch'
76
80
  Provides-Extra: web
@@ -148,6 +148,15 @@
148
148
 
149
149
  "src/chutils/testing/**/*.py" = ["docs/testing.md"]
150
150
 
151
+ # ---------------------------------------------------------------------------
152
+ # Модули Telegram и Qt
153
+ # ---------------------------------------------------------------------------
154
+
155
+ "src/chutils/telegram/**/*.py" = ["docs/telegram.md", "docs/api.md"]
156
+ "src/chutils/vk/**/*.py" = ["docs/vk_bot.md", "docs/vk_testing.md", "docs/api.md"]
157
+ "src/chutils/vkma/**/*.py" = ["docs/vkma.md", "docs/api.md"]
158
+ "src/chutils/qt/**/*.py" = ["docs/api.md"]
159
+
151
160
  # ---------------------------------------------------------------------------
152
161
  # HTTP-клиент и Стриминг
153
162
  # ---------------------------------------------------------------------------
@@ -1,20 +1,23 @@
1
1
  ---
2
- chutils_version: 3.4.1
3
- project_version: 3.4.1
4
- git_commit: 35b0abb02583ebebbd7a918dd74a5056d6b40c5c (dirty)
5
- generated_at: 2026-07-30T21:04:30.356972+00:00
6
- project_hash: 73c182750cd7e4d409a97fe4e3797cb39064637a44fe36638c5c113466639683
2
+ chutils_version: 3.5.0
3
+ project_version: 3.5.0
4
+ git_commit: 1c87144d236dcfcb390390fbe921514503e7956c
5
+ generated_at: 2026-08-07T16:55:37.743906+00:00
6
+ project_hash: b09b4066b90772c4d92b1864d4f07fa1bc34c75ad69786255a83e81e018575d0
7
7
  ---
8
8
 
9
9
  # Public API Map: chutils
10
10
 
11
11
  | Name | Type | Signature | Description |
12
12
  |:--------------------------------------|:---------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------|
13
+ | `AccessListManager` | class | `(self, storage_path: 'str \| Path \| None' = None, allowed_ids: 'list[int] \| None' = None, allowed_usernames: 'list[str] \| None' = None, blocked_ids: 'list[int] \| None' = None, blocked_usernames: 'list[str] \| None' = None) -> 'None'` | Менеджер белых и черных списков пользователей Telegram. |
14
+ | `AdminFilter` | class | `(self, admin_ids: 'list[int] \| None' = None, admin_usernames: 'list[str] \| None' = None, is_admin_func: 'Callable[[int \| None, str \| None], bool] \| None' = None) -> 'None'` | Фильтр проверки прав администратора для aiogram 3.x. |
13
15
  | `AntiCaptchaSolver` | class | `(self, api_key: str \| None = None, host: str = 'https://api.anti-captcha.com') -> None` | Синхронный клиент для Anti-Captcha. |
14
16
  | `AsyncAntiCaptchaSolver` | class | `(self, api_key: str \| None = None, host: str = 'https://api.anti-captcha.com') -> None` | Асинхронный клиент для Anti-Captcha. |
15
17
  | `AsyncCapMonsterSolver` | class | `(self, api_key: str \| None = None, host: str = 'https://api.capmonster.cloud') -> None` | Асинхронный клиент для CapMonster Cloud. |
16
18
  | `AsyncEventStreamClient` | class | `(self, url: 'str', headers: 'dict[str, str] \| None' = None, timeout: 'float \| None' = None, filter_heartbeats: 'bool' = True, reconnect_strategy: 'Iterable[float] \| Callable[[], Iterable[float]] \| None' = None) -> 'None'` | Асинхронный клиент для HTTP Streaming и SSE. |
17
19
  | `AsyncHttpClient` | class | `(self, *, base_url: 'str' = '', default_headers: 'dict[str, str] \| None' = None, timeout: 'float \| None' = 30.0, policy: 'ResiliencePolicy \| None' = None, sensitive_headers: 'set[str] \| None' = None) -> 'None'` | Асинхронный HTTP-клиент на базе httpx.AsyncClient. |
20
+ | `AsyncLifecycleContext` | class | `(self, setup_signals: 'bool' = True, auto_cleanup_subsystems: 'bool' = True, manager: 'LifecycleManager \| None' = None) -> 'None'` | Контекстный менеджер для управления жизненным циклом ресурсов приложения. |
18
21
  | `AsyncRuCaptchaSolver` | class | `(self, api_key: str \| None = None, host: str = 'https://rucaptcha.com') -> None` | Асинхронный клиент для RuCaptcha / 2Captcha. |
19
22
  | `AsyncWebClient` | class | `(self, *args: Any, user_agent_rotator: chutils.web.user_agent.UserAgentRotator \| None = None, proxy_pool: chutils.web.proxy_pool.ProxyPool \| None = None, rotate_ua: bool = True, rotate_proxy: bool = True, retries: int = 0, retry_delay: float = 1.0, retry_backoff: float = 2.0, retry_on_5xx: bool = True, rate_limit_calls: int \| None = None, rate_limit_period: float = 1.0, rate_limit_strategy: str = 'token_bucket', rate_limit_wait: bool = False, cache_ttl: int \| None = None, cache_backend: typing.Any \| None = None, **kwargs: Any) -> None` | Асинхронный HTTP-клиент с поддержкой ротации User-Agent, прокси-пулов, |
20
23
  | `AsyncWebSocketClient` | class | `(self, url: 'str', headers: 'dict[str, str] \| None' = None, filter_heartbeats: 'bool' = True, reconnect_strategy: 'Iterable[float] \| Callable[[], Iterable[float]] \| None' = None) -> 'None'` | Асинхронный клиент для WebSockets. |
@@ -27,6 +30,7 @@ project_hash: 73c182750cd7e4d409a97fe4e3797cb39064637a44fe36638c5c113466639683
27
30
  | `BaseEnvManifest` | class | `(self, /, **data: 'Any') -> 'None'` | Базовый манифест переменных окружения на базе Pydantic. |
28
31
  | `BaseStoreBackend` | class | `(self, /, *args, **kwargs)` | Абстрактный базовый класс для всех бэкендов Key-Value хранилищ. |
29
32
  | `BezierCurveGenerator` | class | `(self, /, *args, **kwargs)` | Генератор траекторий перемещения на основе кривых Безье. |
33
+ | `BrowserProfile` | class | `(self, /, **data: 'Any') -> 'None'` | Универсальная модель профиля браузера для экспорта/импорта. |
30
34
  | `BulkheadLimitExceeded` | class | `(self, message: str, hint: str \| None = None, **context: Any) -> None` | Ошибка: превышен предел параллельных запросов Bulkhead. |
31
35
  | `CacheError` | class | `(self, message: str, hint: str \| None = None, **context: Any) -> None` | Общая ошибка кэширования. |
32
36
  | `CapMonsterSolver` | class | `(self, api_key: str \| None = None, host: str = 'https://api.capmonster.cloud') -> None` | Синхронный клиент для CapMonster Cloud. |
@@ -60,6 +64,7 @@ project_hash: 73c182750cd7e4d409a97fe4e3797cb39064637a44fe36638c5c113466639683
60
64
  | `EventBusExceptionGroup` | class | `(self, message: str, exceptions: list[Exception], **context: Any) -> None` | Группа ошибок, возникших при параллельном или последовательном выполнении |
61
65
  | `EventStreamClient` | class | `(self, url: 'str', headers: 'dict[str, str] \| None' = None, timeout: 'float \| None' = None, filter_heartbeats: 'bool' = True, reconnect_strategy: 'Iterable[float] \| Callable[[], Iterable[float]] \| None' = None) -> 'None'` | Синхронный клиент-обертка для HTTP Streaming и SSE. |
62
66
  | `FileBackend` | class | `(self, path: 'str \| Path') -> 'None'` | Бэкенд хранения событий аудита в JSONL-файле. |
67
+ | `HealthCheckAlertBridge` | class | `(self, bot_token: 'str \| None' = None, chat_id: 'int \| str \| None' = None, notify_on_degraded: 'bool' = True) -> 'None'` | Мост отправки Telegram-уведомлений при изменении статусов здоровья chutils.diagnostics. |
63
68
  | `HttpClient` | class | `(self, *, base_url: 'str' = '', default_headers: 'dict[str, str] \| None' = None, timeout: 'float \| None' = 30.0, policy: 'ResiliencePolicy \| None' = None, sensitive_headers: 'set[str] \| None' = None) -> 'None'` | Синхронный HTTP-клиент с батареями (httpx + fallback на urllib). |
64
69
  | `HttpClientError` | class | `(self, message: str, hint: str \| None = None, **context: Any) -> None` | Базовая ошибка HTTP-клиента chutils. |
65
70
  | `HttpResponse` | class | `(self, status_code: 'int', headers: 'dict[str, str]', content: 'bytes', elapsed: 'float', url: 'str') -> None` | Ответ HTTP-запроса. |
@@ -78,7 +83,9 @@ project_hash: 73c182750cd7e4d409a97fe4e3797cb39064637a44fe36638c5c113466639683
78
83
  | `OTEL_AVAILABLE` | constant | | |
79
84
  | `OptionalDependencyError` | class | `(self, message: str, hint: str \| None = None, **context: Any) -> None` | Ошибка: отсутствует опциональная зависимость (например, watchdog). |
80
85
  | `PYDANTIC_AVAILABLE` | constant | | |
86
+ | `PaginatorKeyboard` | class | `(self, items: 'Sequence[Any]', per_page: 'int' = 5, callback_prefix: 'str' = 'page') -> 'None'` | Управляющий класс пагинации динамических Inline-клавиатур. |
81
87
  | `PostgresBackend` | class | `(self, connection: '_DBAPIConnection') -> 'None'` | Бэкенд хранения событий аудита в PostgreSQL. |
88
+ | `ProfileManager` | class | `(self, /, *args, **kwargs)` | Менеджер для универсального экспорта, конвертации и импорта браузерных профилей. |
82
89
  | `RICH_AVAILABLE` | constant | | |
83
90
  | `RateLimitExceededError` | class | `(self, message: str, hint: str \| None = None, **context: Any) -> None` | Ошибка: превышен лимит частоты вызовов (Rate Limit Exceeded). |
84
91
  | `RedisStore` | class | `(self, url: 'str' = 'redis://localhost:6379/0', **kwargs: 'Any') -> 'None'` | Бэкенд хранилища на базе Redis (требует опционального пакета redis). |
@@ -91,25 +98,34 @@ project_hash: 73c182750cd7e4d409a97fe4e3797cb39064637a44fe36638c5c113466639683
91
98
  | `SecretMaskingFilter` | class | `(self, name: 'str' = '', secrets: 'list[str] \| set[str] \| None' = None, patterns: 'list[str] \| set[str] \| None' = None) -> 'None'` | Фильтр для автоматического маскирования секретов в сообщениях логов. |
92
99
  | `SecretNotFoundError` | class | `(self, message: str, hint: str \| None = None, **context: Any) -> None` | Ошибка: секрет не найден. |
93
100
  | `SecretProviderError` | class | `(self, message: str, hint: str \| None = None, **context: Any) -> None` | Ошибка конкретного провайдера секретов (например, сбой keyring). |
101
+ | `SecretUserFilter` | class | `(self, manager: 'Any \| None' = None, allowed_ids: 'list[int] \| None' = None, allowed_usernames: 'list[str] \| None' = None, blocked_ids: 'list[int] \| None' = None, blocked_usernames: 'list[str] \| None' = None) -> 'None'` | Фильтр белых и черных списков пользователей для aiogram 3.x. |
94
102
  | `ServerSentEvent` | class | `(self, id: 'str \| None' = None, event: 'str \| None' = None, data: 'str' = '', retry: 'int \| None' = None, raw: 'str' = '') -> None` | Представляет собой отдельное событие Server-Sent Events (SSE). |
95
103
  | `SqliteBackend` | class | `(self, path: 'str \| Path') -> 'None'` | Бэкенд хранения событий аудита в таблице SQLite. |
96
104
  | `SseConfigClient` | class | `(self, url: 'str', on_event: 'Callable[[SseEvent], None] \| None' = None, on_reload: 'Callable[[], None] \| None' = None, headers: 'dict[str, str] \| None' = None, timeout: 'float' = 30.0, reconnect_delay: 'float' = 1.0, max_reconnect_delay: 'float' = 60.0) -> 'None'` | Клиент для постоянного подключения к SSE-серверу обновлений конфигурации. |
97
105
  | `SseEvent` | class | `(self, event: 'str' = 'message', data: 'str' = '', event_id: 'str \| None' = None, retry: 'int \| None' = None) -> 'None'` | Представляет отдельное событие Server-Sent Events (SSE). |
98
106
  | `StoreManager` | class | `(self, backend: 'BaseStoreBackend \| None' = None, serializer: 'str \| Any' = 'json', prefix: 'str' = '') -> 'None'` | Центральный менеджер Key-Value хранилища. |
107
+ | `TelegramLogHandler` | class | `(self, bot_token: 'str \| None' = None, chat_id: 'int \| str \| None' = None, level: 'int' = 40, rate_limit_per_min: 'int' = 10) -> 'None'` | Handler стандартного модуля logging для отправки критических логов в Telegram. |
108
+ | `TelegramLoggingMiddleware` | class | `(self, logger_instance: 'Any' = None) -> 'None'` | Middleware контекстного логирования и измерений времени выполнения для aiogram 3.x. |
109
+ | `TelegramRateLimiter` | class | `(self, rate: 'int' = 1, per: 'float' = 1.0) -> 'None'` | Движок ограничений вызовов (Rate Limiter) для Telegram-ботов. |
110
+ | `TelegramThrottlingMiddleware` | class | `(self, rate: 'int' = 1, per: 'float' = 1.0, scope: 'str' = 'user_id', warning_text: 'str \| None' = '⏱ Пожалуйста, подождите {wait_sec} сек. перед повторной отправкой.', silent: 'bool' = False) -> 'None'` | Middleware отслеживания и предотвращения спама (Throttling) для aiogram 3.x. |
99
111
  | `UrllibFallbackClient` | class | `(self, *, base_url: 'str' = '', default_headers: 'dict[str, str] \| None' = None, timeout: 'float \| None' = 30.0, policy: 'ResiliencePolicy \| None' = None, sensitive_headers: 'set[str] \| None' = None) -> 'None'` | Синхронный HTTP-клиент на базе urllib.request. |
112
+ | `VKCallbackRouter` | class | `(self, confirmation_code: str \| None = None, secret_key: str \| None = None, path: str = '/vk-callback') -> None` | Маршрутизатор событий VK Callback API. |
100
113
  | `WATCHDOG_AVAILABLE` | constant | | |
101
114
  | `WatcherInitializationError` | class | `(self, message: str, hint: str \| None = None, **context: Any) -> None` | Ошибка инициализации наблюдателя (watcher) за файлами. |
102
115
  | `WebClient` | class | `(self, *args: Any, user_agent_rotator: chutils.web.user_agent.UserAgentRotator \| None = None, proxy_pool: chutils.web.proxy_pool.ProxyPool \| None = None, rotate_ua: bool = True, rotate_proxy: bool = True, retries: int = 0, retry_delay: float = 1.0, retry_backoff: float = 2.0, retry_on_5xx: bool = True, rate_limit_calls: int \| None = None, rate_limit_period: float = 1.0, rate_limit_strategy: str = 'token_bucket', rate_limit_wait: bool = False, cache_ttl: int \| None = None, cache_backend: typing.Any \| None = None, **kwargs: Any) -> None` | Синхронный HTTP-клиент с поддержкой ротации User-Agent, прокси-пулов, |
103
116
  | `WebSocketClient` | class | `(self, url: 'str', headers: 'dict[str, str] \| None' = None, filter_heartbeats: 'bool' = True, reconnect_strategy: 'Iterable[float] \| Callable[[], Iterable[float]] \| None' = None) -> 'None'` | Синхронный клиент-обертка для WebSockets. |
104
117
  | `WebhookConfigServer` | class | `(self, host: 'str' = '0.0.0.0', port: 'int' = 8080, path: 'str' = '/webhook/config-reload', secret_token: 'str \| None' = None, hmac_secret: 'str \| None' = None, on_reload: 'Callable[[], None] \| None' = None) -> 'None'` | Легковесный Webhook-сервер для принятия входящих HTTP POST запросов |
118
+ | `admin_only` | function | `(admin_ids: 'list[int] \| None' = None, admin_usernames: 'list[str] \| None' = None, is_admin_func: 'Callable[[int \| None, str \| None], bool] \| None' = None, refusal_text: 'str \| None' = '⛔ Доступ запрещен: требуется статус администратора', silent: 'bool' = False, raise_on_denied: 'bool' = False) -> 'Callable[[F], F]'` | Декоратор для ограничения доступа к синхронным и асинхронным хэндлерам Telegram-ботов. |
105
119
  | `aget_config` | function | `(model: 'type[T] \| None' = None) -> 'JSONDict \| T'` | Асинхронная версия get_config. |
106
120
  | `aget_config_value` | function | `(section: 'str', key: 'str', fallback: 'Any' = None, config: 'JSONDict \| None' = None, required: 'bool' = False) -> 'Any'` | Асинхронно получает произвольное значение из конфигурации. |
121
+ | `allowed_only` | function | `(manager: 'AccessListManager \| None' = None, allowed_ids: 'list[int] \| None' = None, allowed_usernames: 'list[str] \| None' = None, blocked_ids: 'list[int] \| None' = None, blocked_usernames: 'list[str] \| None' = None, refusal_text: 'str \| None' = '⛔ У вас нет доступа к этой функции', silent: 'bool' = False, raise_on_denied: 'bool' = False) -> 'Callable[[F], F]'` | Декоратор ограничения доступа по белым и черным спискам. |
107
122
  | `apply_antidetect_nodriver` | function | `(tab: Any, *, webgl_vendor: str = 'Google Inc. (NVIDIA)', webgl_renderer: str = 'ANGLE (NVIDIA, NVIDIA GeForce RTX 3060 Direct3D11 vs_5_0 ps_5_0, D3D11)', hardware_concurrency: int = 8, device_memory: int = 8) -> None` | Применяет JS-инъекции анти-детекта к вкладке (Tab) nodriver. |
108
123
  | `apply_antidetect_playwright` | function | `(context: Any, *, webgl_vendor: str = 'Google Inc. (NVIDIA)', webgl_renderer: str = 'ANGLE (NVIDIA, NVIDIA GeForce RTX 3060 Direct3D11 vs_5_0 ps_5_0, D3D11)', hardware_concurrency: int = 8, device_memory: int = 8) -> None` | Применяет JS-инъекции анти-детекта к контексту Playwright. |
109
124
  | `apply_antidetect_selenium` | function | `(driver: Any, *, webgl_vendor: str = 'Google Inc. (NVIDIA)', webgl_renderer: str = 'ANGLE (NVIDIA, NVIDIA GeForce RTX 3060 Direct3D11 vs_5_0 ps_5_0, D3D11)', hardware_concurrency: int = 8, device_memory: int = 8) -> None` | Применяет JS-инъекции анти-детекта к сессии Selenium. |
110
125
  | `are_paths_initialized` | function | `() -> bool` | Проверяет, были ли инициализированы пути к проекту и файлам конфигурации. |
111
126
  | `asave_config_value` | function | `(section: 'str', key: 'str', value: 'Any', cfg_file: 'str \| None' = None, save_to_local: 'bool' = False, notify: 'bool' = True) -> 'bool'` | Асинхронно сохраняет одно значение в конфигурационном файле. |
112
127
  | `async_human_sleep` | function | `(min_seconds: float, max_seconds: float) -> None` | Асинхронно задерживает выполнение на случайное время, имитируя поведение человека. |
128
+ | `async_lifecycle` | function | `(setup_signals: 'bool' = True, auto_cleanup_subsystems: 'bool' = True) -> 'AsyncLifecycleContext'` | Возвращает контекстный менеджер для управления жизненным циклом ресурсов. |
113
129
  | `async_move_mouse` | function | `(page: Any, x: int, y: int, start: tuple[int, int] \| None = None, steps: int = 30, delay_between_steps: float = 0.01) -> None` | Имитирует плавное перемещение мыши Playwright или nodriver. |
114
130
  | `async_scroll_to` | function | `(page: Any, x: int, y: int, selector: str \| None = None, steps: int = 10, delay_between_steps: float = 0.01) -> None` | Имитирует плавный скроллинг Playwright или nodriver. |
115
131
  | `async_type_text` | function | `(page: Any, selector: str, text: str, error_rate: float = 0.05, speed_wpm: float = 40.0) -> None` | Имитирует ввод текста с опечатками Playwright или nodriver. |
@@ -117,6 +133,7 @@ project_hash: 73c182750cd7e4d409a97fe4e3797cb39064637a44fe36638c5c113466639683
117
133
  | `audit_context` | function | `(action: 'str', actor: 'str', *, target: 'str \| None' = None, backend: 'object') -> 'Generator[_AuditContextState, None, None]'` | Контекстный менеджер для регистрации события аудита в блоке кода. |
118
134
  | `audit_event` | function | `(action: 'str', actor: '_ActorOrCallable' = 'system', *, target: '_TargetOrCallable' = None, backend: 'object') -> 'Callable'` | Декоратор для автоматической регистрации события аудита при вызове функции. |
119
135
  | `bind_context` | function | `(**kwargs: 'Any') -> 'contextvars.Token[dict[str, Any]]'` | Привязывает значения к текущему контексту. |
136
+ | `build_inline_keyboard` | function | `(buttons: 'Sequence[ButtonSpec]', buttons_per_row: 'int' = 2, as_aiogram: 'bool' = False) -> 'Any'` | Создает сетку Inline-клавиатуры Telegram из списка кнопок. |
120
137
  | `bulkhead` | function | `(max_concurrent: int, max_waiting: int = 0, timeout: Optional[float] = None, fallback: Any = <object object>, key: Optional[collections.abc.Callable[..., Any]] = None) -> collections.abc.Callable[[collections.abc.Callable[~P, ~R]], collections.abc.Callable[~P, ~R]]` | Декоратор для изоляции ресурсов (Bulkhead). |
121
138
  | `cache` | module | | |
122
139
  | `cache_with_ttl` | function | `(ttl: int = 60, key_prefix: str = '', sliding: bool = True, backend: Optional[chutils.cache.in_memory.InMemoryCacheBackend[Any]] = None, tags: list[str] \| collections.abc.Callable[..., list[str] \| str] \| None = None) -> collections.abc.Callable[..., typing.Any]` | Декоратор для кэширования результатов выполнения функций с поддержкой TTL. |
@@ -132,14 +149,17 @@ project_hash: 73c182750cd7e4d409a97fe4e3797cb39064637a44fe36638c5c113466639683
132
149
  | `dashboard` | module | | Интерактивный TUI-дашборд для CLI-команд проекта. |
133
150
  | `db` | module | | Модуль chutils.db — готовый менеджер подключений к реляционным БД. |
134
151
  | `decorators` | module | | Модуль с полезными декораторами для автоматизации задач. |
135
- | `decrypt_file` | function | `(file_path: str \| pathlib._local.Path, seed: str, output_path: str \| pathlib._local.Path \| None = None, raise_on_error: bool = False) -> bool` | Дешифрует содержимое файла и сохраняет результат. |
152
+ | `decrypt_file` | function | `(file_path: str \| pathlib._local.Path, seed: str, output_path: str \| pathlib._local.Path \| None = None, raise_on_error: bool = False, stream: bool \| None = None, progress_callback: collections.abc.Callable[[int, int], None] \| None = None) -> bool` | Дешифрует содержимое файла и сохраняет результат. |
136
153
  | `decrypt_portable` | function | `(encrypted_data: str, seed: str, raise_on_error: bool = False) -> str \| None` | Дешифрует строку с использованием детерминированного ключа, полученного из seed. |
137
154
  | `default_container` | constant | | Легковесный IoC/DI контейнер. |
138
155
  | `dev` | module | | Инструменты разработчика для анализа кодовой базы и генерации контекста. |
139
156
  | `di` | module | | |
140
157
  | `diagnostics` | module | | |
141
- | `encrypt_file` | function | `(file_path: str \| pathlib._local.Path, seed: str, output_path: str \| pathlib._local.Path \| None = None) -> pathlib._local.Path` | Шифрует содержимое файла и сохраняет результат. |
158
+ | `download_user_file` | function | `(bot: 'Any', file_id: 'str', target_dir: 'str \| Path', custom_filename: 'str \| None' = None, allow_unsafe_path: 'bool' = False, max_size_bytes: 'int \| None' = None) -> 'Path'` | Безопасно выкачивает файл из Telegram по `file_id` в указанную директорию `target_dir`. |
159
+ | `encrypt_file` | function | `(file_path: str \| pathlib._local.Path, seed: str, output_path: str \| pathlib._local.Path \| None = None, stream: bool = False, chunk_size: int = 67108864, progress_callback: collections.abc.Callable[[int, int], None] \| None = None) -> pathlib._local.Path` | Шифрует содержимое файла и сохраняет результат. |
142
160
  | `encrypt_portable` | function | `(data: str, seed: str) -> str` | Шифрует строку с использованием детерминированного ключа, полученного из seed. |
161
+ | `escape_html` | function | `(text: 'str') -> 'str'` | Экранирует специальные символы в тексте для парс-режима HTML в Telegram. |
162
+ | `escape_markdown` | function | `(text: 'str', version: 'int' = 2) -> 'str'` | Экранирует специальные символы в тексте для парс-режима Markdown в Telegram. |
143
163
  | `events` | module | | Модуль шины событий (In-Memory Event Bus). |
144
164
  | `exceptions` | module | | |
145
165
  | `export_schema` | function | `(model: type[pydantic.main.BaseModel] \| str, output_path: str \| pathlib._local.Path \| None = None, indent: int = 4) -> str` | Генерирует JSON Schema для Pydantic модели и опционально сохраняет в файл. |
@@ -170,6 +190,7 @@ project_hash: 73c182750cd7e4d409a97fe4e3797cb39064637a44fe36638c5c113466639683
170
190
  | `init` | function | `(base_dir: str) -> None` | Ручная инициализация пакета с указанием базовой директории проекта. |
171
191
  | `inject` | function | `(func_or_container: collections.abc.Callable[..., typing.Any] \| chutils.di.container.Container \| None = None, *, container: chutils.di.container.Container \| None = None) -> Any` | Декоратор для автоматического внедрения зависимостей в аргументы функции. |
172
192
  | `inject_trace_headers` | function | `(headers: 'dict[str, str]') -> 'dict[str, str]'` | Инжектирует W3C Trace Context заголовки в словарь заголовков запроса. |
193
+ | `is_admin` | function | `(user_id: 'int \| None' = None, username: 'str \| None' = None, admin_ids: 'list[int] \| None' = None, admin_usernames: 'list[str] \| None' = None, is_admin_func: 'Callable[[int \| None, str \| None], bool] \| None' = None) -> 'bool'` | Проверяет, является ли пользователь администратором. |
173
194
  | `is_config_loaded` | function | `() -> bool` | Проверяет, была ли конфигурация уже загружена в память. |
174
195
  | `is_feature_enabled` | function | `(feature_name: 'str', context: 'dict[str, Any] \| None' = None) -> 'bool'` | Проверяет, включена ли указанная фича. |
175
196
  | `is_otel_enabled` | function | `() -> 'bool'` | Проверяет, доступен ли OpenTelemetry и не отключен ли он. |
@@ -202,14 +223,18 @@ project_hash: 73c182750cd7e4d409a97fe4e3797cb39064637a44fe36638c5c113466639683
202
223
  | `retry` | function | `(retries: int = 3, delay: float = 1.0, backoff: float = 2.0, jitter: bool = False, exceptions: tuple[type[Exception], ...] = (<class 'Exception'>,)) -> collections.abc.Callable[[collections.abc.Callable[~P, ~R]], collections.abc.Callable[~P, ~R]]` | Декоратор для автоматического повторного выполнения функции при возникновении исключений. |
203
224
  | `safe_filename` | function | `(name: 'str', replacement: 'str' = '_', strip_chars: 'str' = ' _.-', max_length: 'int' = 255, transliterate: 'bool' = False) -> 'str'` | Очищает строку, делая её безопасной для использования в качестве имени файла. |
204
225
  | `save_config_value` | function | `(section: 'str', key: 'str', value: 'Any', cfg_file: 'str \| None' = None, save_to_local: 'bool' = False, notify: 'bool' = True) -> 'bool'` | Сохраняет или обновляет одно значение в файле конфигурации. |
205
- | `scraping` | module | | |
226
+ | `scraping` | module | | Модуль скрейпинга, автоматизации и утилиты антидетекта. |
206
227
  | `scroll_to` | function | `(driver: Any, x: int, y: int, selector: str \| None = None, steps: int = 10, delay_between_steps: float = 0.01) -> None` | Имитирует плавный скроллинг Selenium. |
207
228
  | `secret_manager` | module | | |
208
229
  | `semaphore` | function | `(max_concurrent: int, key: Optional[collections.abc.Callable[..., Any]] = None) -> collections.abc.Callable[[collections.abc.Callable[~P, ~R]], collections.abc.Callable[~P, ~R]]` | Декоратор для ограничения максимального количества параллельных вызовов функции (Semaphore). |
230
+ | `send_alert` | function | `(title: 'str', message: 'str', bot_token: 'str \| None' = None, chat_id: 'int \| str \| None' = None, level: 'str' = 'ERROR') -> 'bool'` | Отправляет кастомное алерты-уведомление администраторам в Telegram. |
231
+ | `send_telegram_file` | function | `(bot: 'Any', chat_id: 'int \| str', file_path: 'str \| Path', caption: 'str \| None' = None, parse_mode: 'str \| None' = None, allow_unsafe_path: 'bool' = False, base_dir: 'str \| Path \| None' = None) -> 'Any'` | Безопасно отправляет файл или папку (с авто-упаковкой в ZIP) в Telegram. |
209
232
  | `setup_graceful_shutdown` | function | `() -> 'None'` | Публичный API для настройки Graceful Shutdown. |
210
233
  | `setup_logger` | function | `(name: 'str' = 'app_logger', config_section_name: 'str \| None' = None, log_level: 'LogLevel \| None' = None, log_file_name: 'str \| None' = None, force_reconfigure: 'bool' = False, rotation_type: 'str \| None' = None, max_bytes: 'int \| None' = None, compress: 'bool \| None' = None, backup_count: 'int \| None' = None, encoding: 'str \| None' = None, when: 'str \| None' = None, interval: 'int \| None' = None, utc: 'bool \| None' = None, at_time: 'Any' = None, json_format: 'bool \| None' = None, use_async: 'bool \| None' = None, custom_patterns: 'list[str] \| None' = None, use_predefined_patterns: 'list[str \| list[str]] \| None' = None, **kwargs: 'Any') -> 'ChutilsLogger'` | Настраивает и возвращает экземпляр логгера. |
211
234
  | `setup_logger_from_config` | function | `(name: 'str' = 'app_logger', config_section_name: 'str \| None' = None, force_reconfigure: 'bool' = False) -> 'ChutilsLogger'` | Инициализирует логгер, используя настройки исключительно из файла конфигурации. |
212
235
  | `setup_tracing` | function | `(service_name: 'str', exporter_type: 'str' = 'console', otlp_endpoint: 'str \| None' = None, otlp_protocol: 'str' = 'grpc') -> 'bool'` | Настраивает OpenTelemetry SDK для сбора трасс. |
236
+ | `smart_truncate` | function | `(text: 'str', max_length: 'int' = 4096, suffix: 'str' = '...') -> 'str'` | Безопасно обрезает текст до max_length с закрытием кодовых блоков (```). |
237
+ | `split_message` | function | `(text: 'str', max_length: 'int' = 4096, mode: "Literal['paragraph', 'line', 'word', 'char']" = 'line') -> 'list[str]'` | Разбивает длинный текст на список валидных сообщений не превышающих max_length. |
213
238
  | `start_config_watcher` | function | `() -> 'bool'` | Запускает фоновый процесс отслеживания изменений в файлах конфигурации. |
214
239
  | `start_scheduler` | function | `() -> 'None'` | Запускает глобальный планировщик фоновых задач в текущем Event Loop. |
215
240
  | `start_webhook_server` | function | `(host: str = '0.0.0.0', port: int = 8080, path: str = '/webhook/config-reload', secret_token: str \| None = None, hmac_secret: str \| None = None) -> Any` | Запускает встроенный Webhook-сервер для мгновенного обновления конфигурации. |
@@ -220,11 +245,14 @@ project_hash: 73c182750cd7e4d409a97fe4e3797cb39064637a44fe36638c5c113466639683
220
245
  | `store_cache` | function | `(store: 'StoreManager \| None' = None, ttl: 'int \| float' = 60, key_prefix: 'str' = 'cache:') -> 'Callable[..., Any]'` | Декоратор для кэширования результатов вызова функций через StoreManager. |
221
246
  | `subscribe` | function | `(event_name: str) -> collections.abc.Callable[[collections.abc.Callable[..., typing.Any]], collections.abc.Callable[..., typing.Any]]` | Декоратор для подписки на событие в глобальной шине. |
222
247
  | `tasks` | module | | Модуль планировщика фоновых задач. |
248
+ | `telegram` | module | | |
223
249
  | `testing` | module | | |
224
250
  | `text` | module | | Модуль для обработки текстовых данных. |
251
+ | `tg_rate_limit` | function | `(rate: 'int' = 1, per: 'float' = 1.0, scope: 'str' = 'user_id', warning_text: 'str \| None' = '⏱ Пожалуйста, подождите {wait_sec} сек. перед повторной отправкой.', silent: 'bool' = False, raise_on_limit: 'bool' = False) -> 'Callable[[F], F]'` | Декоратор ограничения частоты запросов для Telegram-ботов. |
225
252
  | `time` | module | | Модуль для работы со временем и датами. |
226
253
  | `timeout` | function | `(seconds: float, fallback: Any = <object object>) -> collections.abc.Callable[[collections.abc.Callable[~P, ~R]], collections.abc.Callable[~P, ~R]]` | Декоратор для ограничения времени выполнения функции. |
227
254
  | `trace` | function | `(name: 'str \| Callable[P, R] \| None' = None, attributes: 'dict[str, Any] \| None' = None, capture_kwargs: 'bool' = False) -> 'Any'` | Декоратор для автоматического создания спана при вызове функции. |
255
+ | `trace_telegram_update` | class | `(self, event: 'Any' = None, logger_instance: 'Any' = None) -> 'None'` | Контекстный менеджер и декоратор трейсинга и логирования Telegram-апдейтов. |
228
256
  | `tracing` | module | | |
229
257
  | `trigger_reload` | function | `() -> None` | Вызывает принудительную перезагрузку конфигурации и оповещает колбэки. |
230
258
  | `type_text` | function | `(driver: Any, selector: str, text: str, error_rate: float = 0.05, speed_wpm: float = 40.0) -> None` | Имитирует ввод текста с опечатками Selenium. |
@@ -234,5 +262,7 @@ project_hash: 73c182750cd7e4d409a97fe4e3797cb39064637a44fe36638c5c113466639683
234
262
  | `validate_data` | function | `(model: 'type[T]', data: 'dict[str, Any] \| str') -> 'T'` | Валидирует словарь или JSON-строку по заданной Pydantic модели. |
235
263
  | `validate_required_keys` | function | `(section: 'str \| dict[str, Any]', keys: 'list[str] \| str', config: 'JSONDict \| None' = None) -> 'None'` | Проверяет наличие списка обязательных ключей в указанной секции конфигурации или словаре. |
236
264
  | `validation` | module | | |
265
+ | `vk` | module | | Экспорт основного модуля chutils.vk. |
266
+ | `vkma` | module | | Экспорт основного функционала chutils.vkma. |
237
267
  | `web` | module | | |
238
268
  | `zip_folder` | function | `(folder_path: 'str \| Path', output_path: 'str \| Path', compression: 'int' = 8, exclude: 'list[str] \| None' = None) -> 'Path'` | Архивирует содержимое папки в ZIP-архив с сохранением структуры. |
@@ -3,15 +3,15 @@
3
3
  Оптимизация утилиты `chutils dev generate-context` с помощью `.gitignore` парсера и инкрементального AST-обновления.
4
4
 
5
5
  ## Phase 1: Gitignore Parser (`src/chutils/dev/context/gitignore.py`)
6
- - [ ] Task: Добавить поддержку чтения и парсинга `.gitignore` файлов через `pathspec` или встроенный fnmatch-механизм в `src/chutils/dev/context/gitignore.py`.
7
- - [ ] Task: Интегрировать опцию `--gitignore` в команду CLI `generate-context` (`src/chutils/commands/dev.py`).
6
+ - [x] Task: Добавить поддержку чтения и парсинга `.gitignore` файлов через `pathspec` или встроенный fnmatch-механизм в `src/chutils/dev/context/gitignore.py`.
7
+ - [x] Task: Интегрировать опцию `--gitignore` в команду CLI `generate-context` (`src/chutils/commands/dev.py`).
8
8
 
9
9
  ## Phase 2: Incremental AST Indexer (`src/chutils/dev/context/incremental.py`)
10
- - [ ] Task: Реализовать получение списка измененных файлов через `git status` / `git diff` в `src/chutils/dev/context/incremental.py`.
11
- - [ ] Task: Реализовать логику частичной замены узлов AST для измененных файлов в `project_index.json` и `api_map.md`.
12
- - [ ] Task: Интегрировать флаги `--incremental` / `-i` в CLI утилиту `generate-context`.
10
+ - [x] Task: Реализовать получение списка измененных файлов через `git status` / `git diff` в `src/chutils/dev/context/incremental.py`.
11
+ - [x] Task: Реализовать логику частичной замены узлов AST для измененных файлов в `project_index.json` и `api_map.md`.
12
+ - [x] Task: Интегрировать флаги `--incremental` / `-i` в CLI утилиту `generate-context`.
13
13
 
14
14
  ## Phase 3: Testing & Verification
15
- - [ ] Task: Написать unit-тесты для парсера `.gitignore` и инкрементальной генерации в `tests/unit/dev/test_context_generator.py`.
16
- - [ ] Task: Проверить работу команды через `uv run mypy src/chutils` и `uv run pytest tests/unit/dev/`.
17
- - [ ] Task: Обновить документацию в `docs/api.md` и перегенерировать `api_map.md`.
15
+ - [x] Task: Написать unit-тесты для парсера `.gitignore` и инкрементальной генерации в `tests/unit/dev/test_context_generator.py`.
16
+ - [x] Task: Проверить работу команды через `uv run mypy src/chutils` и `uv run pytest tests/unit/dev/`.
17
+ - [x] Task: Обновить документацию в `docs/api.md` и перегенерировать `api_map.md`.
@@ -3,14 +3,14 @@
3
3
  Реализация асинхронного контекстного менеджера `async_lifecycle` в `chutils.lifecycle`.
4
4
 
5
5
  ## Phase 1: Lifecycle Context Implementation (`src/chutils/lifecycle.py`)
6
- - [ ] Task: Создать класс/функцию `AsyncLifecycleContext` и публичную функцию `lifecycle()` в `src/chutils/lifecycle.py`.
7
- - [ ] Task: Реализовать логику `__aenter__` (авто-подключение сигналов при `setup_signals=True`) и `__aexit__` (безопасный вызов `async_run_cleanup()`).
8
- - [ ] Task: Добавить поддержку опционального автоклининга подсистем (`db`, `tasks`, `logger`) при `auto_cleanup_subsystems=True`.
6
+ - [x] Task: Создать класс/функцию `AsyncLifecycleContext` и публичную функцию `lifecycle()` в `src/chutils/lifecycle.py`.
7
+ - [x] Task: Реализовать логику `__aenter__` (авто-подключение сигналов при `setup_signals=True`) и `__aexit__` (безопасный вызов `async_run_cleanup()`).
8
+ - [x] Task: Добавить поддержку опционального автоклининга подсистем (`db`, `tasks`, `logger`) при `auto_cleanup_subsystems=True`.
9
9
 
10
10
  ## Phase 2: Unit Testing & Integration Verification
11
- - [ ] Task: Написать unit-тесты для `async with lifecycle()` с успешным завершением и сгенерированным исключением в `tests/unit/core/test_lifecycle.py`.
12
- - [ ] Task: Написать тесты перехвата сигналов ОС в контекстном менеджере.
11
+ - [x] Task: Написать unit-тесты для `async with lifecycle()` с успешным завершением и сгенерированным исключением в `tests/unit/core/test_lifecycle.py`.
12
+ - [x] Task: Написать тесты перехвата сигналов ОС в контекстном менеджере.
13
13
 
14
14
  ## Phase 3: Verification & Documentation
15
- - [ ] Task: Запустить `uv run mypy src/chutils` и `uv run pytest tests/unit/core/test_lifecycle.py`.
16
- - [ ] Task: Добавить примеры использования `async with lifecycle()` в `docs/api.md` и обновить `api_map.md`.
15
+ - [x] Task: Запустить `uv run mypy src/chutils` и `uv run pytest tests/unit/core/test_lifecycle.py`.
16
+ - [x] Task: Добавить примеры использования `async with lifecycle()` в `docs/api.md` и обновить `api_map.md`.
@@ -3,21 +3,21 @@
3
3
  Модуль управления, экспорта, импорта и переноса авторизованных сессий и профилей браузеров между `nodriver`, `playwright` и `selenium`.
4
4
 
5
5
  ## Phase 1: Core Data Models & Serialization (`chutils.scraping.profiles.models`)
6
- - [ ] Task: Создать Pydantic-модели профилей `BrowserProfile`, `CookieData`, `StorageData`, `HeaderData` в `src/chutils/scraping/profiles/models.py`.
7
- - [ ] Task: Реализовать методы упаковывания/распаковывания `.chprofile` архивов с поддержкой Fernet-шифрования (`chutils.crypto`) в `src/chutils/scraping/profiles/storage.py`.
8
- - [ ] Task: Написать unit-тесты для сериализации, шифрования и распаковки `BrowserProfile` в `tests/unit/scraping/test_profile_storage.py`.
6
+ - [x] Task: Создать Pydantic-модели профилей `BrowserProfile`, `CookieData`, `StorageData`, `HeaderData` в `src/chutils/scraping/profiles/models.py`.
7
+ - [x] Task: Реализовать методы упаковывания/распаковывания `.chprofile` архивов с поддержкой Fernet-шифрования (`chutils.crypto`) в `src/chutils/scraping/profiles/storage.py`.
8
+ - [x] Task: Написать unit-тесты для сериализации, шифрования и распаковки `BrowserProfile` в `tests/unit/scraping/test_profile_storage.py`.
9
9
 
10
10
  ## Phase 2: Engine Adapters (nodriver, playwright, selenium)
11
- - [ ] Task: Реализовать адаптер экспорта/импорта для `playwright` (Async & Sync Contexts) в `src/chutils/scraping/profiles/adapters/playwright.py`.
12
- - [ ] Task: Реализовать адаптер экспорта/импорта для `nodriver` через CDP в `src/chutils/scraping/profiles/adapters/nodriver.py`.
13
- - [ ] Task: Реализовать адаптер экспорта/импорта для `selenium`/`undetected_chromedriver` в `src/chutils/scraping/profiles/adapters/selenium.py`.
14
- - [ ] Task: Написать unit-тесты с моками для всех трех адаптеров движков в `tests/unit/scraping/test_profile_adapters.py`.
11
+ - [x] Task: Реализовать адаптер экспорта/импорта для `playwright` (Async & Sync Contexts) в `src/chutils/scraping/profiles/adapters/playwright.py`.
12
+ - [x] Task: Реализовать адаптер экспорта/импорта для `nodriver` через CDP в `src/chutils/scraping/profiles/adapters/nodriver.py`.
13
+ - [x] Task: Реализовать адаптер экспорта/импорта для `selenium`/`undetected_chromedriver` в `src/chutils/scraping/profiles/adapters/selenium.py`.
14
+ - [x] Task: Написать unit-тесты с моками для всех трех адаптеров движков в `tests/unit/scraping/test_profile_adapters.py`.
15
15
 
16
16
  ## Phase 3: ProfileManager & Public API Integration
17
- - [ ] Task: Создать единый интерфейс `ProfileManager` в `src/chutils/scraping/profiles/manager.py` с методами `export_profile()`, `import_profile()`, `convert_profile()`.
18
- - [ ] Task: Экспортировать `BrowserProfile` и `ProfileManager` в `src/chutils/scraping/__init__.py` и `src/chutils/__init__.py` с поддержкой ленивой загрузки (PEP 562).
19
- - [ ] Task: Добавить интеграционные тесты конвертации профилей между движками в `tests/unit/scraping/test_profile_manager.py`.
17
+ - [x] Task: Создать единый интерфейс `ProfileManager` в `src/chutils/scraping/profiles/manager.py` с методами `export_profile()`, `import_profile()`, `convert_profile()`.
18
+ - [x] Task: Экспортировать `BrowserProfile` и `ProfileManager` в `src/chutils/scraping/__init__.py` и `src/chutils/__init__.py` с поддержкой ленивой загрузки (PEP 562).
19
+ - [x] Task: Добавить интеграционные тесты конвертации профилей между движками в `tests/unit/scraping/test_profile_manager.py`.
20
20
 
21
21
  ## Phase 4: Verification & Documentation
22
- - [ ] Task: Проверить проект через `uv run mypy src/chutils` и `uv run pytest`.
23
- - [ ] Task: Обновить документацию в `docs/scraping.md` и сгенерировать контекст через `uv run chutils dev generate-context --force -o api_map.md`.
22
+ - [x] Task: Проверить проект через `uv run mypy src/chutils` и `uv run pytest`.
23
+ - [x] Task: Обновить документацию в `docs/scraping.md` и сгенерировать контекст через `uv run chutils dev generate-context --force -o api_map.md`.
@@ -0,0 +1,15 @@
1
+ # Implementation Plan - Extension of Plugins System for Captcha and Scraping (`plugins_extension_20260805`)
2
+
3
+ ## Phase 1: Core Interfaces (`src/chutils/plugins/interfaces.py` & `src/chutils/plugins/core.py`)
4
+ - [x] Task: Добавить `CaptchaSolverPlugin` и `TaskQueuePlugin` в `src/chutils/plugins/interfaces.py`.
5
+ - [x] Task: Обновить `src/chutils/plugins/__init__.py` для экспорта новых плагин-интерфейсов.
6
+ - [x] Task: Добавить хелперы `get_captcha_solver_plugin(name)` и `get_task_queue_plugin(name)` в `src/chutils/plugins/core.py`.
7
+
8
+ ## Phase 2: Integration & Factories
9
+ - [x] Task: Интегрировать поддержку плагинов в `src/chutils/scraping/captcha/` (фабрика солверов по имени).
10
+ - [x] Task: Интегрировать поддержку плагинов в `src/chutils/scraping/concurrency/` (фабрика очередей по имени).
11
+
12
+ ## Phase 3: Unit Testing & Verification
13
+ - [x] Task: Написать unit-тесты регистрации и подгрузки кастомных плагинов в `tests/unit/plugins/test_plugins.py`.
14
+ - [x] Task: Проверить типы через `uv run mypy src/chutils` и прогнать `uv run pytest tests/unit/plugins/test_plugins.py`.
15
+ - [x] Task: Перегенерировать карты API `api_map.md` и `project_index.json`.