chutils 3.6.0__tar.gz → 3.7.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.
- {chutils-3.6.0 → chutils-3.7.0}/.github/workflows/ci.yml +46 -46
- {chutils-3.6.0 → chutils-3.7.0}/PKG-INFO +5 -1
- {chutils-3.6.0 → chutils-3.7.0}/ai-lint.toml +2 -0
- {chutils-3.6.0 → chutils-3.7.0}/api_map.md +19 -12
- {chutils-3.6.0 → chutils-3.7.0}/benchmarks/cold_start.py +2 -2
- chutils-3.7.0/conductor/archive/advanced_antidetect_e2e_20260910/index.md +5 -0
- chutils-3.7.0/conductor/archive/advanced_antidetect_e2e_20260910/index.md.metadata.json +4 -0
- chutils-3.7.0/conductor/archive/advanced_antidetect_e2e_20260910/metadata.json +8 -0
- chutils-3.7.0/conductor/archive/advanced_antidetect_e2e_20260910/plan.md +29 -0
- chutils-3.7.0/conductor/archive/advanced_antidetect_e2e_20260910/plan.md.metadata.json +4 -0
- chutils-3.7.0/conductor/archive/advanced_antidetect_e2e_20260910/spec.md +25 -0
- chutils-3.7.0/conductor/archive/advanced_antidetect_e2e_20260910/spec.md.metadata.json +4 -0
- chutils-3.7.0/conductor/archive/nodriver_antidetect_20260910/index.md +5 -0
- chutils-3.7.0/conductor/archive/nodriver_antidetect_20260910/metadata.json +8 -0
- chutils-3.7.0/conductor/archive/nodriver_antidetect_20260910/plan.md +41 -0
- chutils-3.7.0/conductor/archive/nodriver_antidetect_20260910/spec.md +31 -0
- chutils-3.7.0/conductor/archive/nodriver_launch_turnstile_fix_20260910/index.md +5 -0
- chutils-3.7.0/conductor/archive/nodriver_launch_turnstile_fix_20260910/metadata.json +9 -0
- chutils-3.7.0/conductor/archive/nodriver_launch_turnstile_fix_20260910/plan.md +39 -0
- chutils-3.7.0/conductor/archive/nodriver_launch_turnstile_fix_20260910/spec.md +34 -0
- chutils-3.7.0/conductor/archive/nodriver_stealth_turnstile_20260910/index.md +5 -0
- chutils-3.7.0/conductor/archive/nodriver_stealth_turnstile_20260910/metadata.json +8 -0
- chutils-3.7.0/conductor/archive/nodriver_stealth_turnstile_20260910/plan.md +38 -0
- chutils-3.7.0/conductor/archive/nodriver_stealth_turnstile_20260910/spec.md +53 -0
- chutils-3.7.0/conductor/archive/profile_warmer_20260910/index.md +5 -0
- chutils-3.7.0/conductor/archive/profile_warmer_20260910/metadata.json +8 -0
- chutils-3.7.0/conductor/archive/profile_warmer_20260910/plan.md +38 -0
- chutils-3.7.0/conductor/archive/profile_warmer_20260910/spec.md +33 -0
- chutils-3.7.0/conductor/archive/proxy_manager_20260910/index.md +5 -0
- chutils-3.7.0/conductor/archive/proxy_manager_20260910/metadata.json +8 -0
- chutils-3.7.0/conductor/archive/proxy_manager_20260910/plan.md +39 -0
- chutils-3.7.0/conductor/archive/proxy_manager_20260910/spec.md +42 -0
- chutils-3.7.0/conductor/archive/scraping_testing_20260910/index.md +5 -0
- chutils-3.7.0/conductor/archive/scraping_testing_20260910/metadata.json +8 -0
- chutils-3.7.0/conductor/archive/scraping_testing_20260910/plan.md +50 -0
- chutils-3.7.0/conductor/archive/scraping_testing_20260910/spec.md +48 -0
- chutils-3.7.0/conductor/archive/tls_impersonation_antidetect_20260910/index.md +5 -0
- chutils-3.7.0/conductor/archive/tls_impersonation_antidetect_20260910/metadata.json +8 -0
- chutils-3.7.0/conductor/archive/tls_impersonation_antidetect_20260910/plan.md +40 -0
- chutils-3.7.0/conductor/archive/tls_impersonation_antidetect_20260910/spec.md +36 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/product.md +24 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/tech-stack.md +2 -0
- chutils-3.7.0/conductor/tracks/nextgen_antidetect_bidi_20260915/index.md +5 -0
- chutils-3.7.0/conductor/tracks/nextgen_antidetect_bidi_20260915/metadata.json +8 -0
- chutils-3.7.0/conductor/tracks/nextgen_antidetect_bidi_20260915/plan.md +50 -0
- chutils-3.7.0/conductor/tracks/nextgen_antidetect_bidi_20260915/spec.md +59 -0
- chutils-3.7.0/conductor/tracks.md +39 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/ai_examples/configuration/bad_pattern.py +22 -22
- {chutils-3.6.0 → chutils-3.7.0}/docs/ai_examples/error_handling/good_pattern.py +92 -92
- {chutils-3.6.0 → chutils-3.7.0}/docs/ai_examples/logging/bad_pattern.py +27 -27
- {chutils-3.6.0 → chutils-3.7.0}/docs/ai_examples/logging/good_pattern.py +38 -38
- {chutils-3.6.0 → chutils-3.7.0}/docs/ai_examples/optional_deps/bad_pattern.py +48 -48
- {chutils-3.6.0 → chutils-3.7.0}/docs/ai_examples/optional_deps/good_pattern.py +68 -68
- {chutils-3.6.0 → chutils-3.7.0}/docs/api.md +43 -1
- {chutils-3.6.0 → chutils-3.7.0}/docs/dependencies.md +4 -2
- chutils-3.7.0/docs/http.md +221 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/migration.md +238 -238
- chutils-3.7.0/docs/scraping.md +1064 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/01_configuration.py +50 -50
- {chutils-3.6.0 → chutils-3.7.0}/examples/06_local_config_override.py +81 -81
- {chutils-3.6.0 → chutils-3.7.0}/examples/08_multiple_loggers_example.py +40 -40
- {chutils-3.6.0 → chutils-3.7.0}/examples/22_safe_path_resolution.py +91 -91
- {chutils-3.6.0 → chutils-3.7.0}/examples/26_metrics_prometheus.py +1 -1
- {chutils-3.6.0 → chutils-3.7.0}/examples/captcha_solvers_usage.py +67 -67
- {chutils-3.6.0 → chutils-3.7.0}/examples/scraping_humanize_usage.py +69 -69
- {chutils-3.6.0 → chutils-3.7.0}/project_index.json +6137 -227
- {chutils-3.6.0 → chutils-3.7.0}/pyproject.toml +196 -170
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/__init__.py +448 -438
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/cli_utils.py +2 -1
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/pypi.py +5 -4
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/config/core.py +1 -3
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/config/manager.py +411 -411
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/config/paths.py +212 -212
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/config/tracing.py +125 -125
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/few_shot/detector.py +3 -1
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/few_shot/writer.py +3 -1
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/rules/docstring.py +8 -8
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/rules/security.py +133 -133
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/env.py +1 -1
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/events/__init__.py +0 -1
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/events/core.py +0 -1
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/http/__init__.py +77 -63
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/http/async_client.py +333 -335
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/http/client.py +10 -10
- chutils-3.7.0/src/chutils/http/tls_client.py +558 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/lifecycle.py +26 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/logger/handlers.py +6 -1
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/logger/internal/builder.py +4 -1
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/qt/shim.py +2 -1
- chutils-3.7.0/src/chutils/scraping/__init__.py +213 -0
- chutils-3.7.0/src/chutils/scraping/camoufox.py +61 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/captcha/exceptions.py +17 -17
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/humanize/__init__.py +71 -48
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/humanize/actions.py +23 -3
- chutils-3.7.0/src/chutils/scraping/humanize/antidetect.py +421 -0
- chutils-3.7.0/src/chutils/scraping/humanize/antidetect_scripts.py +464 -0
- chutils-3.7.0/src/chutils/scraping/humanize/config.py +179 -0
- chutils-3.7.0/src/chutils/scraping/humanize/search.py +176 -0
- chutils-3.7.0/src/chutils/scraping/humanize/turnstile.py +422 -0
- chutils-3.7.0/src/chutils/scraping/humanize/warmer.py +622 -0
- chutils-3.7.0/src/chutils/scraping/nodriver.py +186 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/profiles/adapters/selenium.py +3 -1
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/profiles/manager.py +76 -0
- chutils-3.7.0/src/chutils/scraping/proxy/__init__.py +64 -0
- chutils-3.7.0/src/chutils/scraping/proxy/adapters.py +116 -0
- chutils-3.7.0/src/chutils/scraping/proxy/extension.py +217 -0
- chutils-3.7.0/src/chutils/scraping/proxy/models.py +124 -0
- chutils-3.7.0/src/chutils/scraping/proxy/parser.py +122 -0
- chutils-3.7.0/src/chutils/scraping/proxy/pool.py +287 -0
- chutils-3.7.0/src/chutils/scraping/proxy/tunnel.py +379 -0
- chutils-3.7.0/src/chutils/scraping/testing/__init__.py +123 -0
- chutils-3.7.0/src/chutils/scraping/testing/assertions.py +182 -0
- chutils-3.7.0/src/chutils/scraping/testing/fixtures.py +112 -0
- chutils-3.7.0/src/chutils/scraping/testing/mocks/__init__.py +26 -0
- chutils-3.7.0/src/chutils/scraping/testing/mocks/dom.py +250 -0
- chutils-3.7.0/src/chutils/scraping/testing/mocks/nodriver.py +154 -0
- chutils-3.7.0/src/chutils/scraping/testing/mocks/playwright.py +203 -0
- chutils-3.7.0/src/chutils/scraping/testing/mocks/selenium.py +199 -0
- chutils-3.7.0/src/chutils/scraping/testing/server.py +329 -0
- chutils-3.7.0/src/chutils/scraping/testing/session.py +207 -0
- chutils-3.7.0/src/chutils/scraping/testing/snapshot.py +281 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/secret_manager/core.py +2 -1
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/secret_manager/providers/gcp.py +4 -2
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/tasks/core.py +0 -1
- {chutils-3.6.0 → chutils-3.7.0}/tests/conftest.py +4 -2
- chutils-3.7.0/tests/e2e/test_antidetect_e2e.py +212 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/integration/test_ai_lint_integration.py +52 -52
- {chutils-3.6.0 → chutils-3.7.0}/tests/integration/test_hooks_integration.py +43 -43
- {chutils-3.6.0 → chutils-3.7.0}/tests/manual/manual_test_cli_booster.py +2 -2
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_diagnostics.py +1 -1
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_init.py +1 -1
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_config_required.py +157 -157
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/core/test_time.py +1 -1
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/dev/test_ai_lint_staged.py +2 -1
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/dev/test_chat_context.py +252 -252
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/dev/test_env_parser.py +3 -3
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/dev/test_scaffold.py +151 -149
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/di/test_di.py +1 -1
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/events/test_event_bus.py +1 -1
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/logger/conftest.py +2 -9
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/logger/test_config_sections.py +127 -127
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/metrics/test_metrics.py +2 -3
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/plugins/test_integration.py +1 -1
- chutils-3.7.0/tests/unit/scraping/test_advanced_antidetect.py +137 -0
- chutils-3.7.0/tests/unit/scraping/test_antidetect_config.py +170 -0
- chutils-3.7.0/tests/unit/scraping/test_clearance_bridge.py +124 -0
- chutils-3.7.0/tests/unit/scraping/test_extraction_assertions.py +126 -0
- chutils-3.7.0/tests/unit/scraping/test_live_server_session.py +94 -0
- chutils-3.7.0/tests/unit/scraping/test_nodriver_launcher.py +135 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/scraping/test_profile_manager.py +37 -0
- chutils-3.7.0/tests/unit/scraping/test_proxy_adapters.py +70 -0
- chutils-3.7.0/tests/unit/scraping/test_proxy_extension.py +74 -0
- chutils-3.7.0/tests/unit/scraping/test_proxy_models.py +160 -0
- chutils-3.7.0/tests/unit/scraping/test_proxy_tunnel.py +196 -0
- chutils-3.7.0/tests/unit/scraping/test_pytest_plugin.py +57 -0
- chutils-3.7.0/tests/unit/scraping/test_scraper_mocks.py +124 -0
- chutils-3.7.0/tests/unit/scraping/test_scraping_proxy_pool.py +164 -0
- chutils-3.7.0/tests/unit/scraping/test_snapshot_recorder.py +113 -0
- chutils-3.7.0/tests/unit/scraping/test_turnstile_solver.py +541 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/secret_manager/test_secrets_required.py +87 -87
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/tasks/test_scheduler.py +0 -2
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_ai_lint_ignore.py +103 -103
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_anticaptcha.py +130 -130
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_antidetect.py +74 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_audit.py +5 -5
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_capmonster.py +92 -92
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_captcha_base.py +41 -41
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_captcha_imports.py +25 -25
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_concurrency_queues.py +4 -2
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_crypto_dependencies.py +56 -56
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_decorators_bulkhead.py +16 -9
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_events_exception_group.py +46 -46
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_http_streaming.py +2 -5
- chutils-3.7.0/tests/unit/test_http_tls_client.py +216 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_humanize_math.py +106 -107
- chutils-3.7.0/tests/unit/test_minimal_imports.py +61 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_nodriver_humanize.py +67 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_playwright_humanize.py +106 -106
- chutils-3.7.0/tests/unit/test_profile_warmer.py +380 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_rucaptcha.py +121 -121
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_scraping_imports.py +42 -42
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_selenium_humanize.py +134 -134
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_text_dependencies.py +23 -23
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_vkma_integrations.py +0 -2
- {chutils-3.6.0 → chutils-3.7.0}/uv.lock +1051 -284
- chutils-3.6.0/conductor/tracks.md +0 -35
- chutils-3.6.0/docs/http.md +0 -151
- chutils-3.6.0/docs/scraping.md +0 -337
- chutils-3.6.0/src/chutils/scraping/__init__.py +0 -35
- chutils-3.6.0/src/chutils/scraping/humanize/antidetect.py +0 -222
- chutils-3.6.0/src/chutils/scraping/humanize/warmer.py +0 -232
- chutils-3.6.0/tests/unit/test_minimal_imports.py +0 -88
- chutils-3.6.0/tests/unit/test_profile_warmer.py +0 -147
- {chutils-3.6.0 → chutils-3.7.0}/.chutilsignore +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/.gitattributes +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/.github/workflows/publish-docs.yml +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/.gitignore +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/CODE_OF_CONDUCT.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/CONTRIBUTING.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/GEMINI.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/LICENSE +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/README.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/.gitignore +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/GEMINI.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/ai_context_opt_20260728/index.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/ai_context_opt_20260728/metadata.json +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/ai_context_opt_20260728/plan.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/ai_context_opt_20260728/spec.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/async_lifecycle_20260728/index.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/async_lifecycle_20260728/metadata.json +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/async_lifecycle_20260728/plan.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/async_lifecycle_20260728/spec.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/browser_profiles_20260728/index.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/browser_profiles_20260728/metadata.json +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/browser_profiles_20260728/plan.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/browser_profiles_20260728/spec.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/plugins_extension_20260805/plan.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/plugins_extension_20260805/spec.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/python315_support_20260827/index.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/python315_support_20260827/metadata.json +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/python315_support_20260827/plan.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/python315_support_20260827/spec.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/queue_monitoring_20260728/index.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/queue_monitoring_20260728/metadata.json +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/queue_monitoring_20260728/plan.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/queue_monitoring_20260728/spec.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/stream_crypto_20260728/index.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/stream_crypto_20260728/metadata.json +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/stream_crypto_20260728/plan.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/stream_crypto_20260728/spec.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_access_20260729/index.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_access_20260729/metadata.json +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_access_20260729/plan.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_access_20260729/spec.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_formatting_20260729/index.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_formatting_20260729/metadata.json +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_formatting_20260729/plan.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_formatting_20260729/spec.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_keyboard_20260729/index.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_keyboard_20260729/metadata.json +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_keyboard_20260729/plan.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_keyboard_20260729/spec.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_logging_20260729/index.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_logging_20260729/metadata.json +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_logging_20260729/plan.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_logging_20260729/spec.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_media_20260729/index.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_media_20260729/metadata.json +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_media_20260729/plan.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_media_20260729/spec.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_notifier_20260729/index.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_notifier_20260729/metadata.json +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_notifier_20260729/plan.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_notifier_20260729/spec.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_ratelimit_20260729/index.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_ratelimit_20260729/metadata.json +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_ratelimit_20260729/plan.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_ratelimit_20260729/spec.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_send_file_20260729/index.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_send_file_20260729/metadata.json +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_send_file_20260729/plan.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_send_file_20260729/spec.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_whitelist_20260729/index.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_whitelist_20260729/metadata.json +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_whitelist_20260729/plan.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/telegram_whitelist_20260729/spec.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/vk_callback_20260807/index.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/vk_callback_20260807/metadata.json +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/vk_callback_20260807/plan.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/vk_callback_20260807/spec.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/vk_scaffold_20260807/index.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/vk_scaffold_20260807/metadata.json +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/vk_scaffold_20260807/plan.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/vk_scaffold_20260807/spec.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/vk_testing_20260807/index.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/vk_testing_20260807/metadata.json +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/vk_testing_20260807/plan.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/vk_testing_20260807/spec.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/vkma_20260807/index.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/vkma_20260807/metadata.json +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/vkma_20260807/plan.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/archive/vkma_20260807/spec.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/code_styleguides/python.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/index.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/product-guidelines.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/setup_state.json +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/conductor/workflow.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/CODE_OF_CONDUCT_RU.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/CONTRIBUTING_RU.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/INTEGRATION_AI.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/README_RU.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/ai_examples/README.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/ai_examples/configuration/README.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/ai_examples/configuration/good_pattern.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/ai_examples/error_handling/README.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/ai_examples/error_handling/bad_pattern.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/ai_examples/logging/README.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/ai_examples/optional_deps/README.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/ai_examples/secrets/README.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/ai_examples/secrets/bad_pattern.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/ai_examples/secrets/good_pattern.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/ai_hints.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/ai_lint.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/audit.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/captcha.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/cli/check.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/cli/config.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/cli/db.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/cli/dev.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/cli/env.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/cli/index.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/cli/init.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/cli/pypi.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/cli/secrets.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/cli/show_paths.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/cli/template.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/cli/validate.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/custom_config_providers.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/index.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/plugins.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/qt.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/recipes.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/store.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/telegram.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/testing.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/vk_bot.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/vk_testing.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/vkma.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/docs/web.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/.env +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/02_logging.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/03_secrets.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/04_full_example.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/05_different_log_levels.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/07_decorators_example.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/09_disable_keyring.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/10_universal_env_override.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/11_retry_decorator.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/12_secret_masking.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/13_pydantic_validation.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/15_context_logging.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/16_cloud_secret_managers.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/17_timeout_decorator.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/18_config_hot_reload.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/19_remote_config.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/20_opentelemetry_tracing.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/21_config_diagnostics.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/22_circuit_breaker_decorator.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/22_qt_logging.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/23_event_bus.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/23_qt_async.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/24_qt_typed_signals.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/24_task_scheduler.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/25_testing_fixtures_example.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/27_rate_limiting.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/28_dependency_injection.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/concurrency_scraping_usage.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/config.yml +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/examples/web_client_usage.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/mkdocs.yml +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/__init__.pyi +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/__main__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/antigravity.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/audit/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/audit/_hash.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/audit/api.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/audit/backends/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/audit/backends/base.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/audit/backends/file.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/audit/backends/postgres.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/audit/backends/sqlite.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/audit/schema.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/cache/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/cache/base.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/cache/decorator.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/cache/in_memory.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/cache/utils.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/cli.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/cli_booster.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/base.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/check.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/config.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/db.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/dev/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/dev/ai_lint.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/dev/base.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/dev/chat_context.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/dev/clean.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/dev/dashboard.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/dev/diagnostics.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/dev/few_shot.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/dev/generate_context.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/dev/hooks.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/dev/lock.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/dev/mock.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/dev/profile_imports.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/dev/scaffold.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/dev/setup_github_actions.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/dev/sync_env.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/dev/watch.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/env.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/init.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/paths.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/secrets.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/template.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/utils.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/commands/validate.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/config/GEMINI.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/config/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/config/ast_fallback_parser.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/config/custom_providers.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/config/dev.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/config/diagnostics.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/config/generator.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/config/getters.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/config/integrations.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/config/providers.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/config/schema.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/config/sse.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/config/utils.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/config/watcher.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/config/webhook_server.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/context.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/crypto.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/db.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/decorators.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/ai_lint.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/ast_indexer.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/changelog_parser.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/chat_context.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/cleaner.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/constants.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/context/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/context/gitignore.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/context/incremental.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/dashboard/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/dashboard/indexer.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/dashboard/input.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/dashboard/tui.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/env_parser.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/env_sync.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/few_shot/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/few_shot/models.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/few_shot/renderer.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/github_actions.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/mock_server.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/models/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/models/base.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/models/index.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/models/node.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/models/symbol.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/profile_imports.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/project_metadata.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/rules/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/rules/api_map.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/rules/decomposition.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/rules/dependency_sync.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/rules/env.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/rules/integration.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/rules/linter_coverage.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/rules/manifest.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/rules/upgrade_check.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/runners.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/scaffold.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/upgrade_client.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/version_detector.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/dev/watcher.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/di/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/di/__init__.pyi +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/di/container.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/diagnostics/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/diagnostics/manager.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/diagnostics/models.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/diagnostics/web.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/env.pyi +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/exceptions/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/exceptions/audit.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/exceptions/base.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/exceptions/cache.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/exceptions/config.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/exceptions/di.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/exceptions/events.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/exceptions/logger.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/exceptions/resilience.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/exceptions/secrets.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/exceptions/system.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/exceptions/telegram.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/exceptions/validation.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/exceptions/vkma.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/exceptions/watcher.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/features.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/fs.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/http/api.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/http/fallback.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/http/resilience.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/http/streaming.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/http/tracing.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/logger/GEMINI.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/logger/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/logger/core.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/logger/formatters.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/logger/internal/levels.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/logger/internal/utils.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/logger/masking.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/metrics/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/metrics/base.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/metrics/in_memory.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/metrics/prometheus.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/metrics/timer.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/plugins/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/plugins/core.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/plugins/interfaces.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/qt/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/qt/asyncio.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/qt/logging.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/qt/signals.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/qt/widgets.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scaffold.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/captcha/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/captcha/anticaptcha.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/captcha/base.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/captcha/capmonster.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/captcha/rucaptcha.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/concurrency/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/concurrency/base.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/concurrency/limiter.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/concurrency/metrics.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/concurrency/models.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/concurrency/pool.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/concurrency/queues.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/humanize/math_utils.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/profiles/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/profiles/adapters/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/profiles/adapters/nodriver.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/profiles/adapters/playwright.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/profiles/models.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/scraping/profiles/storage.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/secret_manager/GEMINI.md +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/secret_manager/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/secret_manager/providers/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/secret_manager/providers/aws.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/secret_manager/providers/base.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/secret_manager/providers/dotenv.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/secret_manager/providers/env.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/secret_manager/providers/keyring_provider.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/store/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/store/backends/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/store/backends/base.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/store/backends/memcached.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/store/backends/memory.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/store/backends/redis.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/store/decorator.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/store/manager.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/tasks/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/tasks/__init__.pyi +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/telegram/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/telegram/access.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/telegram/aiogram.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/telegram/formatting.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/telegram/keyboard.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/telegram/logging.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/telegram/media.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/telegram/notifier.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/telegram/rate_limit.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/telegram/whitelist.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/templates/vk/vk-miniapp/backend/config.yml.template +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/templates/vk/vk-miniapp/backend/main.py.template +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/templates/vk/vk-miniapp/docker-compose.yml.template +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/templates/vk/vk-miniapp/frontend/App.jsx.template +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/testing/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/testing/fixtures.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/text.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/time.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/tracing.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/typing.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/validation.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/validation.pyi +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/vk/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/vk/callback/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/vk/callback/router.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/vk/testing/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/vk/testing/fixtures.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/vk/testing/generators.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/vkma/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/vkma/exceptions.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/vkma/integrations/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/vkma/integrations/aiohttp.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/vkma/integrations/fastapi.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/vkma/integrations/flask.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/vkma/models.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/vkma/testing.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/vkma/validator.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/web/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/web/client.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/web/proxy_pool.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/src/chutils/web/user_agent.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/integration/__init__.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/integration/test_cli_e2e.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/integration/test_db_migrations.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/integration/test_event_loops.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/integration/test_examples.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/integration/test_masking_integration.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/integration/test_otel_tracing.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/integration/test_remote_config_integration.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/integration/test_setup_github_actions_integration.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/conftest.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_booster.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_check.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_config.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_config_cmd.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_config_schema.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_dev.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_dev_cmd.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_dev_lock.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_dev_tree.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_dev_watch.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_extras_suggestion.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_init_interactive.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_paths.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_pypi.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_rich.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_rich_width.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_secrets.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_setup_github_actions.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_template.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_utils_internal.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/cli/test_cli_validate.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_config.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_config_ast_parser.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_config_dev.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_config_diagnostics.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_config_env.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_config_env_loading.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_config_generator.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_config_integrations.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_config_json.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_config_pydantic.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_config_schema.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_config_sse.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_config_sse_integration.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_config_tracing.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_config_universal_env.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_config_utils.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_config_validation_group.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_config_watcher.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_config_webhook.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_custom_config_providers.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_priority_unification.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/config/test_remote_config.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/core/test_ast_indexer.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/core/test_ast_indexer_abstract.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/core/test_ast_indexer_graph.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/core/test_ast_indexer_layers.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/core/test_ast_indexer_metadata.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/core/test_cache.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/core/test_dev_models.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/core/test_exceptions.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/core/test_features.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/core/test_fs.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/core/test_lifecycle.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/core/test_thread_safety.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/decorators/test_decorator_circuit_breaker.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/decorators/test_decorator_retry.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/decorators/test_decorator_timeout.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/decorators/test_decorators.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/decorators/test_rate_limit.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/dev/test_ai_lint.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/dev/test_changelog_parser.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/dev/test_cleaner.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/dev/test_context_generator.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/dev/test_env_sync.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/dev/test_generate_few_shot.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/dev/test_linter_coverage_rule.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/dev/test_mock_server.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/dev/test_runners.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/dev/test_setup_github_actions.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/dev/test_upgrade_check_rule.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/dev/test_upgrade_client.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/dev/test_version_detector.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/dev/test_watcher.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/logger/test_basics.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/logger/test_compression.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/logger/test_configuration.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/logger/test_context.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/logger/test_env_control.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/logger/test_files.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/logger/test_json_format.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/logger/test_logger_rich_width.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/logger/test_masking.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/logger/test_performance_security.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/logger/test_rich.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/logger/test_rotation.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/plugins/test_interfaces.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/plugins/test_plugins.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/scraping/test_profile_adapters.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/scraping/test_profile_storage.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/scraping/test_queue_metrics.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/scraping/test_worker_metrics.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/secret_manager/test_secret_manager.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/secret_manager/test_secret_manager_env.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/secret_manager/test_secret_manager_providers.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/telegram/test_access.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/telegram/test_aiogram_filter.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/telegram/test_aiogram_middleware.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/telegram/test_formatting.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/telegram/test_keyboard.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/telegram/test_logging.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/telegram/test_notifier.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/telegram/test_telegram_rate_limit.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/telegram/test_whitelist.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_async_web_client.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_audit_phase2.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_cli_db.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_concurrency_imports.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_concurrency_limiter.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_concurrency_pool.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_config_alias_choices.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_config_fallback.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_crypto.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_crypto_stream.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_dashboard.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_db_init.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_db_operations.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_diagnostics.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_env.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_http_api.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_http_client.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_http_fallback.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_http_resilience.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_http_tracing.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_init_templates.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_install_hooks.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_profile_imports.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_proxy_pool.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_qt_asyncio.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_qt_logging.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_qt_shim.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_qt_signals.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_qt_widgets.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_store_backends_external.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_store_integrations.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_store_manager.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_store_memory.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_telegram_media.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_telegram_send_file.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_text.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_user_agent.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_validation.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_vk_callback_fastapi.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_vk_callback_router.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_vk_testing_fixtures.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_vk_testing_generators.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_vkma_core.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_web_client.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/test_web_imports.py +0 -0
- {chutils-3.6.0 → chutils-3.7.0}/tests/unit/testing/test_fixtures.py +0 -0
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
name: CI
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [ main, master ]
|
|
6
|
-
pull_request:
|
|
7
|
-
branches: [ main, master ]
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
test-and-lint:
|
|
11
|
-
runs-on: ubuntu-latest
|
|
12
|
-
strategy:
|
|
13
|
-
matrix:
|
|
14
|
-
python-version: [ '3.10', '3.11', '3.12', '3.13', '3.14', '3.15-dev' ]
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
steps:
|
|
18
|
-
- uses: actions/checkout@v4
|
|
19
|
-
|
|
20
|
-
- name: Set up Python ${{ matrix.python-version }}
|
|
21
|
-
uses: actions/setup-python@v5
|
|
22
|
-
with:
|
|
23
|
-
python-version: ${{ matrix.python-version }}
|
|
24
|
-
|
|
25
|
-
- name: Install uv
|
|
26
|
-
uses: astral-sh/setup-uv@v5
|
|
27
|
-
with:
|
|
28
|
-
enable-cache: true
|
|
29
|
-
version: "latest"
|
|
30
|
-
|
|
31
|
-
- name: Install dependencies
|
|
32
|
-
run: |
|
|
33
|
-
uv sync --all-extras
|
|
34
|
-
|
|
35
|
-
- name: Run Tests
|
|
36
|
-
run: |
|
|
37
|
-
uv run pytest
|
|
38
|
-
|
|
39
|
-
- name: Run Type Checking (Mypy)
|
|
40
|
-
run: |
|
|
41
|
-
uv run mypy src
|
|
42
|
-
|
|
43
|
-
- name: Run AI-Readiness Audit
|
|
44
|
-
run: |
|
|
45
|
-
uv run python -m chutils dev ai-lint --soft-mode
|
|
46
|
-
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main, master ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main, master ]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test-and-lint:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: [ '3.10', '3.11', '3.12', '3.13', '3.14', '3.15-dev' ]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
21
|
+
uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: ${{ matrix.python-version }}
|
|
24
|
+
|
|
25
|
+
- name: Install uv
|
|
26
|
+
uses: astral-sh/setup-uv@v5
|
|
27
|
+
with:
|
|
28
|
+
enable-cache: true
|
|
29
|
+
version: "latest"
|
|
30
|
+
|
|
31
|
+
- name: Install dependencies
|
|
32
|
+
run: |
|
|
33
|
+
uv sync --all-extras
|
|
34
|
+
|
|
35
|
+
- name: Run Tests
|
|
36
|
+
run: |
|
|
37
|
+
uv run pytest
|
|
38
|
+
|
|
39
|
+
- name: Run Type Checking (Mypy)
|
|
40
|
+
run: |
|
|
41
|
+
uv run mypy src
|
|
42
|
+
|
|
43
|
+
- name: Run AI-Readiness Audit
|
|
44
|
+
run: |
|
|
45
|
+
uv run python -m chutils dev ai-lint --soft-mode
|
|
46
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: chutils
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.7.0
|
|
4
4
|
Summary: Набор простых и удобных утилит для Python, который избавляет от рутины при работе с конфигурацией и логированием в новых проектах.
|
|
5
5
|
Author-email: Chu4hel <sergeiivanov636@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -11,6 +11,8 @@ Requires-Dist: python-dotenv>=1.2.2
|
|
|
11
11
|
Requires-Dist: pyyaml>=6.0.3
|
|
12
12
|
Provides-Extra: aws
|
|
13
13
|
Requires-Dist: boto3>=1.34.0; extra == 'aws'
|
|
14
|
+
Provides-Extra: camoufox
|
|
15
|
+
Requires-Dist: camoufox>=0.4.0; extra == 'camoufox'
|
|
14
16
|
Provides-Extra: captcha
|
|
15
17
|
Requires-Dist: httpx>=0.27.0; extra == 'captcha'
|
|
16
18
|
Provides-Extra: crypto
|
|
@@ -71,6 +73,8 @@ Provides-Extra: testing
|
|
|
71
73
|
Requires-Dist: pytest>=9.0.3; extra == 'testing'
|
|
72
74
|
Provides-Extra: text
|
|
73
75
|
Requires-Dist: rapidfuzz>=3.9.0; extra == 'text'
|
|
76
|
+
Provides-Extra: tls
|
|
77
|
+
Requires-Dist: curl-cffi>=0.7.0; extra == 'tls'
|
|
74
78
|
Provides-Extra: vk
|
|
75
79
|
Requires-Dist: pydantic<3.0.0,>=2.13.4; extra == 'vk'
|
|
76
80
|
Provides-Extra: vkma
|
|
@@ -128,8 +128,10 @@
|
|
|
128
128
|
# ---------------------------------------------------------------------------
|
|
129
129
|
|
|
130
130
|
"src/chutils/scraping/**/*.py" = ["docs/scraping.md"]
|
|
131
|
+
"new:src/chutils/scraping/nodriver.py" = ["docs/scraping.md"]
|
|
131
132
|
"src/chutils/scraping/captcha/**/*.py" = ["docs/captcha.md"]
|
|
132
133
|
|
|
134
|
+
|
|
133
135
|
# ---------------------------------------------------------------------------
|
|
134
136
|
# Модуль аудита
|
|
135
137
|
# ---------------------------------------------------------------------------
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
-
chutils_version: 3.
|
|
3
|
-
project_version: 3.
|
|
4
|
-
git_commit:
|
|
5
|
-
generated_at: 2026-09-
|
|
6
|
-
project_hash:
|
|
2
|
+
chutils_version: 3.7.0
|
|
3
|
+
project_version: 3.7.0
|
|
4
|
+
git_commit: 5cb29a30832f6b1d6e3af1c4572da491e9a76968 (dirty)
|
|
5
|
+
generated_at: 2026-09-15T14:49:04.299233+00:00
|
|
6
|
+
project_hash: 58ba4b8fbabcd20573314c01c78c3ef9decdf6006d6aac4c12d7be9c84989f7a
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Public API Map: chutils
|
|
@@ -104,6 +104,8 @@ project_hash: fb14b689767aaa8d9826e388bf1bc7b7627bbc60d975d32d8e73cbab59a05758
|
|
|
104
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-серверу обновлений конфигурации. |
|
|
105
105
|
| `SseEvent` | class | `(self, event: 'str' = 'message', data: 'str' = '', event_id: 'str \| None' = None, retry: 'int \| None' = None) -> 'None'` | Представляет отдельное событие Server-Sent Events (SSE). |
|
|
106
106
|
| `StoreManager` | class | `(self, backend: 'BaseStoreBackend \| None' = None, serializer: 'str \| Any' = 'json', prefix: 'str' = '') -> 'None'` | Центральный менеджер Key-Value хранилища. |
|
|
107
|
+
| `TLSAsyncClient` | class | `(self, impersonate: 'str' = 'chrome120', proxy: 'ProxyConfig \| str \| None' = None, proxy_pool: 'ProxyPool \| None' = None, fallback_to_standard: 'bool' = False, timeout: 'float' = 30.0, **kwargs: 'Any') -> 'None'` | Асинхронный HTTP-клиент с поддержкой TLS/HTTP2 Client Impersonation (curl-cffi). |
|
|
108
|
+
| `TLSSession` | class | `(self, impersonate: 'str' = 'chrome120', proxy: 'ProxyConfig \| str \| None' = None, proxy_pool: 'ProxyPool \| None' = None, fallback_to_standard: 'bool' = False, timeout: 'float' = 30.0, **kwargs: 'Any') -> 'None'` | Синхронный HTTP-клиент с поддержкой TLS/HTTP2 Client Impersonation (curl-cffi). |
|
|
107
109
|
| `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
110
|
| `TelegramLoggingMiddleware` | class | `(self, logger_instance: 'Any' = None) -> 'None'` | Middleware контекстного логирования и измерений времени выполнения для aiogram 3.x. |
|
|
109
111
|
| `TelegramRateLimiter` | class | `(self, rate: 'int' = 1, per: 'float' = 1.0) -> 'None'` | Движок ограничений вызовов (Rate Limiter) для Telegram-ботов. |
|
|
@@ -120,17 +122,17 @@ project_hash: fb14b689767aaa8d9826e388bf1bc7b7627bbc60d975d32d8e73cbab59a05758
|
|
|
120
122
|
| `aget_config` | function | `(model: 'type[T] \| None' = None) -> 'JSONDict \| T'` | Асинхронная версия get_config. |
|
|
121
123
|
| `aget_config_value` | function | `(section: 'str', key: 'str', fallback: 'Any' = None, config: 'JSONDict \| None' = None, required: 'bool' = False) -> 'Any'` | Асинхронно получает произвольное значение из конфигурации. |
|
|
122
124
|
| `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]'` | Декоратор ограничения доступа по белым и черным спискам. |
|
|
123
|
-
| `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`
|
|
124
|
-
| `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`
|
|
125
|
-
| `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`
|
|
125
|
+
| `apply_antidetect_nodriver` | function | `(tab: 'Any', *, config: 'AntidetectConfig \| None' = None, 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, stealth_minimal: 'bool' = True, session_seed: 'str \| int' = 1337, client_hints: 'dict[str, Any] \| None' = None) -> 'None'` | Применяет JS-инъекции анти-детекта к вкладке (Tab) nodriver. |
|
|
126
|
+
| `apply_antidetect_playwright` | function | `(context: 'Any', *, config: 'AntidetectConfig \| None' = None, 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, stealth_minimal: 'bool' = False, session_seed: 'str \| int' = 1337, client_hints: 'dict[str, Any] \| None' = None) -> 'None'` | Применяет JS-инъекции анти-детекта к контексту Playwright. |
|
|
127
|
+
| `apply_antidetect_selenium` | function | `(driver: 'Any', *, config: 'AntidetectConfig \| None' = None, 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, stealth_minimal: 'bool' = False, session_seed: 'str \| int' = 1337, client_hints: 'dict[str, Any] \| None' = None) -> 'None'` | Применяет JS-инъекции анти-детекта к сессии Selenium. |
|
|
126
128
|
| `are_paths_initialized` | function | `() -> bool` | Проверяет, были ли инициализированы пути к проекту и файлам конфигурации. |
|
|
127
129
|
| `asave_config_value` | function | `(section: 'str', key: 'str', value: 'Any', cfg_file: 'str \| None' = None, save_to_local: 'bool' = False, notify: 'bool' = True) -> 'bool'` | Асинхронно сохраняет одно значение в конфигурационном файле. |
|
|
128
|
-
| `async_click` | function | `(page: Any, selector: str \| None = None, x: int \| None = None, y: int \| None = None, start: tuple[int, int] \| None = None, algorithm: str = 'windmouse', button: str = 'left') -> None`
|
|
130
|
+
| `async_click` | function | `(page: Any, selector: str \| None = None, x: int \| None = None, y: int \| None = None, start: tuple[int, int] \| None = None, algorithm: str = 'windmouse', button: str = 'left', hold_time: tuple[float, float] = (0.05, 0.12)) -> None` | Имитирует реалистичный клик мышью (с плавным наведением, микропаузами и удержанием кнопки). |
|
|
129
131
|
| `async_human_sleep` | function | `(min_seconds: float, max_seconds: float) -> None` | Асинхронно задерживает выполнение на случайное время, имитируя поведение человека. |
|
|
130
132
|
| `async_lifecycle` | function | `(setup_signals: 'bool' = True, auto_cleanup_subsystems: 'bool' = True) -> 'AsyncLifecycleContext'` | Возвращает контекстный менеджер для управления жизненным циклом ресурсов. |
|
|
131
133
|
| `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, algorithm: str = 'bezier') -> None` | Имитирует плавное перемещение мыши Playwright или nodriver. |
|
|
132
134
|
| `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. |
|
|
133
|
-
| `async_type_text` | function | `(page: Any, selector: str, text: str, error_rate: float = 0.05, speed_wpm: float = 40.0) -> None`
|
|
135
|
+
| `async_type_text` | function | `(page: Any, selector: str, text: str, error_rate: float = 0.05, speed_wpm: float = 40.0, key_hold_time: tuple[float, float] = (0.04, 0.09)) -> None` | Имитирует ввод текста с опечатками Playwright или nodriver. |
|
|
134
136
|
| `audit` | module | | chutils.audit — Неизменяемый журнал событий аудита. |
|
|
135
137
|
| `audit_context` | function | `(action: 'str', actor: 'str', *, target: 'str \| None' = None, backend: 'object') -> 'Generator[_AuditContextState, None, None]'` | Контекстный менеджер для регистрации события аудита в блоке кода. |
|
|
136
138
|
| `audit_event` | function | `(action: 'str', actor: '_ActorOrCallable' = 'system', *, target: '_TargetOrCallable' = None, backend: 'object') -> 'Callable'` | Декоратор для автоматической регистрации события аудита при вызове функции. |
|
|
@@ -143,10 +145,12 @@ project_hash: fb14b689767aaa8d9826e388bf1bc7b7627bbc60d975d32d8e73cbab59a05758
|
|
|
143
145
|
| `cleanup_paths` | function | `(*paths: 'str \| Path', retries: 'int' = 3, delay: 'float' = 0.1, on_locked: "Literal['raise', 'rename_orphan', 'warn']" = 'warn', orphan_collision: "Literal['raise', 'overwrite', 'unique']" = 'raise') -> 'None'` | Пакетное удаление нескольких путей. |
|
|
144
146
|
| `clear_context` | function | `() -> 'None'` | Полностью очищает текущий контекст. |
|
|
145
147
|
| `cli_command` | function | `(func: ~F) -> ~F` | Декоратор для превращения функции в CLI-команду. |
|
|
146
|
-
| `click` | function | `(driver: Any, selector: str \| None = None, x: int \| None = None, y: int \| None = None, start: tuple[int, int] \| None = None, algorithm: str = 'windmouse') -> None`
|
|
148
|
+
| `click` | function | `(driver: Any, selector: str \| None = None, x: int \| None = None, y: int \| None = None, start: tuple[int, int] \| None = None, algorithm: str = 'windmouse', hold_time: tuple[float, float] = (0.05, 0.12)) -> None` | Имитирует реалистичный клик мышью Selenium. |
|
|
147
149
|
| `config` | module | | Модуль для работы с конфигурацией. |
|
|
148
150
|
| `container` | constant | | Легковесный IoC/DI контейнер. |
|
|
149
151
|
| `context` | module | | |
|
|
152
|
+
| `create_curl_async_session` | function | `(impersonate: 'str', proxy: 'str \| None' = None, **kwargs: 'Any') -> 'Any'` | Создает асинхронную сессию curl_cffi с заданным профилем impersonate. |
|
|
153
|
+
| `create_curl_session` | function | `(impersonate: 'str', proxy: 'str \| None' = None, **kwargs: 'Any') -> 'Any'` | Создает синхронную сессию curl_cffi с заданным профилем impersonate. |
|
|
150
154
|
| `create_http_span` | function | `(method: 'str', url: 'str', tracer_name: 'str' = 'chutils.http') -> 'object \| None'` | Создаёт OTEL-спан для исходящего HTTP-запроса. |
|
|
151
155
|
| `crypto` | module | | Модуль для портативного детерминированного шифрования данных. |
|
|
152
156
|
| `dashboard` | module | | Интерактивный TUI-дашборд для CLI-команд проекта. |
|
|
@@ -166,6 +170,7 @@ project_hash: fb14b689767aaa8d9826e388bf1bc7b7627bbc60d975d32d8e73cbab59a05758
|
|
|
166
170
|
| `events` | module | | Модуль шины событий (In-Memory Event Bus). |
|
|
167
171
|
| `exceptions` | module | | |
|
|
168
172
|
| `export_schema` | function | `(model: type[pydantic.main.BaseModel] \| str, output_path: str \| pathlib.Path \| None = None, indent: int = 4) -> str` | Генерирует JSON Schema для Pydantic модели и опционально сохраняет в файл. |
|
|
173
|
+
| `extract_clearance_cookies` | function | `(target: 'Any') -> 'Any'` | Извлекает cookies (включая cf_clearance) и User-Agent из сессии браузера. |
|
|
169
174
|
| `few_shot` | module | | |
|
|
170
175
|
| `fs` | module | | Модуль для надежных операций с файловой системой. |
|
|
171
176
|
| `generate_env_template` | function | `(model_class: 'type[BaseModel]', prefix: 'str' = 'CH') -> 'str'` | Генерирует .env шаблон (плоский формат). |
|
|
@@ -175,7 +180,8 @@ project_hash: fb14b689767aaa8d9826e388bf1bc7b7627bbc60d975d32d8e73cbab59a05758
|
|
|
175
180
|
| `generate_yaml_template` | function | `(model_class: 'type[BaseModel]', indent: 'int' = 0) -> 'str'` | Генерирует YAML шаблон на основе Pydantic модели с комментариями. |
|
|
176
181
|
| `get_all_config_paths` | function | `(cfg_file: str \| None = None) -> tuple[str \| None, str \| None, str \| None]` | Возвращает пути к основному, специфичному для окружения и локальному файлам конфигурации. |
|
|
177
182
|
| `get_base_dir` | function | `() -> str \| None` | Возвращает абсолютный путь к корневой директории проекта. |
|
|
178
|
-
| `get_browser_launch_args` | function | `() -> list[str]`
|
|
183
|
+
| `get_browser_launch_args` | function | `() -> 'list[str]'` | Возвращает расширенный набор аргументов запуска браузера для скрытия автоматизации. |
|
|
184
|
+
| `get_client_hints` | function | `(user_agent: 'str \| None' = None) -> 'dict[str, Any]'` | Генерирует словарь согласованных Client Hints (navigator.userAgentData) на основе User-Agent. |
|
|
179
185
|
| `get_config` | function | `(model: 'type[T] \| None' = None, remote_url: 'str \| None' = None, remote_auth: 'tuple[str, str] \| None' = None, polling_interval: 'int \| None' = None, sse_url: 'str \| None' = None, sse_headers: 'dict[str, str] \| None' = None) -> 'JSONDict \| T'` | Загружает и объединяет конфигурацию из всех доступных источников. |
|
|
180
186
|
| `get_config_boolean` | function | `(section: 'str', key: 'str', fallback: 'bool' = False, config: 'JSONDict \| None' = None, required: 'bool' = False) -> 'bool'` | Получает булево значение из конфигурации. |
|
|
181
187
|
| `get_config_file_path` | function | `() -> str \| None` | Возвращает путь к основному файлу конфигурации, который используется в данный момент. |
|
|
@@ -199,6 +205,7 @@ project_hash: fb14b689767aaa8d9826e388bf1bc7b7627bbc60d975d32d8e73cbab59a05758
|
|
|
199
205
|
| `is_otel_enabled` | function | `() -> 'bool'` | Проверяет, доступен ли OpenTelemetry и не отключен ли он. |
|
|
200
206
|
| `is_rich_enabled` | function | `() -> 'bool'` | Централизованная проверка: доступен ли Rich и разрешен ли он настройками. |
|
|
201
207
|
| `is_significant_difference` | function | `(text1: str, text2: str, threshold: float = 0.9) -> bool` | Проверяет, является ли разница между двумя текстами значительной. |
|
|
208
|
+
| `launch_camoufox` | function | `(headless: 'bool' = True, os: 'str' = 'windows', **kwargs: 'Any') -> 'Any'` | Создает и возвращает контекстный менеджер / сессию браузера AsyncCamoufox. |
|
|
202
209
|
| `lifecycle` | module | | Управление жизненным циклом приложения. |
|
|
203
210
|
| `load_ai_lint_config` | function | `(cli_args: 'JSONDict \| None' = None) -> 'JSONDict'` | Загружает и объединяет конфигурацию для ai-lint из всех источников. |
|
|
204
211
|
| `log_function_details` | function | `(func: collections.abc.Callable[~P, ~R]) -> collections.abc.Callable[~P, ~R]` | Декоратор для логирования деталей вызова функции. |
|
|
@@ -35,13 +35,13 @@ loaded_chutils = [m for m in sys.modules if m.startswith('chutils.')]
|
|
|
35
35
|
print(json.dumps({{"duration": end - start, "modules": loaded_chutils}}))
|
|
36
36
|
"""
|
|
37
37
|
result = subprocess.run(
|
|
38
|
-
[sys.executable, "-c", script], capture_output=True, text=True
|
|
38
|
+
[sys.executable, "-c", script], capture_output=True, text=True, check=False
|
|
39
39
|
)
|
|
40
40
|
if result.returncode != 0:
|
|
41
41
|
print(f"Error: {result.stderr}")
|
|
42
42
|
try:
|
|
43
43
|
return json.loads(result.stdout)
|
|
44
|
-
except:
|
|
44
|
+
except Exception:
|
|
45
45
|
return None
|
|
46
46
|
return json.loads(result.stdout)
|
|
47
47
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"track_id": "advanced_antidetect_e2e_20260910",
|
|
3
|
+
"type": "feature",
|
|
4
|
+
"status": "new",
|
|
5
|
+
"created_at": "2026-09-10T15:53:30+03:00",
|
|
6
|
+
"updated_at": "2026-09-10T15:53:30+03:00",
|
|
7
|
+
"description": "Улучшение антидетекта (Web Workers, stack traces, cookie bridge) и E2E тесты"
|
|
8
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Implementation Plan: Продвинутый антидетект и E2E тесты
|
|
2
|
+
|
|
3
|
+
## Phase 1: Усиление JS-антидетекта (Web Workers & V8 Stacks)
|
|
4
|
+
- [x] Task: Написать unit-тесты для перехвата Worker и маскировки стектрейсов
|
|
5
|
+
- [x] Написать тесты на генерацию JS-кода с перехватом `Worker` и `SharedWorker`
|
|
6
|
+
- [x] Написать тесты на генерацию чистого `Error.prototype.stack` в геттерах
|
|
7
|
+
- [x] Task: Модернизация src/chutils/scraping/humanize/antidetect.py
|
|
8
|
+
- [x] Добавить в JS-скрипт перехват `window.Worker` и `window.SharedWorker` с инъекцией преамбулы
|
|
9
|
+
- [x] Улучшить хелпер `makeNative` для маскировки стектрейсов вызовов V8
|
|
10
|
+
- [x] Task: Conductor - User Manual Verification 'Phase 1: Worker & Stack Protection' (Protocol in workflow.md)
|
|
11
|
+
|
|
12
|
+
## Phase 2: Мост Cookie/Headers (Браузер -> TLSAsyncClient)
|
|
13
|
+
- [x] Task: Написать unit-тесты для extract_clearance_cookies
|
|
14
|
+
- [x] Написать тесты для извлечения кук и User-Agent из Playwright, Selenium и Nodriver моков
|
|
15
|
+
- [x] Task: Реализация extract_clearance_cookies и интеграция с TLSAsyncClient
|
|
16
|
+
- [x] Реализовать `extract_clearance_cookies` в `src/chutils/scraping/humanize/antidetect.py`
|
|
17
|
+
- [x] Добавить фабричный метод `from_browser_session` в `TLSAsyncClient` / `TLSSession`
|
|
18
|
+
- [x] Task: Conductor - User Manual Verification 'Phase 2: Cookie Bridge' (Protocol in workflow.md)
|
|
19
|
+
|
|
20
|
+
## Phase 3: E2E Тесты и финальная верификация
|
|
21
|
+
- [x] Task: Реализация E2E тестов в tests/e2e/test_antidetect_e2e.py
|
|
22
|
+
- [x] Реализовать E2E проверку TLS/JA4 профилей через peet.ws
|
|
23
|
+
- [x] Реализовать проверку чистоты окружения Worker и navigator
|
|
24
|
+
- [x] Реализовать сквозной тест передачи сессии из браузера в TLSAsyncClient
|
|
25
|
+
- [x] Task: Экспорт, документация и проверки качества
|
|
26
|
+
- [x] Добавить экспорт новых утилит в `src/chutils/__init__.py` и `src/chutils/scraping/__init__.py`
|
|
27
|
+
- [x] Обновить документацию `docs/scraping.md` и `docs/http.md`
|
|
28
|
+
- [x] Прогнать `pytest`, `mypy --strict`, `ruff check`, `ruff format --check`, `chutils dev lock --force`, `chutils dev ai-lint`
|
|
29
|
+
- [x] Task: Conductor - User Manual Verification 'Phase 3: E2E Testing & Verification' (Protocol in workflow.md)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Specification: Продвинутый антидетект (Web Workers, V8 Stacks, Cookie Bridge) и E2E тесты
|
|
2
|
+
|
|
3
|
+
## 1. Overview
|
|
4
|
+
Трек направлен на закрытие ключевых векторов обнаружения автоматизации (утечки через изолированные Web Workers/SharedWorkers, следы в Error.prototype.stack) и создание сквозного моста передачи сессионных cookie/заголовков из браузеров (Playwright/Camoufox/Nodriver) в высокоскоростные TLS-клиенты (TLSSession/TLSAsyncClient), а также покрытие функционала E2E-тестами.
|
|
5
|
+
|
|
6
|
+
## 2. Functional Requirements
|
|
7
|
+
- **Web Workers & SharedWorkers Protection**:
|
|
8
|
+
- Внедрение перехвата `window.Worker` и `window.SharedWorker` в `antidetect.py`.
|
|
9
|
+
- Автоматическая инъекция защитного преамбул-скрипта (очистка `navigator.webdriver`, подмена `navigator.userAgentData`, маскировка `toString`) при создании Worker через URL или Blob.
|
|
10
|
+
- **V8 Stack Traces Cloaking**:
|
|
11
|
+
- Улучшение `makeNative` для предотвращения утечек имен патч-функций и неверных строк стека при искусственном вызове ошибок внутри геттеров.
|
|
12
|
+
- **Cookie/Header Bridge (`extract_clearance_cookies`)**:
|
|
13
|
+
- Функция `extract_clearance_cookies(target: Any) -> dict[str, Any]` с извлечением кук (`cf_clearance`, `__cf_bm` и др.), заголовков и User-Agent из Playwright `BrowserContext`/`Page`, Selenium WebDriver и Nodriver Tab.
|
|
14
|
+
- Метод интеграции или фабрика создания `TLSAsyncClient.from_browser_session(session_or_page)`.
|
|
15
|
+
- **E2E Testing Suite**:
|
|
16
|
+
- Создание `tests/e2e/test_antidetect_e2e.py` (с маркером `@pytest.mark.e2e`):
|
|
17
|
+
- Тест валидации JA3/JA4 и HTTP/2 на реальном сервисе `https://tls.peet.ws/api/all`.
|
|
18
|
+
- Тест изоляции Web Workers и прототипов в браузере.
|
|
19
|
+
- Сквозной тест передачи сессии из браузера в `TLSAsyncClient`.
|
|
20
|
+
|
|
21
|
+
## 3. Acceptance Criteria
|
|
22
|
+
1. Web Workers не выдают `navigator.webdriver === true`.
|
|
23
|
+
2. Стектрейсы ошибок в пропатченных свойствах не содержат артефактов стороннего JS кода.
|
|
24
|
+
3. Функция `extract_clearance_cookies` успешно работает со всеми поддерживаемыми драйверами с graceful fallback.
|
|
25
|
+
4. Все E2E и unit-тесты проходят, mypy strict, ruff и ai-lint без ошибок и предупреждений.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"track_id": "nodriver_antidetect_20260910",
|
|
3
|
+
"type": "feature",
|
|
4
|
+
"status": "completed",
|
|
5
|
+
"created_at": "2026-09-10T02:42:00Z",
|
|
6
|
+
"updated_at": "2026-09-10T02:42:00Z",
|
|
7
|
+
"description": "Улучшение антидетекта и скрытия автоматизации nodriver (маскировка JS, нативные дескрипторы, микропаузы, Permissions API)"
|
|
8
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Implementation Plan: nodriver Anti-Detect & Stealth Enhancement
|
|
2
|
+
|
|
3
|
+
## Phase 1: JavaScript Anti-Tampering & Permissions Synchronization
|
|
4
|
+
- [x] Task: TDD - Тесты для улучшенной JS-инъекции (защита toString, WebGL2, Permissions API)
|
|
5
|
+
- [x] Написать unit-тесты для проверки `Function.prototype.toString` (`[native code]`)
|
|
6
|
+
- [x] Написать unit-тесты для одновременного патчинга WebGL1 и WebGL2
|
|
7
|
+
- [x] Написать unit-тесты эмуляции Permissions API и Notification
|
|
8
|
+
- [x] Task: Реализация улучшений JS-маскировки в `antidetect.py`
|
|
9
|
+
- [x] Реализовать функцию `makeNative` для маскировки строкового представления функций
|
|
10
|
+
- [x] Добавить обработку `WebGL2RenderingContext`
|
|
11
|
+
- [x] Добавить синхронизацию `navigator.permissions.query` и `Notification.permission`
|
|
12
|
+
- [x] Привести в соответствие дескрипторы свойств `navigator`
|
|
13
|
+
- [x] Task: Conductor - User Manual Verification 'Phase 1: JavaScript Anti-Tampering & Permissions Synchronization' (Protocol in workflow.md)
|
|
14
|
+
|
|
15
|
+
## Phase 2: nodriver Stealth Minimal Mode & Browser Flags
|
|
16
|
+
- [x] Task: TDD - Тесты для режима stealth_minimal и флагов запуска браузера
|
|
17
|
+
- [x] Добавить тесты для `apply_antidetect_nodriver` с параметром `stealth_minimal=True`
|
|
18
|
+
- [x] Протестировать обновленный список флагов запуска `get_browser_launch_args`
|
|
19
|
+
- [x] Task: Реализация `stealth_minimal` и обновление аргументов запуска
|
|
20
|
+
- [x] Добавить аргумент `stealth_minimal` в функцию `apply_antidetect_nodriver`
|
|
21
|
+
- [x] Исключить модификацию Canvas и WebGL при `stealth_minimal=True`
|
|
22
|
+
- [x] Обновить флаги в `get_browser_launch_args` (современный headless, подавление детекта автоматизации)
|
|
23
|
+
- [x] Task: Conductor - User Manual Verification 'Phase 2: nodriver Stealth Minimal Mode & Browser Flags' (Protocol in workflow.md)
|
|
24
|
+
|
|
25
|
+
## Phase 3: Humanized Hold Time in CDP Input Actions
|
|
26
|
+
- [x] Task: TDD - Тесты для микропауз удержания кнопок мыши и клавиш
|
|
27
|
+
- [x] Написать тесты для проверки пауз между mousePressed и mouseReleased в `async_click`
|
|
28
|
+
- [x] Написать тесты для проверки задержек удержания keyDown/keyUp в `async_type_text`
|
|
29
|
+
- [x] Task: Реализация микропауз удержания в `actions.py`
|
|
30
|
+
- [x] Добавить параметры `hold_time_min` и `hold_time_max` в `async_click` для CDP
|
|
31
|
+
- [x] Добавить эмуляцию задержки нажатия клавиш в `async_type_text` для nodriver
|
|
32
|
+
- [x] Task: Conductor - User Manual Verification 'Phase 3: Humanized Hold Time in CDP Input Actions' (Protocol in workflow.md)
|
|
33
|
+
|
|
34
|
+
## Phase 4: Documentation, AI Context Sync & Final Integration
|
|
35
|
+
- [x] Task: Обновление документации
|
|
36
|
+
- [x] Обновить `docs/scraping.md` с описанием новых параметров и возможностей антидетекта
|
|
37
|
+
- [x] Проверить соответствие Google docstrings в затронутых файлах
|
|
38
|
+
- [x] Task: Синхронизация AI-контекста и линтинг
|
|
39
|
+
- [x] Сгенерировать контекст через `uv run chutils dev generate-context`
|
|
40
|
+
- [x] Запустить `uv run chutils dev ai-lint` и `uv run pytest` для валидации всего набора тестов
|
|
41
|
+
- [x] Task: Conductor - User Manual Verification 'Phase 4: Documentation, AI Context Sync & Final Integration' (Protocol in workflow.md)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Specification: nodriver Anti-Detect & Stealth Enhancement (`chutils.scraping.humanize`)
|
|
2
|
+
|
|
3
|
+
## 1. Overview
|
|
4
|
+
Улучшение механизмов маскировки автоматизации и антидетекта для `nodriver` (а также `playwright` и `selenium`) в модуле `chutils.scraping.humanize`. Цель: устранение прямых признаков вмешательства (Tampering) в окружение JavaScript, поддержка WebGL2, нативная маскировка `Function.prototype.toString`, согласование дескрипторов свойств, реализация режима `stealth_minimal` и добавление физиологических микропауз удержания (Hold Time) для CDP-ввода.
|
|
5
|
+
|
|
6
|
+
## 2. Functional Requirements
|
|
7
|
+
1. **Качественная маскировка JavaScript (Anti-Tampering)**:
|
|
8
|
+
- Защита `Function.prototype.toString`: все подмененные встроенные функции должны возвращать `"function [name]() { [native code] }"`, а вызов `.toString()` на них самих — корректную нативную строку.
|
|
9
|
+
- Корректная эмуляция дескрипторов: `Object.getOwnPropertyDescriptor` на `navigator` и прототипах должен возвращать стандартные атрибуты без явных следов переопределения (`enumerable`, `configurable`, `writable`).
|
|
10
|
+
- Патчинг WebGL2: одновременная и согласованная подмена параметров вендора и рендерера в `WebGLRenderingContext` и `WebGL2RenderingContext`.
|
|
11
|
+
- Синхронизация Permissions API: приведение к консистентному состоянию `Notification.permission` и `navigator.permissions.query({name: 'notifications'})`.
|
|
12
|
+
2. **Режим `stealth_minimal` для nodriver**:
|
|
13
|
+
- Параметр `stealth_minimal: bool = False` в `apply_antidetect_nodriver()`.
|
|
14
|
+
- При активном флаге не вносить синтетический шум в Canvas (`getImageData`) и не переопределять WebGL-параметры, если используется полноценный установленный Google Chrome, чтобы не нарушать естественный отпечаток железа.
|
|
15
|
+
3. **Физиологические микропаузы (Hold Time)**:
|
|
16
|
+
- Добавить настраиваемый диапазон задержки удержания (Hold Time) для событий клика мыши (`mousePressed` -> `mouseReleased`) в `async_click` (по умолчанию 50–120 мс).
|
|
17
|
+
- Добавить задержку удержания между нажатием и отпусканием клавиш (`keyDown` -> `keyUp`) в `async_type_text` (по умолчанию 40–90 мс) при работе через CDP.
|
|
18
|
+
4. **Оптимизация флагов запуска**:
|
|
19
|
+
- Обновить `get_browser_launch_args()` для добавления флагов исключения предупреждений автоматизации и поддержки современного режима headless.
|
|
20
|
+
|
|
21
|
+
## 3. Non-Functional Requirements
|
|
22
|
+
- Строгая типизация Python 3.10+ (без устаревших `typing.Optional`, `typing.List` и без `Any` в сигнатурах публичного API).
|
|
23
|
+
- Обратная совместимость с существующими сигнатурами функций `apply_antidetect_*` и `async_click`/`async_type_text`.
|
|
24
|
+
- Высокое покрытие модульными тестами (>90%).
|
|
25
|
+
|
|
26
|
+
## 4. Acceptance Criteria
|
|
27
|
+
- [ ] Вызовы `.toString()` на подмененных функциях в JS-инъекциях возвращают `[native code]`.
|
|
28
|
+
- [ ] Параметры WebGL вендора и рендерера корректно подменяются как для WebGL 1, так и для WebGL 2.
|
|
29
|
+
- [ ] `apply_antidetect_nodriver(..., stealth_minimal=True)` не внедряет искажения Canvas и WebGL.
|
|
30
|
+
- [ ] Ввод текста и клики через CDP в `nodriver` содержат микропаузы удержания клавиш и кнопок мыши.
|
|
31
|
+
- [ ] Все существующие и новые unit-тесты успешно проходят через `uv run pytest`.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"track_id": "nodriver_launch_turnstile_fix_20260910",
|
|
3
|
+
"type": "feature",
|
|
4
|
+
"status": "completed",
|
|
5
|
+
"created_at": "2026-09-10T18:51:00Z",
|
|
6
|
+
"updated_at": "2026-09-10T19:04:00Z",
|
|
7
|
+
|
|
8
|
+
"description": "Исправление координат Turnstile, поддержка Shadow DOM и фабрика launch_nodriver с AntidetectConfig"
|
|
9
|
+
}
|