chutils 3.4.1__tar.gz → 3.4.2__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.4.1 → chutils-3.4.2}/PKG-INFO +1 -1
- {chutils-3.4.1 → chutils-3.4.2}/api_map.md +3 -3
- chutils-3.4.2/conductor/tracks/telegram_access_20260729/index.md +5 -0
- chutils-3.4.2/conductor/tracks/telegram_access_20260729/metadata.json +8 -0
- chutils-3.4.2/conductor/tracks/telegram_access_20260729/plan.md +18 -0
- chutils-3.4.2/conductor/tracks/telegram_access_20260729/spec.md +24 -0
- chutils-3.4.2/conductor/tracks/telegram_formatting_20260729/index.md +5 -0
- chutils-3.4.2/conductor/tracks/telegram_formatting_20260729/metadata.json +8 -0
- chutils-3.4.2/conductor/tracks/telegram_formatting_20260729/plan.md +17 -0
- chutils-3.4.2/conductor/tracks/telegram_formatting_20260729/spec.md +14 -0
- chutils-3.4.2/conductor/tracks/telegram_keyboard_20260729/index.md +5 -0
- chutils-3.4.2/conductor/tracks/telegram_keyboard_20260729/metadata.json +8 -0
- chutils-3.4.2/conductor/tracks/telegram_keyboard_20260729/plan.md +18 -0
- chutils-3.4.2/conductor/tracks/telegram_keyboard_20260729/spec.md +15 -0
- chutils-3.4.2/conductor/tracks/telegram_logging_20260729/index.md +5 -0
- chutils-3.4.2/conductor/tracks/telegram_logging_20260729/metadata.json +8 -0
- chutils-3.4.2/conductor/tracks/telegram_logging_20260729/plan.md +17 -0
- chutils-3.4.2/conductor/tracks/telegram_logging_20260729/spec.md +16 -0
- chutils-3.4.2/conductor/tracks/telegram_media_20260729/index.md +5 -0
- chutils-3.4.2/conductor/tracks/telegram_media_20260729/metadata.json +8 -0
- chutils-3.4.2/conductor/tracks/telegram_media_20260729/plan.md +18 -0
- chutils-3.4.2/conductor/tracks/telegram_media_20260729/spec.md +15 -0
- chutils-3.4.2/conductor/tracks/telegram_notifier_20260729/index.md +5 -0
- chutils-3.4.2/conductor/tracks/telegram_notifier_20260729/metadata.json +8 -0
- chutils-3.4.2/conductor/tracks/telegram_notifier_20260729/plan.md +17 -0
- chutils-3.4.2/conductor/tracks/telegram_notifier_20260729/spec.md +18 -0
- chutils-3.4.2/conductor/tracks/telegram_ratelimit_20260729/index.md +5 -0
- chutils-3.4.2/conductor/tracks/telegram_ratelimit_20260729/metadata.json +8 -0
- chutils-3.4.2/conductor/tracks/telegram_ratelimit_20260729/plan.md +19 -0
- chutils-3.4.2/conductor/tracks/telegram_ratelimit_20260729/spec.md +21 -0
- chutils-3.4.2/conductor/tracks/telegram_send_file_20260729/index.md +5 -0
- chutils-3.4.2/conductor/tracks/telegram_send_file_20260729/metadata.json +8 -0
- chutils-3.4.2/conductor/tracks/telegram_send_file_20260729/plan.md +18 -0
- chutils-3.4.2/conductor/tracks/telegram_send_file_20260729/spec.md +14 -0
- chutils-3.4.2/conductor/tracks/telegram_whitelist_20260729/index.md +5 -0
- chutils-3.4.2/conductor/tracks/telegram_whitelist_20260729/metadata.json +8 -0
- chutils-3.4.2/conductor/tracks/telegram_whitelist_20260729/plan.md +17 -0
- chutils-3.4.2/conductor/tracks/telegram_whitelist_20260729/spec.md +19 -0
- chutils-3.4.2/conductor/tracks.md +91 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/INTEGRATION_AI.md +25 -2
- {chutils-3.4.1 → chutils-3.4.2}/docs/ai_lint.md +24 -5
- chutils-3.4.2/docs/cli/check.md +97 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/cli/dev.md +138 -17
- chutils-3.4.2/docs/cli/validate.md +130 -0
- {chutils-3.4.1 → chutils-3.4.2}/project_index.json +172 -48
- {chutils-3.4.1 → chutils-3.4.2}/pyproject.toml +1 -1
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/__init__.py +8 -1
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/cli.py +4 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/__init__.py +2 -0
- chutils-3.4.2/src/chutils/commands/check.py +238 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/dev/diagnostics.py +6 -2
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/dev/generate_context.py +30 -5
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/utils.py +19 -2
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/validate.py +17 -4
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/ai_lint.py +4 -7
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/ast_indexer.py +18 -4
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/changelog_parser.py +3 -3
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/project_metadata.py +7 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/rules/dependency_sync.py +5 -13
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/upgrade_client.py +33 -4
- chutils-3.4.2/tests/unit/cli/test_cli_check.py +60 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/test_cli_utils_internal.py +15 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/dev/test_changelog_parser.py +8 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/dev/test_upgrade_client.py +21 -2
- {chutils-3.4.1 → chutils-3.4.2}/uv.lock +251 -125
- chutils-3.4.1/conductor/tracks.md +0 -37
- chutils-3.4.1/docs/cli/validate.md +0 -78
- {chutils-3.4.1 → chutils-3.4.2}/.chutilsignore +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/.gitattributes +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/.github/workflows/ci.yml +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/.github/workflows/publish-docs.yml +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/.gitignore +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/CODE_OF_CONDUCT.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/CONTRIBUTING.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/GEMINI.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/LICENSE +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/README.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/ai-lint.toml +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/benchmarks/cold_start.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/.gitignore +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/GEMINI.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/code_styleguides/python.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/index.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/product-guidelines.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/product.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/setup_state.json +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/tech-stack.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/tracks/ai_context_opt_20260728/index.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/tracks/ai_context_opt_20260728/metadata.json +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/tracks/ai_context_opt_20260728/plan.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/tracks/ai_context_opt_20260728/spec.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/tracks/async_lifecycle_20260728/index.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/tracks/async_lifecycle_20260728/metadata.json +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/tracks/async_lifecycle_20260728/plan.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/tracks/async_lifecycle_20260728/spec.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/tracks/browser_profiles_20260728/index.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/tracks/browser_profiles_20260728/metadata.json +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/tracks/browser_profiles_20260728/plan.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/tracks/browser_profiles_20260728/spec.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/tracks/queue_monitoring_20260728/index.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/tracks/queue_monitoring_20260728/metadata.json +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/tracks/queue_monitoring_20260728/plan.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/tracks/queue_monitoring_20260728/spec.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/tracks/stream_crypto_20260728/index.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/tracks/stream_crypto_20260728/metadata.json +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/tracks/stream_crypto_20260728/plan.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/tracks/stream_crypto_20260728/spec.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/conductor/workflow.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/CODE_OF_CONDUCT_RU.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/CONTRIBUTING_RU.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/README_RU.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/ai_examples/README.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/ai_examples/configuration/README.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/ai_examples/configuration/bad_pattern.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/ai_examples/configuration/good_pattern.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/ai_examples/error_handling/README.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/ai_examples/error_handling/bad_pattern.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/ai_examples/error_handling/good_pattern.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/ai_examples/logging/README.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/ai_examples/logging/bad_pattern.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/ai_examples/logging/good_pattern.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/ai_examples/optional_deps/README.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/ai_examples/optional_deps/bad_pattern.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/ai_examples/optional_deps/good_pattern.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/ai_examples/secrets/README.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/ai_examples/secrets/bad_pattern.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/ai_examples/secrets/good_pattern.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/ai_hints.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/api.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/audit.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/captcha.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/cli/config.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/cli/db.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/cli/env.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/cli/index.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/cli/init.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/cli/pypi.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/cli/secrets.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/cli/show_paths.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/cli/template.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/custom_config_providers.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/dependencies.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/http.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/index.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/migration.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/plugins.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/qt.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/recipes.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/scraping.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/store.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/testing.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/docs/web.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/.env +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/01_configuration.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/02_logging.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/03_secrets.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/04_full_example.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/05_different_log_levels.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/06_local_config_override.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/07_decorators_example.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/08_multiple_loggers_example.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/09_disable_keyring.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/10_universal_env_override.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/11_retry_decorator.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/12_secret_masking.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/13_pydantic_validation.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/15_context_logging.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/16_cloud_secret_managers.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/17_timeout_decorator.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/18_config_hot_reload.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/19_remote_config.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/20_opentelemetry_tracing.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/21_config_diagnostics.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/22_circuit_breaker_decorator.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/22_qt_logging.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/22_safe_path_resolution.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/23_event_bus.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/23_qt_async.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/24_qt_typed_signals.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/24_task_scheduler.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/25_testing_fixtures_example.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/26_metrics_prometheus.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/27_rate_limiting.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/28_dependency_injection.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/captcha_solvers_usage.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/concurrency_scraping_usage.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/config.yml +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/scraping_humanize_usage.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/examples/web_client_usage.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/mkdocs.yml +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/__init__.pyi +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/__main__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/antigravity.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/audit/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/audit/_hash.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/audit/api.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/audit/backends/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/audit/backends/base.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/audit/backends/file.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/audit/backends/postgres.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/audit/backends/sqlite.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/audit/schema.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/cache/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/cache/base.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/cache/decorator.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/cache/in_memory.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/cache/utils.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/cli_booster.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/cli_utils.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/base.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/config.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/db.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/dev/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/dev/ai_lint.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/dev/base.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/dev/chat_context.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/dev/clean.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/dev/dashboard.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/dev/few_shot.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/dev/hooks.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/dev/mock.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/dev/profile_imports.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/dev/scaffold.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/dev/setup_github_actions.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/dev/sync_env.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/dev/watch.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/env.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/init.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/paths.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/pypi.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/secrets.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/commands/template.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/config/GEMINI.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/config/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/config/ast_fallback_parser.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/config/core.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/config/custom_providers.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/config/dev.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/config/diagnostics.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/config/generator.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/config/getters.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/config/integrations.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/config/manager.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/config/providers.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/config/schema.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/config/sse.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/config/utils.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/config/watcher.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/config/webhook_server.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/context.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/crypto.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/db.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/decorators.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/chat_context.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/cleaner.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/constants.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/dashboard/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/dashboard/indexer.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/dashboard/input.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/dashboard/tui.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/env_parser.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/env_sync.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/few_shot/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/few_shot/detector.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/few_shot/models.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/few_shot/renderer.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/few_shot/writer.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/github_actions.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/mock_server.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/models/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/models/base.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/models/index.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/models/node.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/models/symbol.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/profile_imports.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/rules/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/rules/api_map.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/rules/decomposition.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/rules/docstring.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/rules/env.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/rules/integration.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/rules/linter_coverage.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/rules/manifest.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/rules/security.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/rules/upgrade_check.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/runners.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/scaffold.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/version_detector.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/dev/watcher.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/di/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/di/__init__.pyi +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/di/container.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/diagnostics/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/diagnostics/manager.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/diagnostics/models.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/diagnostics/web.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/env.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/env.pyi +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/events/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/events/core.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/exceptions/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/exceptions/audit.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/exceptions/base.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/exceptions/cache.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/exceptions/config.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/exceptions/di.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/exceptions/events.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/exceptions/logger.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/exceptions/resilience.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/exceptions/secrets.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/exceptions/system.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/exceptions/validation.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/exceptions/watcher.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/features.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/fs.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/http/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/http/api.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/http/client.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/http/fallback.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/http/resilience.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/http/streaming.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/http/tracing.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/lifecycle.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/logger/GEMINI.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/logger/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/logger/core.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/logger/formatters.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/logger/handlers.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/logger/internal/builder.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/logger/internal/levels.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/logger/internal/utils.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/logger/masking.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/metrics/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/metrics/base.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/metrics/in_memory.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/metrics/prometheus.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/metrics/timer.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/plugins/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/plugins/core.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/plugins/interfaces.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/qt/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/qt/asyncio.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/qt/logging.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/qt/shim.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/qt/signals.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/qt/widgets.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/scraping/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/scraping/captcha/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/scraping/captcha/anticaptcha.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/scraping/captcha/base.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/scraping/captcha/capmonster.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/scraping/captcha/exceptions.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/scraping/captcha/rucaptcha.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/scraping/concurrency/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/scraping/concurrency/base.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/scraping/concurrency/limiter.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/scraping/concurrency/models.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/scraping/concurrency/pool.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/scraping/concurrency/queues.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/scraping/humanize/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/scraping/humanize/actions.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/scraping/humanize/antidetect.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/scraping/humanize/math_utils.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/scraping/humanize/warmer.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/secret_manager/GEMINI.md +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/secret_manager/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/secret_manager/core.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/secret_manager/providers/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/secret_manager/providers/aws.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/secret_manager/providers/base.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/secret_manager/providers/dotenv.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/secret_manager/providers/env.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/secret_manager/providers/gcp.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/secret_manager/providers/keyring_provider.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/store/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/store/backends/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/store/backends/base.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/store/backends/memcached.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/store/backends/memory.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/store/backends/redis.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/store/decorator.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/store/manager.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/tasks/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/tasks/__init__.pyi +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/tasks/core.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/testing/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/testing/fixtures.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/text.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/time.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/tracing.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/typing.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/validation.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/validation.pyi +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/web/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/web/client.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/web/proxy_pool.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/src/chutils/web/user_agent.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/conftest.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/integration/__init__.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/integration/test_ai_lint_integration.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/integration/test_cli_e2e.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/integration/test_db_migrations.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/integration/test_event_loops.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/integration/test_examples.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/integration/test_hooks_integration.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/integration/test_masking_integration.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/integration/test_otel_tracing.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/integration/test_remote_config_integration.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/integration/test_setup_github_actions_integration.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/manual/manual_test_cli_booster.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/conftest.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/test_cli.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/test_cli_booster.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/test_cli_config.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/test_cli_config_cmd.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/test_cli_config_schema.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/test_cli_dev.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/test_cli_dev_cmd.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/test_cli_dev_tree.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/test_cli_dev_watch.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/test_cli_diagnostics.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/test_cli_extras_suggestion.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/test_cli_init.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/test_cli_init_interactive.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/test_cli_paths.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/test_cli_pypi.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/test_cli_rich.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/test_cli_rich_width.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/test_cli_secrets.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/test_cli_setup_github_actions.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/test_cli_template.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/cli/test_cli_validate.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_config.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_config_ast_parser.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_config_dev.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_config_diagnostics.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_config_env.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_config_env_loading.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_config_generator.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_config_integrations.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_config_json.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_config_pydantic.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_config_required.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_config_schema.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_config_sse.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_config_sse_integration.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_config_tracing.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_config_universal_env.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_config_utils.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_config_validation_group.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_config_watcher.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_config_webhook.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_custom_config_providers.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_priority_unification.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/config/test_remote_config.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/core/test_ast_indexer.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/core/test_ast_indexer_abstract.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/core/test_ast_indexer_graph.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/core/test_ast_indexer_layers.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/core/test_ast_indexer_metadata.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/core/test_cache.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/core/test_dev_models.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/core/test_exceptions.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/core/test_features.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/core/test_fs.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/core/test_lifecycle.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/core/test_thread_safety.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/core/test_time.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/decorators/test_decorator_circuit_breaker.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/decorators/test_decorator_retry.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/decorators/test_decorator_timeout.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/decorators/test_decorators.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/decorators/test_rate_limit.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/dev/test_ai_lint.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/dev/test_ai_lint_staged.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/dev/test_chat_context.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/dev/test_cleaner.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/dev/test_env_parser.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/dev/test_env_sync.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/dev/test_generate_few_shot.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/dev/test_linter_coverage_rule.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/dev/test_mock_server.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/dev/test_runners.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/dev/test_scaffold.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/dev/test_setup_github_actions.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/dev/test_upgrade_check_rule.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/dev/test_version_detector.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/dev/test_watcher.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/di/test_di.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/events/test_event_bus.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/logger/conftest.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/logger/test_basics.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/logger/test_compression.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/logger/test_config_sections.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/logger/test_configuration.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/logger/test_context.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/logger/test_env_control.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/logger/test_files.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/logger/test_json_format.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/logger/test_logger_rich_width.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/logger/test_masking.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/logger/test_performance_security.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/logger/test_rich.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/logger/test_rotation.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/metrics/test_metrics.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/plugins/test_integration.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/plugins/test_interfaces.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/plugins/test_plugins.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/secret_manager/test_secret_manager.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/secret_manager/test_secret_manager_env.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/secret_manager/test_secret_manager_providers.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/secret_manager/test_secrets_required.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/tasks/test_scheduler.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_ai_lint_ignore.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_anticaptcha.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_antidetect.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_async_web_client.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_audit.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_audit_phase2.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_capmonster.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_captcha_base.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_captcha_imports.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_cli_db.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_concurrency_imports.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_concurrency_limiter.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_concurrency_pool.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_concurrency_queues.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_config_alias_choices.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_config_fallback.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_crypto.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_crypto_dependencies.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_dashboard.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_db_init.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_db_operations.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_decorators_bulkhead.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_diagnostics.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_env.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_events_exception_group.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_http_api.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_http_client.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_http_fallback.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_http_resilience.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_http_streaming.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_http_tracing.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_humanize_math.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_install_hooks.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_minimal_imports.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_nodriver_humanize.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_playwright_humanize.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_profile_imports.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_profile_warmer.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_proxy_pool.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_qt_asyncio.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_qt_logging.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_qt_shim.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_qt_signals.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_qt_widgets.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_rucaptcha.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_scraping_imports.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_selenium_humanize.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_store_backends_external.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_store_integrations.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_store_manager.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_store_memory.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_text.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_text_dependencies.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_user_agent.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_validation.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_web_client.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/tests/unit/test_web_imports.py +0 -0
- {chutils-3.4.1 → chutils-3.4.2}/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.
|
|
3
|
+
Version: 3.4.2
|
|
4
4
|
Summary: Набор простых и удобных утилит для Python, который избавляет от рутины при работе с конфигурацией и логированием в новых проектах.
|
|
5
5
|
Author-email: Chu4hel <sergeiivanov636@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
chutils_version: 3.4.1
|
|
3
3
|
project_version: 3.4.1
|
|
4
|
-
git_commit:
|
|
5
|
-
generated_at: 2026-07-
|
|
6
|
-
project_hash:
|
|
4
|
+
git_commit: 35b0abb02583ebebbd7a918dd74a5056d6b40c5c (dirty)
|
|
5
|
+
generated_at: 2026-07-30T21:04:30.356972+00:00
|
|
6
|
+
project_hash: 73c182750cd7e4d409a97fe4e3797cb39064637a44fe36638c5c113466639683
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Public API Map: chutils
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"track_id": "telegram_access_20260729",
|
|
3
|
+
"type": "feature",
|
|
4
|
+
"status": "new",
|
|
5
|
+
"created_at": "2026-07-29T00:04:00Z",
|
|
6
|
+
"updated_at": "2026-07-29T00:04:00Z",
|
|
7
|
+
"description": "Безопасность и ограничение доступа для Telegram ботов: @admin_only, AdminFilter с fallback-ом на chutils config"
|
|
8
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Implementation Plan: Telegram Bot Access Control (`telegram_access_20260729`)
|
|
2
|
+
|
|
3
|
+
## Phase 1: Core Access Control Logic & Exception Hierarchy
|
|
4
|
+
- [ ] Task: Create `chutils.exceptions.telegram` module with `TelegramAccessDeniedError`
|
|
5
|
+
- [ ] Task: Create core `chutils.telegram.access` module with `is_admin()` predicate logic and config fallback
|
|
6
|
+
- [ ] Task: Implement `@admin_only` decorator for sync/async handler functions with refusal handling options (`refusal_text`, `silent`, raise exception)
|
|
7
|
+
- [ ] Task: Unit tests for core `is_admin` and `@admin_only` decorator
|
|
8
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 1: Core Access Control' (Protocol in workflow.md)
|
|
9
|
+
|
|
10
|
+
## Phase 2: Framework Integrations & Lazy Exports
|
|
11
|
+
- [ ] Task: Implement `AdminFilter` for `aiogram 3.x` with safe import handling if `aiogram` is not installed
|
|
12
|
+
- [ ] Task: Register lazy exports in `src/chutils/telegram/__init__.py` and root `src/chutils/__init__.py`
|
|
13
|
+
- [ ] Task: Unit tests for `aiogram` filter and framework compatibility
|
|
14
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 2: Framework Integrations' (Protocol in workflow.md)
|
|
15
|
+
|
|
16
|
+
## Phase 3: Documentation & Indexing
|
|
17
|
+
- [ ] Task: Document `chutils.telegram` usage in `docs/` and update `api_map.md` / `project_index.json`
|
|
18
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 3: Documentation' (Protocol in workflow.md)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Track Specification: Telegram Bot Access Control (`telegram_access_20260729`)
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Добавление модуля `chutils.telegram` с универсальным механизмом проверки прав доступа и ограничения вызовов для Telegram-ботов (`@admin_only`, `AdminFilter`). Подсистема решает задачу безопасного разграничения доступа админов/пользователей с автоматическим фоллбэком на конфигурацию `chutils` и поддержкой популярнейших фреймворков (`aiogram 3.x`, `python-telegram-bot`, `telebot`).
|
|
5
|
+
|
|
6
|
+
## Functional Requirements
|
|
7
|
+
- **Декоратор `@admin_only`**:
|
|
8
|
+
- Поддержка синхронных и асинхронных функций-хэндлеров.
|
|
9
|
+
- Поддержка явного списка `admin_ids` (int) и `admin_usernames` (str без/с `@`).
|
|
10
|
+
- Поддержка кастомной функции-предиката `is_admin_func(user_id, username) -> bool`.
|
|
11
|
+
- Автоматический fallback на конфигурацию `chutils`: чтение списка админов из `get_config_value("Telegram", "admin_ids")` / `admin_usernames` при отсутствии явных аргументов.
|
|
12
|
+
- **Отказ в доступе (Refusal Handling)**:
|
|
13
|
+
- Настройка кастомного ответа (`refusal_text="⛔ Доступ запрещен"`).
|
|
14
|
+
- Поддержка тихого режима (`silent=True`), когда неавторизованные запросы игнорируются без ответа.
|
|
15
|
+
- Поддержка выброса исключения `TelegramAccessDeniedError` для тонкой обработки в Middleware.
|
|
16
|
+
- **Интеграция с Telegram-фреймворками**:
|
|
17
|
+
- `AdminFilter` для `aiogram 3.x` (реализация `BaseFilter`).
|
|
18
|
+
- Универсальная функция-предикат `is_admin(user_id, username, ...)` для использования в `python-telegram-bot`, `telebot` и чистых Webhook/Polling обновлениях.
|
|
19
|
+
- **Типизация и Zero-Any**:
|
|
20
|
+
- Полная типизация через Python 3.10+ unions (`int | str`), отсутствие `Any` в бизнес-логике.
|
|
21
|
+
|
|
22
|
+
## Out of Scope
|
|
23
|
+
- Хранение прав пользователей в БД (управление ролями).
|
|
24
|
+
- Пагинаторы и UI-клавиатуры (будут вынесены в отдельные треки).
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"track_id": "telegram_formatting_20260729",
|
|
3
|
+
"type": "feature",
|
|
4
|
+
"status": "new",
|
|
5
|
+
"created_at": "2026-07-29T00:11:00Z",
|
|
6
|
+
"updated_at": "2026-07-29T00:11:00Z",
|
|
7
|
+
"description": "chutils.telegram.formatting: Экранирование MarkdownV2/HTML (escape_markdown, escape_html) и умное разбиение сообщений (smart_truncate)"
|
|
8
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Implementation Plan: Telegram Safe Formatting & Message Truncation (`telegram_formatting_20260729`)
|
|
2
|
+
|
|
3
|
+
## Phase 1: Core Escaping Functions & Unit Tests
|
|
4
|
+
- [ ] Task: Create `chutils.telegram.formatting` module with `escape_markdown` and `escape_html`
|
|
5
|
+
- [ ] Task: Write comprehensive unit tests for `escape_markdown` (v1/v2) and `escape_html`
|
|
6
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 1: Escaping Functions' (Protocol in workflow.md)
|
|
7
|
+
|
|
8
|
+
## Phase 2: Smart Truncation & Message Splitting
|
|
9
|
+
- [ ] Task: Implement `smart_truncate` with code block (```) and HTML tag closure
|
|
10
|
+
- [ ] Task: Implement `split_message` helper for splitting logs/long reports
|
|
11
|
+
- [ ] Task: Export functions in `src/chutils/telegram/__init__.py` and root `src/chutils/__init__.py`
|
|
12
|
+
- [ ] Task: Unit tests for `smart_truncate` and `split_message`
|
|
13
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 2: Smart Truncation & Splitting' (Protocol in workflow.md)
|
|
14
|
+
|
|
15
|
+
## Phase 3: Documentation & Indexing
|
|
16
|
+
- [ ] Task: Add examples in `docs/` and update `api_map.md` / `project_index.json`
|
|
17
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 3: Documentation' (Protocol in workflow.md)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Track Specification: Telegram Safe Formatting & Message Truncation (`telegram_formatting_20260729`)
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Реализация модуля `chutils.telegram.formatting` для безопасной работы с разметкой сообщений Telegram. Модуль гарантирует защиту от ошибок `BadRequest: Can't parse entities` за счет надежного экранирования `MarkdownV2` / `HTML` и предотвращает вылеты по превышению 4096 символов благодаря умному сплиттингу сообщений с сохранением парности тегов и кодовых блоков.
|
|
5
|
+
|
|
6
|
+
## Functional Requirements
|
|
7
|
+
- **Экранирование символов (`escape_markdown` / `escape_html`)**:
|
|
8
|
+
- `escape_markdown(text, version=2)`: Экранирование спецсимволов (`_`, `*`, `[`, `]`, `(`, `)`, `~`, `` ` ``, `>`, `#`, `+`, `-`, `=`, `|`, `{`, `}`, `.`, `!`). Поддержка v1 и v2.
|
|
9
|
+
- `escape_html(text)`: Экранирование `<`, `>`, `&`, `"`.
|
|
10
|
+
- **Умное разбиение сообщений (`smart_truncate` & `split_message`)**:
|
|
11
|
+
- `smart_truncate(text, max_length=4096)`: Обрезка текста до `max_length` с автоматическим закрытием незавершенных кодовых блоков (```) или HTML-тегов.
|
|
12
|
+
- `split_message(text, max_length=4096)`: Разбиение длинного текста/логов на список валидных чанков не превышающих `max_length` символов.
|
|
13
|
+
- **Типизация**:
|
|
14
|
+
- Строгие аннотации типов Python 3.10+.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"track_id": "telegram_keyboard_20260729",
|
|
3
|
+
"type": "feature",
|
|
4
|
+
"status": "new",
|
|
5
|
+
"created_at": "2026-07-29T20:20:00Z",
|
|
6
|
+
"updated_at": "2026-07-29T20:20:00Z",
|
|
7
|
+
"description": "chutils.telegram.keyboard: build_inline_keyboard генератор сетки и PaginatorKeyboard для пагинации списков"
|
|
8
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Implementation Plan: Telegram Dynamic & Paginated Keyboards (`telegram_keyboard_20260729`)
|
|
2
|
+
|
|
3
|
+
## Phase 1: Core Inline Keyboard Generator
|
|
4
|
+
- [ ] Task: Create `chutils.telegram.keyboard` module with `build_inline_keyboard` function
|
|
5
|
+
- [ ] Task: Support grid alignment (`buttons_per_row`), custom URLs, and dict/tuple inputs
|
|
6
|
+
- [ ] Task: Unit tests for `build_inline_keyboard` logic
|
|
7
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 1: Core Inline Keyboard' (Protocol in workflow.md)
|
|
8
|
+
|
|
9
|
+
## Phase 2: PaginatorKeyboard & Framework Integrations
|
|
10
|
+
- [ ] Task: Implement `PaginatorKeyboard` class with page slicing, state labels, and navigation buttons
|
|
11
|
+
- [ ] Task: Support `footer_buttons` and `aiogram` `InlineKeyboardMarkup` conversion
|
|
12
|
+
- [ ] Task: Export symbols in `src/chutils/telegram/__init__.py` and root `src/chutils/__init__.py`
|
|
13
|
+
- [ ] Task: Unit tests for `PaginatorKeyboard` pagination and navigation
|
|
14
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 2: PaginatorKeyboard & Integration' (Protocol in workflow.md)
|
|
15
|
+
|
|
16
|
+
## Phase 3: Documentation & Indexing
|
|
17
|
+
- [ ] Task: Add examples in `docs/` and update `api_map.md` / `project_index.json`
|
|
18
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 3: Documentation' (Protocol in workflow.md)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Track Specification: Telegram Dynamic & Paginated Keyboards (`telegram_keyboard_20260729`)
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Реализация модуля `chutils.telegram.keyboard` для конструирования динамических Inline-клавиатур и управления пагинацией списков. Подсистема исключает рутинное написание сетки кнопок, автоматизирует навигацию (`« Назад`, `1/5`, `Вперед »`) и поддерживает экспорт в формате чистых Python-словарей или готовых `InlineKeyboardMarkup` для `aiogram 3.x`.
|
|
5
|
+
|
|
6
|
+
## Functional Requirements
|
|
7
|
+
- **Генератор сетки `build_inline_keyboard`**:
|
|
8
|
+
- Принимает список элементов `(text, callback_data)` или словарей `{"text": ..., "callback_data": ..., "url": ...}`.
|
|
9
|
+
- Автоматическое разбиение на ряды с помощью параметра `buttons_per_row` (по умолчанию 2).
|
|
10
|
+
- Опция `as_aiogram` для приведения к объекту `InlineKeyboardMarkup` при наличии `aiogram`.
|
|
11
|
+
- **Пагинатор `PaginatorKeyboard`**:
|
|
12
|
+
- Универсальный класс пагинации для списков любых объектов.
|
|
13
|
+
- Генерация строки состояния (например, `1/5`) и навигационных кнопок (`«`, `»`).
|
|
14
|
+
- Метод `get_page(page: int, per_page: int)` для сбора подмножества данных.
|
|
15
|
+
- Поддержка прикрепления дополнительных фиктивных или постоянных кнопок (`footer_buttons`, например "Закрыть").
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"track_id": "telegram_logging_20260729",
|
|
3
|
+
"type": "feature",
|
|
4
|
+
"status": "new",
|
|
5
|
+
"created_at": "2026-07-29T00:09:00Z",
|
|
6
|
+
"updated_at": "2026-07-29T00:09:00Z",
|
|
7
|
+
"description": "TelegramLogFilter / TelegramMiddleware: Автоматическое логирование команд, нажатий inline-кнопок и авто-проброс контекста в chutils.logger"
|
|
8
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Implementation Plan: Telegram Update Logging & Context Tracing (`telegram_logging_20260729`)
|
|
2
|
+
|
|
3
|
+
## Phase 1: Core Context Tracing Engine & Decorator
|
|
4
|
+
- [ ] Task: Create `chutils.telegram.logging` module with context binding logic (`telegram_user_id`, `chat_id`, `update_id`)
|
|
5
|
+
- [ ] Task: Implement `trace_telegram_update` sync/async context manager and decorator with `execution_time_ms` calculation and PII masking
|
|
6
|
+
- [ ] Task: Unit tests for core `trace_telegram_update` and logger context binding
|
|
7
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 1: Core Context Tracing Engine' (Protocol in workflow.md)
|
|
8
|
+
|
|
9
|
+
## Phase 2: aiogram Middleware & Lazy Exports
|
|
10
|
+
- [ ] Task: Implement `TelegramLoggingMiddleware` for `aiogram 3.x`
|
|
11
|
+
- [ ] Task: Register lazy exports in `src/chutils/telegram/__init__.py` and root `src/chutils/__init__.py`
|
|
12
|
+
- [ ] Task: Unit tests for `aiogram` logging middleware
|
|
13
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 2: aiogram Middleware' (Protocol in workflow.md)
|
|
14
|
+
|
|
15
|
+
## Phase 3: Documentation & Indexing
|
|
16
|
+
- [ ] Task: Add examples in `docs/` and update `api_map.md` / `project_index.json`
|
|
17
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 3: Documentation' (Protocol in workflow.md)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Track Specification: Telegram Update Logging & Context Tracing (`telegram_logging_20260729`)
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Добавление подсистемы прозрачного логирования и контекстного трейсинга Telegram-апдейтов в `chutils.telegram.logging`. Модуль автоматически обогащает все логи, вызывемые внутри хэндлеров, контекстными полями `telegram_user_id` и `chat_id`, измеряет время выполнения (`execution_time_ms`), маскирует PII-данные и предоставляет удобную мидлварь для `aiogram 3.x`.
|
|
5
|
+
|
|
6
|
+
## Functional Requirements
|
|
7
|
+
- **Авто-проброс контекста (`chutils.logger.bind_context`)**:
|
|
8
|
+
- При получении любого апдейта автоматически устанавливается локальный контекст потока/таски (`telegram_user_id`, `chat_id`, `update_id`).
|
|
9
|
+
- Гарантированный сброс контекста (cleanup) после завершения работы хэндлера.
|
|
10
|
+
- **Метрики и структура логов**:
|
|
11
|
+
- Логирование успешных команд, нажатий inline-кнопок и необработанных исключений.
|
|
12
|
+
- Измерение точности выполнения в миллисекундах (`execution_time_ms`).
|
|
13
|
+
- Маскирование PII через `chutils.logger.masking`.
|
|
14
|
+
- **Интеграции с фреймворками**:
|
|
15
|
+
- `TelegramLoggingMiddleware` для `aiogram 3.x` (Outer / Inner Middleware).
|
|
16
|
+
- Декоратор и асинхронный контекстный менеджер `trace_telegram_update` для `python-telegram-bot`, `telebot` и пользовательских скриптов.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"track_id": "telegram_media_20260729",
|
|
3
|
+
"type": "feature",
|
|
4
|
+
"status": "new",
|
|
5
|
+
"created_at": "2026-07-29T20:23:00Z",
|
|
6
|
+
"updated_at": "2026-07-29T20:23:00Z",
|
|
7
|
+
"description": "chutils.telegram.media: download_user_file с автоматической проверкой resolve_safe_path и опцией отключения allow_unsafe_path"
|
|
8
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Implementation Plan: Telegram Safe File Downloader (`telegram_media_20260729`)
|
|
2
|
+
|
|
3
|
+
## Phase 1: Core File Download Logic & Path Safety
|
|
4
|
+
- [ ] Task: Create `chutils.telegram.media` module with `download_user_file` function
|
|
5
|
+
- [ ] Task: Integrate `chutils.fs.resolve_safe_path` and `safe_filename` with `allow_unsafe_path=False` toggle
|
|
6
|
+
- [ ] Task: Implement file size validation (`max_size_bytes`) and HTTP/Bot API stream saving
|
|
7
|
+
- [ ] Task: Unit tests for path traversal attacks, `allow_unsafe_path` override, and file size limits
|
|
8
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 1: Core File Downloader' (Protocol in workflow.md)
|
|
9
|
+
|
|
10
|
+
## Phase 2: Framework Integrations & Lazy Exports
|
|
11
|
+
- [ ] Task: Support `aiogram 3.x` `Bot` instance and raw `bot_token` HTTP download fallback
|
|
12
|
+
- [ ] Task: Export symbols in `src/chutils/telegram/__init__.py` and root `src/chutils/__init__.py`
|
|
13
|
+
- [ ] Task: Unit tests for framework compatibility and download fallbacks
|
|
14
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 2: Framework Support' (Protocol in workflow.md)
|
|
15
|
+
|
|
16
|
+
## Phase 3: Documentation & Indexing
|
|
17
|
+
- [ ] Task: Add examples in `docs/` and update `api_map.md` / `project_index.json`
|
|
18
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 3: Documentation' (Protocol in workflow.md)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Track Specification: Telegram Safe File Downloader (`telegram_media_20260729`)
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Реализация модуля `chutils.telegram.media` для безопасного выкачивания файлов пользователей из Telegram (`download_user_file`). Модуль решает проблему уязвимости Path Traversal при передаче имени файла пользователем через механизмы `chutils.fs.resolve_safe_path` и `safe_filename`, с опциональной возможностью отключения защиты разработчиком (`allow_unsafe_path=True`).
|
|
5
|
+
|
|
6
|
+
## Functional Requirements
|
|
7
|
+
- **Функция `download_user_file`**:
|
|
8
|
+
- Принимает `bot` (aiogram/python-telegram-bot или bot_token), `file_id`, `target_dir` и `custom_filename` (опционально).
|
|
9
|
+
- Интеграция с `chutils.fs.resolve_safe_path`: гарантирует, что итоговый файл сохраняется строго в пределах `target_dir`.
|
|
10
|
+
- Защита от Path Traversal: санитизация имени файла (удаление `../`, `..\`, замена через `safe_filename`).
|
|
11
|
+
- Опция отключения: параметр `allow_unsafe_path: bool = False`, позволяющий разработчику при необходимости отключить проверку с записью предупреждения в лог (`logger.warning`).
|
|
12
|
+
- Контроль размера файла: `max_size_bytes: int | None` с выбросом `ChutilsException` при превышении.
|
|
13
|
+
- **Типизация и исключения**:
|
|
14
|
+
- Поддержка `async def` и `def` вызова.
|
|
15
|
+
- Понятные ошибки при недоступности файла или нарушении безопасности.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"track_id": "telegram_notifier_20260729",
|
|
3
|
+
"type": "feature",
|
|
4
|
+
"status": "new",
|
|
5
|
+
"created_at": "2026-07-29T00:13:00Z",
|
|
6
|
+
"updated_at": "2026-07-29T00:13:00Z",
|
|
7
|
+
"description": "chutils.telegram.notifier: TelegramLogHandler для алертов об ошибках со стеком и HealthCheckAlertBridge для моста с chutils.diagnostics"
|
|
8
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Implementation Plan: Telegram Admin Notifications & Diagnostics Alert Bridge (`telegram_notifier_20260729`)
|
|
2
|
+
|
|
3
|
+
## Phase 1: TelegramLogHandler & Alert Throttling
|
|
4
|
+
- [ ] Task: Create `chutils.telegram.notifier` module with `TelegramLogHandler` class for standard `logging`
|
|
5
|
+
- [ ] Task: Implement rate-limiting / deduplication of log alerts to prevent spam during cascading failures
|
|
6
|
+
- [ ] Task: Unit tests for `TelegramLogHandler` formatting, rate-limiting, and error handling
|
|
7
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 1: TelegramLogHandler' (Protocol in workflow.md)
|
|
8
|
+
|
|
9
|
+
## Phase 2: HealthCheckAlertBridge & Diagnostics Integration
|
|
10
|
+
- [ ] Task: Implement `HealthCheckAlertBridge` connected to `chutils.diagnostics`
|
|
11
|
+
- [ ] Task: Export symbols in `src/chutils/telegram/__init__.py` and root `src/chutils/__init__.py`
|
|
12
|
+
- [ ] Task: Unit tests for `HealthCheckAlertBridge` notification triggers
|
|
13
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 2: HealthCheckAlertBridge' (Protocol in workflow.md)
|
|
14
|
+
|
|
15
|
+
## Phase 3: Documentation & Indexing
|
|
16
|
+
- [ ] Task: Add examples in `docs/` and update `api_map.md` / `project_index.json`
|
|
17
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 3: Documentation' (Protocol in workflow.md)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Track Specification: Telegram Admin Notifications & Diagnostics Alert Bridge (`telegram_notifier_20260729`)
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Реализация модуля `chutils.telegram.notifier` для немедленного оповещения администраторов о критических сбоях и проблемах здоровья приложения в Telegram. Модуль содержит встроенный лог-хэндлер `TelegramLogHandler` с защитой от флуда и мост `HealthCheckAlertBridge` для отправки алертов при деградации проверок `chutils.diagnostics`.
|
|
5
|
+
|
|
6
|
+
## Functional Requirements
|
|
7
|
+
- **Лог-хэндлер `TelegramLogHandler`**:
|
|
8
|
+
- Перехват исключений уровня `ERROR` / `CRITICAL`.
|
|
9
|
+
- Форматирование сообщений с трейсбэками, именем модуля и меткой времени.
|
|
10
|
+
- Встроенный Rate-Limiter (дросселирование одинаковых или каскадных алертов, например, не более N сообщений в минуту).
|
|
11
|
+
- Автоматическое чтение `bot_token` и `chat_id` из секции `[Telegram]` конфигурации `chutils`.
|
|
12
|
+
- **Мост алертов диагностики `HealthCheckAlertBridge`**:
|
|
13
|
+
- Подписка на результаты проверок `chutils.diagnostics`.
|
|
14
|
+
- Автоматическая отправка уведомления при переходах статусов здоровья в `DEGRADED` или `UNHEALTHY`.
|
|
15
|
+
- Информативные алерты с форматированием деталей сбоя.
|
|
16
|
+
- **Асинхронность и изоляция**:
|
|
17
|
+
- Отправка алертов не блокирует основной поток приложения (неблокирующий I/O или фоновые таски).
|
|
18
|
+
- Ошибки отправки самого Telegram API не падают с крашем основного приложения.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"track_id": "telegram_ratelimit_20260729",
|
|
3
|
+
"type": "feature",
|
|
4
|
+
"status": "new",
|
|
5
|
+
"created_at": "2026-07-29T00:06:00Z",
|
|
6
|
+
"updated_at": "2026-07-29T00:06:00Z",
|
|
7
|
+
"description": "@rate_limit(rate=3, per=60): Защита от спама/флуда пользователей с автоматической отправкой сообщения 'Пожалуйста, подождите X сек.'"
|
|
8
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Implementation Plan: Telegram Bot Rate Limiting & Throttling (`telegram_ratelimit_20260729`)
|
|
2
|
+
|
|
3
|
+
## Phase 1: Core Telegram Rate Limiter Engine & Decorator
|
|
4
|
+
- [ ] Task: Create `chutils.telegram.rate_limit` module with `TelegramRateLimiter` class wrapping `chutils.decorators.rate_limit`
|
|
5
|
+
- [ ] Task: Implement `wait_sec` calculation logic and template formatting (`{wait_sec}`)
|
|
6
|
+
- [ ] Task: Implement `@tg_rate_limit` decorator for sync/async handlers with scope (`user_id`/`chat_id`), `warning_text` and `silent` options
|
|
7
|
+
- [ ] Task: Unit tests for `TelegramRateLimiter` and `@tg_rate_limit` decorator
|
|
8
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 1: Core Telegram Rate Limiter Engine' (Protocol in workflow.md)
|
|
9
|
+
|
|
10
|
+
## Phase 2: aiogram Middleware & Redis Storage Backend
|
|
11
|
+
- [ ] Task: Implement `TelegramThrottlingMiddleware` for `aiogram 3.x`
|
|
12
|
+
- [ ] Task: Support Redis / `chutils.cache` storage adapter for distributed rate limiting
|
|
13
|
+
- [ ] Task: Export symbols in `src/chutils/telegram/__init__.py` and root `src/chutils/__init__.py`
|
|
14
|
+
- [ ] Task: Unit tests for `aiogram` throttling middleware and Redis storage logic
|
|
15
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 2: aiogram Middleware & Storage' (Protocol in workflow.md)
|
|
16
|
+
|
|
17
|
+
## Phase 3: Documentation & Indexing
|
|
18
|
+
- [ ] Task: Add examples in `docs/` and update `api_map.md` / `project_index.json`
|
|
19
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 3: Documentation' (Protocol in workflow.md)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Track Specification: Telegram Bot Rate Limiting & Throttling (`telegram_ratelimit_20260729`)
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Добавление специализированных механизмов защиты от флуда/спама в Telegram-ботах: декоратор `@tg_rate_limit(rate=3, per=60)` и `TelegramThrottlingMiddleware` (для `aiogram 3.x`). Утилита опирается на проверенное ядро `chutils.decorators.rate_limit`, высчитывает точное время ожидания `wait_sec` и автоматически высылает пользователю информативное предупреждение.
|
|
5
|
+
|
|
6
|
+
## Functional Requirements
|
|
7
|
+
- **Декоратор `@tg_rate_limit` & `TelegramThrottlingMiddleware`**:
|
|
8
|
+
- Параметры: `rate` (количество вызовов), `per` (период в секундах), `strategy` (`token_bucket` / `leaky_bucket`).
|
|
9
|
+
- Шаблон предупреждения: `warning_text="⏱ Пожалуйста, подождите {wait_sec} сек. перед повторной отправкой."`.
|
|
10
|
+
- Тихий режим: `silent=True` для полного отбрасывания спам-запросов без вызова Telegram API и расхода лимитов бота.
|
|
11
|
+
- Ключи лимитирования (`scope`): по `user_id` (дефолт), по `chat_id` или комбинированный `user_and_chat`.
|
|
12
|
+
- Динамический рассчет `wait_sec`: точное количество секунд, оставшихся до возобновления лимита.
|
|
13
|
+
- **Хранение состояний (Storage Backends)**:
|
|
14
|
+
- `In-Memory` (по умолчанию, с TTL-очисткой).
|
|
15
|
+
- Поддержка внешних бэкендов (Redis / `chutils.cache`) для распределенных Telegram-ботов.
|
|
16
|
+
- **Совместимость с фреймворками**:
|
|
17
|
+
- `TelegramThrottlingMiddleware` для `aiogram 3.x`.
|
|
18
|
+
- Синхронный и асинхронный декоратор `@tg_rate_limit` для `python-telegram-bot`, `telebot` и асинхронных хэндлеров.
|
|
19
|
+
|
|
20
|
+
## Out of Scope
|
|
21
|
+
- Глобальное ограничение скорости ответа самого Telegram API (обработка HTTP 429 от Telegram сервера).
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"track_id": "telegram_send_file_20260729",
|
|
3
|
+
"type": "feature",
|
|
4
|
+
"status": "new",
|
|
5
|
+
"created_at": "2026-07-29T20:27:00Z",
|
|
6
|
+
"updated_at": "2026-07-29T20:27:00Z",
|
|
7
|
+
"description": "chutils.telegram.media: send_telegram_file для отправки локальных файлов/папок с авто-архивацией в ZIP и безопасным экранированием подписи"
|
|
8
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Implementation Plan: Telegram File Upload Helper (`telegram_send_file_20260729`)
|
|
2
|
+
|
|
3
|
+
## Phase 1: Core send_telegram_file Implementation
|
|
4
|
+
- [ ] Task: Create `send_telegram_file` function in `chutils.telegram.media`
|
|
5
|
+
- [ ] Task: Integrate `resolve_safe_path` check and directory auto-zipping (`zip_folder`)
|
|
6
|
+
- [ ] Task: Implement safe caption formatting, 1024 char truncation, and 50MB file size limit check
|
|
7
|
+
- [ ] Task: Unit tests for path safety, directory auto-zipping, and caption truncation
|
|
8
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 1: Core File Upload Logic' (Protocol in workflow.md)
|
|
9
|
+
|
|
10
|
+
## Phase 2: Framework Integrations & Lazy Exports
|
|
11
|
+
- [ ] Task: Support `aiogram 3.x` `Bot` sendDocument call and raw HTTP upload fallback
|
|
12
|
+
- [ ] Task: Export `send_telegram_file` in `src/chutils/telegram/__init__.py` and root `src/chutils/__init__.py`
|
|
13
|
+
- [ ] Task: Unit tests for framework compatibility and fallback mechanisms
|
|
14
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 2: Framework Integrations' (Protocol in workflow.md)
|
|
15
|
+
|
|
16
|
+
## Phase 3: Documentation & Indexing
|
|
17
|
+
- [ ] Task: Add examples in `docs/` and update `api_map.md` / `project_index.json`
|
|
18
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 3: Documentation' (Protocol in workflow.md)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Track Specification: Telegram File Upload Helper (`telegram_send_file_20260729`)
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Реализация функции `send_telegram_file` в подсистеме `chutils.telegram.media` для надежной и безопасной отправки локальных файлов и директорий из приложения в Telegram. Функция берет на себя защиту от Path Traversal, экранирование и обрезку подписей (`caption`), контроль лимитов размера Telegram API (50 МБ) и авто-упаковку папок в ZIP-архивы.
|
|
5
|
+
|
|
6
|
+
## Functional Requirements
|
|
7
|
+
- **Функция `send_telegram_file`**:
|
|
8
|
+
- Аргументы: `bot`, `chat_id: int | str`, `file_path: str | Path`, `caption: str | None = None`, `parse_mode: str | None = None`, `allow_unsafe_path: bool = False`.
|
|
9
|
+
- Проверка безопасности пути через `chutils.fs.resolve_safe_path()` (с возможностью отключения через `allow_unsafe_path=True`).
|
|
10
|
+
- Авто-упаковка: если `file_path` указывает на папку, функция автоматически создает временный ZIP-архив через `chutils.fs.zip_folder` и отправляет его как файл.
|
|
11
|
+
- Обработка подписи (`caption`): безопасное экранирование спецсимволов и обрезка текста под 1024 символа (`smart_truncate`) во избежание вылетов по `BadRequest`.
|
|
12
|
+
- Проверка размера: проверка превышения лимита ботов Telegram (50 МБ) перед вызовом API.
|
|
13
|
+
- **Совместимость с фреймворками**:
|
|
14
|
+
- Поддержка экземпляров `Bot` (`aiogram 3.x`, `python-telegram-bot`) и отправка через прямой `HTTP POST` по `bot_token`.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"track_id": "telegram_whitelist_20260729",
|
|
3
|
+
"type": "feature",
|
|
4
|
+
"status": "new",
|
|
5
|
+
"created_at": "2026-07-29T00:07:00Z",
|
|
6
|
+
"updated_at": "2026-07-29T00:07:00Z",
|
|
7
|
+
"description": "SecretUserFilter: Разграничение прав по белым/черным спискам Telegram ID / хэндлов"
|
|
8
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Implementation Plan: Secret User & Access Whitelist/Blacklist Filter (`telegram_whitelist_20260729`)
|
|
2
|
+
|
|
3
|
+
## Phase 1: Core Access List Engine & Decorator
|
|
4
|
+
- [ ] Task: Create `chutils.telegram.whitelist` module with `AccessListManager` class supporting allow/block lists and file persistence
|
|
5
|
+
- [ ] Task: Implement `@allowed_only` decorator with config fallback (`allowed_users`/`blocked_users`)
|
|
6
|
+
- [ ] Task: Unit tests for `AccessListManager` and `@allowed_only` decorator
|
|
7
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 1: Core Access List Engine' (Protocol in workflow.md)
|
|
8
|
+
|
|
9
|
+
## Phase 2: aiogram Integration & Framework Support
|
|
10
|
+
- [ ] Task: Implement `SecretUserFilter` for `aiogram 3.x`
|
|
11
|
+
- [ ] Task: Export symbols in `src/chutils/telegram/__init__.py` and root `src/chutils/__init__.py`
|
|
12
|
+
- [ ] Task: Unit tests for `aiogram` filter and framework compatibility
|
|
13
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 2: aiogram Integration' (Protocol in workflow.md)
|
|
14
|
+
|
|
15
|
+
## Phase 3: Documentation & Indexing
|
|
16
|
+
- [ ] Task: Add examples in `docs/` and update `api_map.md` / `project_index.json`
|
|
17
|
+
- [ ] Task: Conductor - User Manual Verification 'Phase 3: Documentation' (Protocol in workflow.md)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Track Specification: Secret User & Access Whitelist/Blacklist Filter (`telegram_whitelist_20260729`)
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Реализация специализированных фильтров белых и черных списков доступа для Telegram-ботов (`SecretUserFilter`, `@allowed_only`). Компонент позволяет ограничивать доступ к боту или конкретным фичам только определенной группе пользователей (по Telegram ID и @username), с поддержкой динамического пополнения/удаления записей и сохранения в файл/БД.
|
|
5
|
+
|
|
6
|
+
## Functional Requirements
|
|
7
|
+
- **Класс `SecretUserFilter` & Декоратор `@allowed_only`**:
|
|
8
|
+
- Фильтрация по `allowed_ids` (int) и `allowed_usernames` (str).
|
|
9
|
+
- Настройка черного списка: `blocked_ids` / `blocked_usernames`.
|
|
10
|
+
- Автоматический fallback на конфигурацию `chutils`: `get_config_value("Telegram", "allowed_users")` / `blocked_users`.
|
|
11
|
+
- **Динамический менеджер списков (`AccessListManager`)**:
|
|
12
|
+
- Методы `allow_user(user_id_or_username)`, `block_user(user_id_or_username)`, `remove_user(...)`.
|
|
13
|
+
- Опциональное сохранение изменений в JSON-файл (`atomic_write`) или пользовательский провайдер.
|
|
14
|
+
- **Интеграции с фреймворками**:
|
|
15
|
+
- `SecretUserFilter` для `aiogram 3.x` (реализация `BaseFilter`).
|
|
16
|
+
- `@allowed_only` для `python-telegram-bot`, `telebot` и кастомных асинхронных хэндлеров.
|
|
17
|
+
|
|
18
|
+
## Out of Scope
|
|
19
|
+
- Хранение сложных ролей и прав групп в СУБД (RBAC).
|