py-wlcli 0.8.0__py3-none-any.whl
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.
- py_wlcli-0.8.0.dist-info/METADATA +139 -0
- py_wlcli-0.8.0.dist-info/RECORD +320 -0
- py_wlcli-0.8.0.dist-info/WHEEL +4 -0
- py_wlcli-0.8.0.dist-info/entry_points.txt +2 -0
- py_wlcli-0.8.0.dist-info/licenses/LICENSE +21 -0
- wl_cli/__init__.py +27 -0
- wl_cli/__main__.py +130 -0
- wl_cli/capabilities.py +79 -0
- wl_cli/cc/__init__.py +5 -0
- wl_cli/cc/checks.py +1019 -0
- wl_cli/cc/cli.py +370 -0
- wl_cli/cc/mutate.py +1350 -0
- wl_cli/cli_click.py +156 -0
- wl_cli/commands/__init__.py +84 -0
- wl_cli/commands/base.py +80 -0
- wl_cli/commands/buildcommands/__init__.py +1 -0
- wl_cli/commands/buildcommands/build.py +71 -0
- wl_cli/commands/buildcommands/build_utils.py +47 -0
- wl_cli/commands/buildcommands/builders/__init__.py +18 -0
- wl_cli/commands/buildcommands/builders/cleanup.py +35 -0
- wl_cli/commands/buildcommands/builders/coordinator.py +122 -0
- wl_cli/commands/buildcommands/builders/environment.py +81 -0
- wl_cli/commands/buildcommands/builders/rust_builder.py +39 -0
- wl_cli/commands/buildcommands/builders/stubs.py +58 -0
- wl_cli/commands/buildcommands/dist.py +326 -0
- wl_cli/commands/buildcommands/test.py +89 -0
- wl_cli/commands/clean/__init__.py +1 -0
- wl_cli/commands/clean/build.py +151 -0
- wl_cli/commands/clean/clean.py +294 -0
- wl_cli/commands/clean/clean_utils.py +77 -0
- wl_cli/commands/clean/core.py +236 -0
- wl_cli/commands/clean/dead_code/__init__.py +0 -0
- wl_cli/commands/clean/dead_code/dead_code_command.py +70 -0
- wl_cli/commands/clean/dead_code/detector.py +161 -0
- wl_cli/commands/clean/dead_code/fixer.py +176 -0
- wl_cli/commands/clean/dead_code/reporter.py +295 -0
- wl_cli/commands/clean/dead_code/utils.py +0 -0
- wl_cli/commands/clean/lfs.py +215 -0
- wl_cli/commands/clean/python.py +81 -0
- wl_cli/commands/clean/rust.py +91 -0
- wl_cli/commands/clean/utils/__init__.py +34 -0
- wl_cli/commands/clean/venv.py +91 -0
- wl_cli/commands/cleanup.py +73 -0
- wl_cli/commands/click_base.py +79 -0
- wl_cli/commands/config/__init__.py +1 -0
- wl_cli/commands/config/config.py +291 -0
- wl_cli/commands/debug/__init__.py +6 -0
- wl_cli/commands/debug/debug.py +309 -0
- wl_cli/commands/debug/debug_cache.py +86 -0
- wl_cli/commands/debug/debug_subagent.py +156 -0
- wl_cli/commands/debug/output_formatter.py +165 -0
- wl_cli/commands/debug/source_hasher.py +92 -0
- wl_cli/commands/format/__init__.py +13 -0
- wl_cli/commands/format/format_cache_adapter.py +125 -0
- wl_cli/commands/format/format_command.py +197 -0
- wl_cli/commands/format/format_coordinator.py +191 -0
- wl_cli/commands/format/format_executor.py +470 -0
- wl_cli/commands/format/format_outcome.py +44 -0
- wl_cli/commands/format/format_path_handler.py +1016 -0
- wl_cli/commands/format/format_progress.py +62 -0
- wl_cli/commands/format/format_reporter.py +31 -0
- wl_cli/commands/format/python_formatter.py +506 -0
- wl_cli/commands/format/rust_formatter.py +106 -0
- wl_cli/commands/gate/__init__.py +1 -0
- wl_cli/commands/gate/gate_command.py +862 -0
- wl_cli/commands/gate/preflight.py +445 -0
- wl_cli/commands/git/__init__.py +1 -0
- wl_cli/commands/git/config.py +169 -0
- wl_cli/commands/git/git_facts.py +60 -0
- wl_cli/commands/git/git_flow.py +86 -0
- wl_cli/commands/git/hook.py +112 -0
- wl_cli/commands/git/policy.py +216 -0
- wl_cli/commands/git/push_update.py +82 -0
- wl_cli/commands/initenv/__init__.py +1 -0
- wl_cli/commands/initenv/common/__init__.py +23 -0
- wl_cli/commands/initenv/common/check_git_bash.py +78 -0
- wl_cli/commands/initenv/common/error_handler.py +68 -0
- wl_cli/commands/initenv/common/exceptions.py +52 -0
- wl_cli/commands/initenv/components/__init__.py +4 -0
- wl_cli/commands/initenv/components/cargo_sync.py +240 -0
- wl_cli/commands/initenv/components/config_manager.py +106 -0
- wl_cli/commands/initenv/components/directory_utils.py +71 -0
- wl_cli/commands/initenv/components/git/__init__.py +9 -0
- wl_cli/commands/initenv/components/git/branch_creator.py +143 -0
- wl_cli/commands/initenv/components/git/git_flow_interface.py +24 -0
- wl_cli/commands/initenv/components/git/git_flow_manager.py +159 -0
- wl_cli/commands/initenv/components/git/git_lfs_manager.py +272 -0
- wl_cli/commands/initenv/components/git/git_utility.py +254 -0
- wl_cli/commands/initenv/components/git/gitignore_manager.py +53 -0
- wl_cli/commands/initenv/components/git_initializer.py +212 -0
- wl_cli/commands/initenv/components/i18n_manager.py +104 -0
- wl_cli/commands/initenv/components/log_manager.py +241 -0
- wl_cli/commands/initenv/components/project_structure/__init__.py +23 -0
- wl_cli/commands/initenv/components/project_structure/config_generator.py +360 -0
- wl_cli/commands/initenv/components/project_structure/directory_creator.py +184 -0
- wl_cli/commands/initenv/components/project_structure/hook_source.py +110 -0
- wl_cli/commands/initenv/components/project_structure/hooks_manager.py +995 -0
- wl_cli/commands/initenv/components/project_structure/readme_handler.py +56 -0
- wl_cli/commands/initenv/components/project_structure/rust_files_handler.py +30 -0
- wl_cli/commands/initenv/components/project_structure/setup_handler.py +103 -0
- wl_cli/commands/initenv/components/project_structure/sop_generator.py +73 -0
- wl_cli/commands/initenv/components/project_structure/template_copier.py +104 -0
- wl_cli/commands/initenv/components/project_structure/template_manager.py +195 -0
- wl_cli/commands/initenv/components/pyproject_generator.py +194 -0
- wl_cli/commands/initenv/components/rust_initializer.py +145 -0
- wl_cli/commands/initenv/components/symlink_cleaner.py +99 -0
- wl_cli/commands/initenv/components/symlink_manager.py +52 -0
- wl_cli/commands/initenv/components/venv_manager.py +118 -0
- wl_cli/commands/initenv/initenv.py +169 -0
- wl_cli/commands/initenv/services/__init__.py +11 -0
- wl_cli/commands/initenv/services/environment_initializer.py +288 -0
- wl_cli/commands/initenv/services/git_lfs_initializer.py +26 -0
- wl_cli/commands/initenv/services/project_structure_initializer.py +52 -0
- wl_cli/commands/lfs/README.md +221 -0
- wl_cli/commands/lfs/__init__.py +5 -0
- wl_cli/commands/lfs/cli.py +106 -0
- wl_cli/commands/lfs/config.py +164 -0
- wl_cli/commands/lfs/hook.py +61 -0
- wl_cli/commands/lfs/initializer.py +531 -0
- wl_cli/commands/lfs/manager.py +95 -0
- wl_cli/commands/lfs/policy.py +165 -0
- wl_cli/commands/lfs/watcher.py +294 -0
- wl_cli/commands/lint/__init__.py +1 -0
- wl_cli/commands/lint/lint_command.py +297 -0
- wl_cli/commands/lint/lint_executor.py +409 -0
- wl_cli/commands/lint/lint_reporter.py +579 -0
- wl_cli/commands/lint/lint_run.py +258 -0
- wl_cli/commands/lint/mypy_config.py +90 -0
- wl_cli/commands/registry.py +103 -0
- wl_cli/commands/self/__init__.py +7 -0
- wl_cli/commands/self/common/__init__.py +8 -0
- wl_cli/commands/self/common/capabilities.py +30 -0
- wl_cli/commands/self/common/config.py +27 -0
- wl_cli/commands/self/common/version_cache.py +85 -0
- wl_cli/commands/self/handlers/__init__.py +19 -0
- wl_cli/commands/self/handlers/base_handler.py +28 -0
- wl_cli/commands/self/handlers/install_handler.py +85 -0
- wl_cli/commands/self/handlers/status_handler.py +66 -0
- wl_cli/commands/self/handlers/uninstall_handler.py +58 -0
- wl_cli/commands/self/handlers/update_handler.py +102 -0
- wl_cli/commands/self/handlers/version_handler.py +16 -0
- wl_cli/commands/self/self_command.py +237 -0
- wl_cli/commands/self/services/__init__.py +15 -0
- wl_cli/commands/self/services/installation_manager.py +187 -0
- wl_cli/commands/self/services/local_installer.py +165 -0
- wl_cli/commands/self/services/pypi_updater.py +278 -0
- wl_cli/commands/self/services/windows_update.py +174 -0
- wl_cli/commands/testcommands/__init__.py +8 -0
- wl_cli/commands/testcommands/base_dependency_analyzer.py +198 -0
- wl_cli/commands/testcommands/batch_processor.py +278 -0
- wl_cli/commands/testcommands/cache_manager.py +1156 -0
- wl_cli/commands/testcommands/coverage_analyzer.py +955 -0
- wl_cli/commands/testcommands/coverage_cache_manager.py +183 -0
- wl_cli/commands/testcommands/progress_manager.py +79 -0
- wl_cli/commands/testcommands/python_env_detector.py +207 -0
- wl_cli/commands/testcommands/report_generator.py +101 -0
- wl_cli/commands/testcommands/single_test_executor.py +250 -0
- wl_cli/commands/testcommands/speed_checker.py +118 -0
- wl_cli/commands/testcommands/test_command_builder.py +165 -0
- wl_cli/commands/testcommands/test_commands.py +786 -0
- wl_cli/commands/testcommands/test_reporter.py +181 -0
- wl_cli/commands/testcommands/test_result_handler.py +96 -0
- wl_cli/commands/testcommands/test_runner.py +1343 -0
- wl_cli/commands/testcommands/test_utils.py +197 -0
- wl_cli/commands/testcommands/utils/__init__.py +17 -0
- wl_cli/commands/testcommands/utils/coverage_parser.py +98 -0
- wl_cli/commands/testcommands/utils/env_info.py +36 -0
- wl_cli/commands/testcommands/utils/junit_parser.py +75 -0
- wl_cli/commands/testcommands/utils/markdown_utils.py +20 -0
- wl_cli/commands/testcommands/utils/project_root.py +61 -0
- wl_cli/commands/update/__init__.py +9 -0
- wl_cli/commands/update/services/__init__.py +21 -0
- wl_cli/commands/update/services/backup_manager.py +207 -0
- wl_cli/commands/update/services/component_manager.py +83 -0
- wl_cli/commands/update/services/conflict_resolver.py +189 -0
- wl_cli/commands/update/services/vendors_updater.py +85 -0
- wl_cli/commands/update/services/version_tracker.py +127 -0
- wl_cli/commands/update/update_command.py +270 -0
- wl_cli/commands/update/utils/__init__.py +3 -0
- wl_cli/commands/version/__init__.py +9 -0
- wl_cli/commands/version/version_command.py +155 -0
- wl_cli/commands/workflow.py +477 -0
- wl_cli/env/__init__.py +5 -0
- wl_cli/env/cli.py +167 -0
- wl_cli/env_status.py +157 -0
- wl_cli/envelope.py +91 -0
- wl_cli/exceptions.py +85 -0
- wl_cli/lib/__init__.py +3 -0
- wl_cli/lib/rust_utils.py +35 -0
- wl_cli/mcp/__init__.py +6 -0
- wl_cli/mcp/capabilities.py +19 -0
- wl_cli/mcp/cli.py +22 -0
- wl_cli/mcp/gitlab.py +553 -0
- wl_cli/mcp/k8s.py +344 -0
- wl_cli/mcp/protocol.py +159 -0
- wl_cli/platform.py +139 -0
- wl_cli/quality/__init__.py +18 -0
- wl_cli/utils/__init__.py +7 -0
- wl_cli/utils/cache.py +491 -0
- wl_cli/utils/cache_ledger.py +355 -0
- wl_cli/utils/cache_store.py +546 -0
- wl_cli/utils/config/__init__.py +27 -0
- wl_cli/utils/config/config_loader.py +163 -0
- wl_cli/utils/config/core.py +862 -0
- wl_cli/utils/config/defaults.py +142 -0
- wl_cli/utils/config/env_exporter.py +86 -0
- wl_cli/utils/config/env_parser.py +108 -0
- wl_cli/utils/config/validation.py +280 -0
- wl_cli/utils/error_handler.py +165 -0
- wl_cli/utils/file_copier.py +56 -0
- wl_cli/utils/file_operations.py +506 -0
- wl_cli/utils/language_utils.py +122 -0
- wl_cli/utils/lazy_import.py +240 -0
- wl_cli/utils/log_levels.py +35 -0
- wl_cli/utils/log_rotators.py +74 -0
- wl_cli/utils/logging.py +458 -0
- wl_cli/utils/output_context.py +142 -0
- wl_cli/utils/performance/__init__.py +1 -0
- wl_cli/utils/performance/decorators.py +111 -0
- wl_cli/utils/performance/exporter.py +38 -0
- wl_cli/utils/performance/models.py +16 -0
- wl_cli/utils/performance/monitor.py +161 -0
- wl_cli/utils/performance_monitor.py +32 -0
- wl_cli/utils/platform_adapter.py +131 -0
- wl_cli/utils/pre_commit.py +266 -0
- wl_cli/utils/pre_commit_config.py +72 -0
- wl_cli/utils/root.py +521 -0
- wl_cli/utils/root_fallback.py +256 -0
- wl_cli/utils/run_evidence.py +236 -0
- wl_cli/utils/structured_logger.py +18 -0
- wl_cli/utils/structured_logging/__init__.py +19 -0
- wl_cli/utils/structured_logging/config.py +337 -0
- wl_cli/utils/structured_logging/core.py +177 -0
- wl_cli/utils/structured_logging/env.py +56 -0
- wl_cli/utils/structured_logging/filtering.py +75 -0
- wl_cli/utils/structured_logging/filters.py +55 -0
- wl_cli/utils/structured_logging/formatters.py +251 -0
- wl_cli/utils/structured_logging/handlers.py +308 -0
- wl_cli/utils/structured_logging/logger.py +354 -0
- wl_cli/utils/subprocess.py +71 -0
- wl_cli/utils/subprocess_utils.py +260 -0
- wl_cli/utils/test_utils/__init__.py +5 -0
- wl_cli/utils/test_utils/test_filter.py +36 -0
- wl_cli/utils/uv_run.py +79 -0
- wl_cli/utils/uv_tool.py +117 -0
- wl_cli/utils/uv_tree.py +71 -0
- wl_cli/utils/uv_workspace.py +174 -0
- wl_cli/utils/version/__init__.py +15 -0
- wl_cli/utils/version/pypi_version_checker.py +95 -0
- wl_cli/utils/version/version_comparator.py +133 -0
- wl_cli/utils/version/version_detectors.py +312 -0
- wl_cli/utils/version/version_service.py +131 -0
- wl_cli/utils/version/version_updater.py +198 -0
- wl_cli/utils/wl_dir_updater.py +1440 -0
- wl_cli/utils/workspace_detector/__init__.py +28 -0
- wl_cli/utils/workspace_detector/core.py +161 -0
- wl_cli/utils/workspace_detector/detection_strategies.py +107 -0
- wl_cli/utils/workspace_detector/exceptions.py +5 -0
- wl_cli/utils/workspace_detector/types.py +17 -0
- wl_cli/utils/workspace_detector/venv_resolver.py +84 -0
- wl_cli/vendors/config/.codespellrc +2 -0
- wl_cli/vendors/config/dependencies.toml +10 -0
- wl_cli/vendors/config/mypy.ini +62 -0
- wl_cli/vendors/config/pyproject_defaults.toml +28 -0
- wl_cli/vendors/config/template_config.toml +24 -0
- wl_cli/vendors/config/tool_configs.toml +76 -0
- wl_cli/vendors/git/.gitignore +122 -0
- wl_cli/vendors/git/.pre-commit-config.yaml +37 -0
- wl_cli/vendors/hooks/applypatch-msg.sample +15 -0
- wl_cli/vendors/hooks/commit-msg.sample +24 -0
- wl_cli/vendors/hooks/fsmonitor-watchman.sample +174 -0
- wl_cli/vendors/hooks/post-update.sample +8 -0
- wl_cli/vendors/hooks/pre-applypatch.sample +14 -0
- wl_cli/vendors/hooks/pre-commit +45 -0
- wl_cli/vendors/hooks/pre-commit.legacy +31 -0
- wl_cli/vendors/hooks/pre-commit.sample +49 -0
- wl_cli/vendors/hooks/pre-merge-commit.sample +13 -0
- wl_cli/vendors/hooks/pre-push.sample +60 -0
- wl_cli/vendors/hooks/pre-rebase.sample +169 -0
- wl_cli/vendors/hooks/pre-receive.sample +24 -0
- wl_cli/vendors/hooks/prepare-commit-msg.sample +42 -0
- wl_cli/vendors/hooks/push-to-checkout.sample +78 -0
- wl_cli/vendors/hooks/sendemail-validate.sample +77 -0
- wl_cli/vendors/hooks/unix/applypatch-msg.sample +15 -0
- wl_cli/vendors/hooks/unix/check_lockfile.py +58 -0
- wl_cli/vendors/hooks/unix/check_lockfile.sh +36 -0
- wl_cli/vendors/hooks/unix/commit-msg.sample +24 -0
- wl_cli/vendors/hooks/unix/fsmonitor-watchman.sample +174 -0
- wl_cli/vendors/hooks/unix/post-update.sample +8 -0
- wl_cli/vendors/hooks/unix/pre-applypatch.sample +14 -0
- wl_cli/vendors/hooks/unix/pre-commit +190 -0
- wl_cli/vendors/hooks/unix/pre-commit.legacy +31 -0
- wl_cli/vendors/hooks/unix/pre-commit.py +81 -0
- wl_cli/vendors/hooks/unix/pre-commit.sample +49 -0
- wl_cli/vendors/hooks/unix/pre-merge-commit.sample +13 -0
- wl_cli/vendors/hooks/unix/pre-push +417 -0
- wl_cli/vendors/hooks/unix/pre-push.sample +53 -0
- wl_cli/vendors/hooks/unix/pre-rebase.sample +169 -0
- wl_cli/vendors/hooks/unix/pre-receive.sample +24 -0
- wl_cli/vendors/hooks/unix/prepare-commit-msg.sample +42 -0
- wl_cli/vendors/hooks/update.sample +128 -0
- wl_cli/vendors/hooks/win/work.bat +63 -0
- wl_cli/vendors/project/.gitignore +90 -0
- wl_cli/vendors/project/.python-version +1 -0
- wl_cli/vendors/project/LICENSE +21 -0
- wl_cli/vendors/project/README.md +0 -0
- wl_cli/vendors/project/pyproject.toml +27 -0
- wl_cli/vendors/project/pyproject_no_workspace.toml +16 -0
- wl_cli/vendors/project/pyproject_workspace.toml +14 -0
- wl_cli/vendors/readme/README.md +120 -0
- wl_cli/vendors/rust/Cargo.toml +14 -0
- wl_cli/vendors/rust/lib/__init__.py +3 -0
- wl_cli/vendors/rust/lib/rust_utils.py +31 -0
- wl_cli/vendors/rust/src/lib.rs +13 -0
- wl_cli/vendors/rust/src/main.rs +3 -0
- wl_cli/vendors/rust/tests/test_rust_fallback.py +40 -0
- wl_cli/vendors/sop_doc/git-dev-sop.md +220 -0
- wl_cli/vendors/sop_doc/industrial-standard-sop.md +145 -0
- wl_cli/vendors/sop_doc/python-sop.md +342 -0
- wl_cli/vendors/sop_doc/rust-readme.md +219 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from .core import WorkspaceDetector
|
|
2
|
+
from .detection_strategies import (
|
|
3
|
+
check_init_workspace,
|
|
4
|
+
check_pyproject_workspace,
|
|
5
|
+
check_tree_workspace,
|
|
6
|
+
check_uv_lock_workspace,
|
|
7
|
+
is_valid_version,
|
|
8
|
+
parse_root_packages,
|
|
9
|
+
)
|
|
10
|
+
from .exceptions import WorkspaceDetectionError
|
|
11
|
+
from .types import ValidationResult, WorkspaceDetectionRules
|
|
12
|
+
from .venv_resolver import get_active_venv_path, get_active_venv_path_str, get_venv_path
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"WorkspaceDetectionError",
|
|
16
|
+
"WorkspaceDetectionRules",
|
|
17
|
+
"ValidationResult",
|
|
18
|
+
"WorkspaceDetector",
|
|
19
|
+
"check_pyproject_workspace",
|
|
20
|
+
"check_uv_lock_workspace",
|
|
21
|
+
"check_init_workspace",
|
|
22
|
+
"check_tree_workspace",
|
|
23
|
+
"parse_root_packages",
|
|
24
|
+
"is_valid_version",
|
|
25
|
+
"get_venv_path",
|
|
26
|
+
"get_active_venv_path_str",
|
|
27
|
+
"get_active_venv_path",
|
|
28
|
+
]
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from ..subprocess_utils import SubprocessExecutor
|
|
4
|
+
from .detection_strategies import (
|
|
5
|
+
check_init_workspace,
|
|
6
|
+
check_pyproject_workspace,
|
|
7
|
+
check_tree_workspace,
|
|
8
|
+
check_uv_lock_workspace,
|
|
9
|
+
)
|
|
10
|
+
from .types import ValidationResult, WorkspaceDetectionRules
|
|
11
|
+
from .venv_resolver import get_active_venv_path_str, get_venv_path
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class WorkspaceDetector:
|
|
15
|
+
def __init__(self, rules: WorkspaceDetectionRules | None = None) -> None:
|
|
16
|
+
self._executor = SubprocessExecutor()
|
|
17
|
+
self._cache: dict[str, bool] = {}
|
|
18
|
+
self._rules: WorkspaceDetectionRules = {
|
|
19
|
+
"use_pyproject": True,
|
|
20
|
+
"use_uv_lock": True,
|
|
21
|
+
"use_uv_init": True,
|
|
22
|
+
"use_uv_tree": True,
|
|
23
|
+
"uv_tree_min_roots": 2,
|
|
24
|
+
}
|
|
25
|
+
if rules:
|
|
26
|
+
self._rules.update(rules)
|
|
27
|
+
|
|
28
|
+
def detect(self, project_root: Path | None = None) -> bool:
|
|
29
|
+
"""Whether ``project_root`` looks like a uv workspace.
|
|
30
|
+
|
|
31
|
+
Worst case is bounded: the file checks are local I/O, and the two
|
|
32
|
+
``uv`` probes each carry ``UV_PROBE_TIMEOUT_SECONDS``, so a wedged
|
|
33
|
+
``uv`` costs at most ``2 x`` that value (30 s) before detection
|
|
34
|
+
answers ``False`` -- never an unbounded wait (#184). The strategies
|
|
35
|
+
keep their order; the bound is the probes', not a skipped probe's.
|
|
36
|
+
"""
|
|
37
|
+
start = (project_root or Path(self._rules.get("cwd", "."))).resolve()
|
|
38
|
+
key = str(start)
|
|
39
|
+
if key in self._cache:
|
|
40
|
+
return self._cache[key]
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
root = self._find_workspace_root(start)
|
|
44
|
+
|
|
45
|
+
if self._rules.get("use_pyproject", True) and check_pyproject_workspace(
|
|
46
|
+
root
|
|
47
|
+
):
|
|
48
|
+
self._cache[key] = True
|
|
49
|
+
return True
|
|
50
|
+
|
|
51
|
+
if self._rules.get("use_uv_lock", True) and check_uv_lock_workspace(root):
|
|
52
|
+
self._cache[key] = True
|
|
53
|
+
return True
|
|
54
|
+
|
|
55
|
+
if self._rules.get("use_uv_init", True) and check_init_workspace(
|
|
56
|
+
root, self._executor
|
|
57
|
+
):
|
|
58
|
+
self._cache[key] = True
|
|
59
|
+
return True
|
|
60
|
+
|
|
61
|
+
min_roots = int(self._rules.get("uv_tree_min_roots", 2))
|
|
62
|
+
if self._rules.get("use_uv_tree", True) and check_tree_workspace(
|
|
63
|
+
root, self._executor, min_roots
|
|
64
|
+
):
|
|
65
|
+
self._cache[key] = True
|
|
66
|
+
return True
|
|
67
|
+
|
|
68
|
+
self._cache[key] = False
|
|
69
|
+
return False
|
|
70
|
+
except Exception:
|
|
71
|
+
self._cache[key] = False
|
|
72
|
+
return False
|
|
73
|
+
|
|
74
|
+
def validate(self, project_root: Path | None = None) -> ValidationResult:
|
|
75
|
+
root = self._find_workspace_root(
|
|
76
|
+
(project_root or Path(self._rules.get("cwd", "."))).resolve()
|
|
77
|
+
)
|
|
78
|
+
detected = self.detect(root)
|
|
79
|
+
details: dict[str, str] = {}
|
|
80
|
+
pyproject_path = root / "pyproject.toml"
|
|
81
|
+
uv_lock_path = root / "uv.lock"
|
|
82
|
+
details["pyproject.exists"] = str(pyproject_path.exists())
|
|
83
|
+
details["uv.lock.exists"] = str(uv_lock_path.exists())
|
|
84
|
+
details["apps.exists"] = str((root / "apps").exists())
|
|
85
|
+
details["packages.exists"] = str((root / "packages").exists())
|
|
86
|
+
return ValidationResult(valid=detected, details=details)
|
|
87
|
+
|
|
88
|
+
def get_config(self) -> WorkspaceDetectionRules:
|
|
89
|
+
return self._rules.copy()
|
|
90
|
+
|
|
91
|
+
def resolve_path(self, path: str | Path, project_root: Path | None = None) -> Path:
|
|
92
|
+
root = self._find_workspace_root(
|
|
93
|
+
(project_root or Path(self._rules.get("cwd", "."))).resolve()
|
|
94
|
+
)
|
|
95
|
+
p = Path(path)
|
|
96
|
+
if p.is_absolute():
|
|
97
|
+
return p
|
|
98
|
+
resolved = (root / p).resolve()
|
|
99
|
+
return resolved
|
|
100
|
+
|
|
101
|
+
def get_venv_path(self, project_root: Path | None = None) -> Path | None:
|
|
102
|
+
root = self._find_workspace_root(
|
|
103
|
+
(project_root or Path(self._rules.get("cwd", "."))).resolve()
|
|
104
|
+
)
|
|
105
|
+
return get_venv_path(root, self._executor)
|
|
106
|
+
|
|
107
|
+
def get_active_venv_path_str(self, project_root: Path | None = None) -> str:
|
|
108
|
+
root = self._find_workspace_root(
|
|
109
|
+
(project_root or Path(self._rules.get("cwd", "."))).resolve()
|
|
110
|
+
)
|
|
111
|
+
return get_active_venv_path_str(root)
|
|
112
|
+
|
|
113
|
+
def getActiveVenvPath(self, project_root: Path | None = None) -> str:
|
|
114
|
+
"""
|
|
115
|
+
Alias for get_active_venv_path_str to support backward compatibility.
|
|
116
|
+
|
|
117
|
+
This method uses camelCase naming for backward compatibility.
|
|
118
|
+
"""
|
|
119
|
+
return self.get_active_venv_path_str(project_root)
|
|
120
|
+
|
|
121
|
+
def _find_workspace_root(self, start: Path) -> Path:
|
|
122
|
+
cur = start
|
|
123
|
+
try:
|
|
124
|
+
while True:
|
|
125
|
+
if self._rules.get("use_pyproject", True) and check_pyproject_workspace(
|
|
126
|
+
cur
|
|
127
|
+
):
|
|
128
|
+
return cur
|
|
129
|
+
if self._rules.get("use_uv_lock", True) and check_uv_lock_workspace(
|
|
130
|
+
cur
|
|
131
|
+
):
|
|
132
|
+
return cur
|
|
133
|
+
if cur.parent == cur:
|
|
134
|
+
return start
|
|
135
|
+
cur = cur.parent
|
|
136
|
+
except Exception:
|
|
137
|
+
return start
|
|
138
|
+
|
|
139
|
+
def getConfig(self) -> WorkspaceDetectionRules:
|
|
140
|
+
"""
|
|
141
|
+
Alias for get_config to support backward compatibility.
|
|
142
|
+
|
|
143
|
+
This method uses camelCase naming for backward compatibility.
|
|
144
|
+
"""
|
|
145
|
+
return self.get_config()
|
|
146
|
+
|
|
147
|
+
def resolvePath(self, path: str | Path, project_root: Path | None = None) -> Path:
|
|
148
|
+
"""
|
|
149
|
+
Alias for resolve_path to support backward compatibility.
|
|
150
|
+
|
|
151
|
+
This method uses camelCase naming for backward compatibility.
|
|
152
|
+
"""
|
|
153
|
+
return self.resolve_path(path, project_root)
|
|
154
|
+
|
|
155
|
+
def getVenvPath(self, project_root: Path | None = None) -> Path | None:
|
|
156
|
+
"""
|
|
157
|
+
Alias for get_venv_path to support backward compatibility.
|
|
158
|
+
|
|
159
|
+
This method uses camelCase naming for backward compatibility.
|
|
160
|
+
"""
|
|
161
|
+
return self.get_venv_path(project_root)
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from ..logging import log_warning_pair
|
|
4
|
+
from ..subprocess_utils import SubprocessExecutor, SubprocessResult
|
|
5
|
+
from ..uv_tree import is_valid_version as _is_valid_version
|
|
6
|
+
from ..uv_tree import parse_uv_tree_roots
|
|
7
|
+
|
|
8
|
+
#: Upper bound, in seconds, for the two ``uv`` *probes* behind this detector
|
|
9
|
+
#: (``uv init --dry-run`` and ``uv tree``). Both are heuristics that normally
|
|
10
|
+
#: answer in milliseconds, but on a runner whose ``uv`` blocks on a network
|
|
11
|
+
#: fetch or on its cache lock they can hang forever -- three MRs silently hung
|
|
12
|
+
#: >10 minutes on exactly this path (#184). Expiry is treated as "not
|
|
13
|
+
#: detected", which costs a caller nothing it could have relied on, while an
|
|
14
|
+
#: unbounded probe costs the whole ``wl test`` / ``wl init`` / ``wl build`` run.
|
|
15
|
+
#: Only quick probes get a deadline: production commands stay unbounded.
|
|
16
|
+
#: ``detect()`` can run both probes, so its worst case is ``2 x`` this
|
|
17
|
+
#: value (30 s). The strategies keep their order -- the bound belongs to the
|
|
18
|
+
#: probes, not to skipping one.
|
|
19
|
+
UV_PROBE_TIMEOUT_SECONDS: float = 15.0
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def check_pyproject_workspace(root: Path) -> bool:
|
|
23
|
+
"""检查pyproject.toml中是否包含workspace配置。"""
|
|
24
|
+
py = root / "pyproject.toml"
|
|
25
|
+
if not py.exists():
|
|
26
|
+
return False
|
|
27
|
+
try:
|
|
28
|
+
content = py.read_text(encoding="utf-8")
|
|
29
|
+
return "[tool.uv.workspace]" in content or "tool.uv.workspace" in content
|
|
30
|
+
except Exception:
|
|
31
|
+
return False
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def check_uv_lock_workspace(root: Path) -> bool:
|
|
35
|
+
"""检查uv.lock文件是否包含足够多的包。"""
|
|
36
|
+
lock = root / "uv.lock"
|
|
37
|
+
if not lock.exists():
|
|
38
|
+
return False
|
|
39
|
+
try:
|
|
40
|
+
content = lock.read_text(encoding="utf-8")
|
|
41
|
+
count = content.count("[package]")
|
|
42
|
+
return count >= 5
|
|
43
|
+
except Exception:
|
|
44
|
+
return False
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def check_init_workspace(root: Path, executor: SubprocessExecutor) -> bool:
|
|
48
|
+
"""使用uv init --dry-run检查是否已在工作区中。"""
|
|
49
|
+
try:
|
|
50
|
+
result = executor.run(
|
|
51
|
+
["uv", "init", "--dry-run"],
|
|
52
|
+
cwd=root,
|
|
53
|
+
quiet=True,
|
|
54
|
+
cache_result=True,
|
|
55
|
+
timeout=UV_PROBE_TIMEOUT_SECONDS,
|
|
56
|
+
)
|
|
57
|
+
_warn_if_probe_timed_out("uv init --dry-run", root, result)
|
|
58
|
+
output = (result.stdout or "") + (result.stderr or "")
|
|
59
|
+
return result.success and ("is already a member of workspace" in output)
|
|
60
|
+
except Exception:
|
|
61
|
+
return False
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def check_tree_workspace(
|
|
65
|
+
root: Path, executor: SubprocessExecutor, min_roots: int = 2
|
|
66
|
+
) -> bool:
|
|
67
|
+
"""使用uv tree检查根包数量是否达到最小值。"""
|
|
68
|
+
try:
|
|
69
|
+
result = executor.run(
|
|
70
|
+
["uv", "tree"],
|
|
71
|
+
cwd=root,
|
|
72
|
+
quiet=True,
|
|
73
|
+
cache_result=True,
|
|
74
|
+
timeout=UV_PROBE_TIMEOUT_SECONDS,
|
|
75
|
+
)
|
|
76
|
+
_warn_if_probe_timed_out("uv tree", root, result)
|
|
77
|
+
if not result.success or not result.stdout:
|
|
78
|
+
return False
|
|
79
|
+
lines = result.stdout.split("\n")
|
|
80
|
+
roots = parse_root_packages(lines)
|
|
81
|
+
return len(roots) >= min_roots
|
|
82
|
+
except Exception:
|
|
83
|
+
return False
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _warn_if_probe_timed_out(probe: str, root: Path, result: SubprocessResult) -> None:
|
|
87
|
+
"""让「探测超时」可见:否则它和「确实不是工作区」在调用方眼里一模一样。"""
|
|
88
|
+
if not result.timed_out:
|
|
89
|
+
return
|
|
90
|
+
# Language-neutral payload (a command and a path): both variants are
|
|
91
|
+
# identical by design.
|
|
92
|
+
log_warning_pair(
|
|
93
|
+
f"{probe} did not answer within {UV_PROBE_TIMEOUT_SECONDS:g}s in {root}; "
|
|
94
|
+
"treating the workspace probe as not detected",
|
|
95
|
+
f"{probe} 在 {root} 未于 {UV_PROBE_TIMEOUT_SECONDS:g} 秒内返回;"
|
|
96
|
+
"按未探测到工作区处理",
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def parse_root_packages(lines: list[str]) -> list[str]:
|
|
101
|
+
"""从uv tree输出中解析根包(委派到共享解析器,见 #178)。"""
|
|
102
|
+
return parse_uv_tree_roots(lines)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def is_valid_version(version: str) -> bool:
|
|
106
|
+
"""检查版本字符串是否有效(委派到共享解析器,字符集不变)。"""
|
|
107
|
+
return _is_valid_version(version)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import TypedDict
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class WorkspaceDetectionRules(TypedDict, total=False):
|
|
6
|
+
use_pyproject: bool
|
|
7
|
+
use_uv_lock: bool
|
|
8
|
+
use_uv_init: bool
|
|
9
|
+
use_uv_tree: bool
|
|
10
|
+
uv_tree_min_roots: int
|
|
11
|
+
cwd: str
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class ValidationResult:
|
|
16
|
+
valid: bool
|
|
17
|
+
details: dict[str, str]
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from ..logging import log_error, log_info
|
|
5
|
+
from ..subprocess_utils import SubprocessExecutor
|
|
6
|
+
from .exceptions import WorkspaceDetectionError
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get_venv_path(root: Path, executor: SubprocessExecutor) -> Path | None:
|
|
10
|
+
"""获取虚拟环境路径。"""
|
|
11
|
+
env_path = os.environ.get("VENV_PATH")
|
|
12
|
+
if env_path:
|
|
13
|
+
p = Path(env_path)
|
|
14
|
+
if p.exists():
|
|
15
|
+
return p.resolve()
|
|
16
|
+
local = root / ".venv"
|
|
17
|
+
if local.exists():
|
|
18
|
+
return local.resolve()
|
|
19
|
+
try:
|
|
20
|
+
res = executor.run(
|
|
21
|
+
[
|
|
22
|
+
"uv",
|
|
23
|
+
"run",
|
|
24
|
+
"python",
|
|
25
|
+
"-c",
|
|
26
|
+
"import sys;print(sys.executable)",
|
|
27
|
+
],
|
|
28
|
+
cwd=root,
|
|
29
|
+
quiet=True,
|
|
30
|
+
)
|
|
31
|
+
if res.success and res.stdout:
|
|
32
|
+
exe = Path(res.stdout.strip())
|
|
33
|
+
parent = exe.parent
|
|
34
|
+
venv_dir = parent.parent
|
|
35
|
+
if venv_dir.exists():
|
|
36
|
+
return venv_dir.resolve()
|
|
37
|
+
except Exception:
|
|
38
|
+
return None
|
|
39
|
+
return None
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def get_active_venv_path_str(root: Path) -> str:
|
|
43
|
+
"""获取当前激活的虚拟环境路径。"""
|
|
44
|
+
log_info(f"Workspace venv path resolution at: {root}")
|
|
45
|
+
|
|
46
|
+
# 检查工作区配置
|
|
47
|
+
py = root / "pyproject.toml"
|
|
48
|
+
uv_toml = root / "uv.toml"
|
|
49
|
+
ws_json = root / "workspace.json"
|
|
50
|
+
has_ws_conf = False
|
|
51
|
+
try:
|
|
52
|
+
if py.exists() and "tool.uv.workspace" in py.read_text(encoding="utf-8"):
|
|
53
|
+
has_ws_conf = True
|
|
54
|
+
if uv_toml.exists() or ws_json.exists():
|
|
55
|
+
has_ws_conf = True
|
|
56
|
+
except Exception:
|
|
57
|
+
pass
|
|
58
|
+
if not has_ws_conf:
|
|
59
|
+
log_error("Workspace configuration file not found or invalid")
|
|
60
|
+
raise WorkspaceDetectionError("Workspace configuration not found or invalid")
|
|
61
|
+
|
|
62
|
+
# 检查虚拟环境是否激活
|
|
63
|
+
venv_env = os.environ.get("VIRTUAL_ENV", "").strip()
|
|
64
|
+
if not venv_env:
|
|
65
|
+
log_error("Virtual environment is not activated (VIRTUAL_ENV not set)")
|
|
66
|
+
raise WorkspaceDetectionError("Virtual environment not activated")
|
|
67
|
+
|
|
68
|
+
venv_path = Path(venv_env)
|
|
69
|
+
if not venv_path.exists():
|
|
70
|
+
log_error(f"Activated virtual environment path does not exist: {venv_env}")
|
|
71
|
+
raise WorkspaceDetectionError(
|
|
72
|
+
"Activated virtual environment path does not exist"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
resolved = venv_path.resolve()
|
|
76
|
+
# Use platform-appropriate path separators instead of forcing POSIX format
|
|
77
|
+
normalized = str(resolved)
|
|
78
|
+
log_info(f"Resolved virtual environment path: {normalized}")
|
|
79
|
+
return normalized
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def get_active_venv_path(root: Path) -> str:
|
|
83
|
+
"""get_active_venv_path_str的别名,用于向后兼容。"""
|
|
84
|
+
return get_active_venv_path_str(root)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# MyPy configuration file for WL Commands
|
|
2
|
+
# WL Commands 的 mypy 配置文件
|
|
3
|
+
|
|
4
|
+
[mypy]
|
|
5
|
+
# Python version to target (目标 Python 版本)
|
|
6
|
+
python_version = 3.12
|
|
7
|
+
|
|
8
|
+
# Baseline: ignore missing imports from untyped third-party libraries.
|
|
9
|
+
# 基线:忽略未类型化第三方库的导入告警(import-untyped)。
|
|
10
|
+
ignore_missing_imports = true
|
|
11
|
+
|
|
12
|
+
# Error reporting settings (错误输出设置)
|
|
13
|
+
show_error_codes = true
|
|
14
|
+
show_error_context = true
|
|
15
|
+
show_column_numbers = true
|
|
16
|
+
pretty = true
|
|
17
|
+
|
|
18
|
+
# Incremental mode for faster checks (增量检查,加快速度)
|
|
19
|
+
incremental = true
|
|
20
|
+
|
|
21
|
+
# Cache directory (缓存目录)
|
|
22
|
+
cache_dir = .mypy_cache
|
|
23
|
+
|
|
24
|
+
# Core warning flags — always ON (核心告警项,始终开启)
|
|
25
|
+
warn_return_any = true
|
|
26
|
+
warn_unused_configs = true
|
|
27
|
+
warn_unused_ignores = true
|
|
28
|
+
|
|
29
|
+
# ---------------------------------------------------------------------------
|
|
30
|
+
# Tightening ladder (渐进收紧阶梯)
|
|
31
|
+
# The stricter flags below are intentionally DISABLED (commented out) in the
|
|
32
|
+
# baseline. Teams can progressively enable them as the codebase becomes fully
|
|
33
|
+
# typed. 以下为渐进式收紧项:基线默认关闭,待代码完全类型化后逐项开启。
|
|
34
|
+
# ---------------------------------------------------------------------------
|
|
35
|
+
# allow_untyped_defs = false
|
|
36
|
+
# 禁止未类型标注的函数定义 (Disallow untyped function definitions)
|
|
37
|
+
# allow_untyped_calls = false
|
|
38
|
+
# 禁止调用未类型标注的函数 (Disallow calls to untyped functions)
|
|
39
|
+
# allow_untyped_decorators = false
|
|
40
|
+
# 禁止未类型标注的装饰器 (Disallow untyped decorators)
|
|
41
|
+
# allow_incomplete_defs = false
|
|
42
|
+
# 禁止不完整的类型标注 (Disallow partially annotated definitions)
|
|
43
|
+
# 注(2026-09-16):此处曾把 strict_optional 列为 “future rung”,那是错的。
|
|
44
|
+
# mypy 早已**默认开启** strict optional(CLI 只提供 `--no-strict-optional`),
|
|
45
|
+
# 所以 `strict_optional = true` 是 **no-op**、不构成一档阶梯(只有显式 `= false` 才有意义)。
|
|
46
|
+
# 日后若要加下一档,应挑一个真正有效的开关(如 disallow_untyped_defs),而不是这一条。
|
|
47
|
+
# Rung 1 (enabled 2026-09): no_implicit_optional + warn_redundant_casts
|
|
48
|
+
no_implicit_optional = true
|
|
49
|
+
# 禁止隐式 Optional (Disallow implicit Optional)
|
|
50
|
+
warn_redundant_casts = true
|
|
51
|
+
# 警告冗余的强制类型转换 (Warn about redundant casts)
|
|
52
|
+
|
|
53
|
+
# Exclude specific directories (排除目录)
|
|
54
|
+
exclude =
|
|
55
|
+
__pycache__,
|
|
56
|
+
build,
|
|
57
|
+
dist,
|
|
58
|
+
*.egg-info,
|
|
59
|
+
.ruff_cache,
|
|
60
|
+
.venv,
|
|
61
|
+
.git,
|
|
62
|
+
rust/
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "{{project_name}}"
|
|
3
|
+
dynamic = ["version"]
|
|
4
|
+
description = "{{project_name}} - Python项目"
|
|
5
|
+
requires-python = ">=3.10"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
readme = "README.md"
|
|
8
|
+
authors = [{name = "Admin", email = "admin@example.com"}]
|
|
9
|
+
|
|
10
|
+
[project.urls]
|
|
11
|
+
Homepage = "https://github.com/example/{{project_name}}"
|
|
12
|
+
Issues = "https://github.com/example/{{project_name}}/issues"
|
|
13
|
+
|
|
14
|
+
[build-system]
|
|
15
|
+
requires = ["maturin>=1.0,<2.0"]
|
|
16
|
+
build-backend = "maturin"
|
|
17
|
+
|
|
18
|
+
[maturin]
|
|
19
|
+
manifest-path = "rust/Cargo.toml"
|
|
20
|
+
module-name = "{{python_name}}.lib.{{rust_name}}"
|
|
21
|
+
python-source = "src"
|
|
22
|
+
include = ["src/{{python_name}}/**/*"]
|
|
23
|
+
bindings = "pyo3"
|
|
24
|
+
features = ["pyo3/extension-module"]
|
|
25
|
+
|
|
26
|
+
[build-system.setuptools]
|
|
27
|
+
requires = ["setuptools>=61.0"]
|
|
28
|
+
build-backend = "setuptools.build_meta"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
[core_templates]
|
|
2
|
+
python_version = { src = "project/.python-version", dest = ".python-version" }
|
|
3
|
+
license = { src = "project/LICENSE", dest = "LICENSE" }
|
|
4
|
+
gitignore = { src = "project/.gitignore", dest = ".gitignore" }
|
|
5
|
+
|
|
6
|
+
[pyproject_templates]
|
|
7
|
+
workspace = { src = "project/pyproject.toml", dest = "pyproject.toml" }
|
|
8
|
+
no_workspace = { src = "project/pyproject_no_workspace.toml", dest = "pyproject.toml" }
|
|
9
|
+
workspace_root = { src = "project/pyproject_workspace.toml", dest = "pyproject.toml" }
|
|
10
|
+
|
|
11
|
+
[rust_templates]
|
|
12
|
+
init_py = { src = "rust/lib/__init__.py", dest = "src/{project_name}/lib/__init__.py" }
|
|
13
|
+
rust_utils = { src = "rust/lib/rust_utils.py", dest = "src/{project_name}/lib/rust_utils.py", template = true }
|
|
14
|
+
test_fallback = { src = "rust/tests/test_rust_fallback.py", dest = "tests/test_rust_fallback.py" }
|
|
15
|
+
|
|
16
|
+
[sop_templates]
|
|
17
|
+
rust_readme = { src = "sop_doc/rust-readme.md", dest = "rust/README.md" }
|
|
18
|
+
python_sop = { src = "sop_doc/python-sop.md", dest = "src/{project_name}/lib/sop.md" }
|
|
19
|
+
git_dev_sop = { src = "sop_doc/git-dev-sop.md", dest = "docs/git-dev-sop.md" }
|
|
20
|
+
|
|
21
|
+
[config_templates]
|
|
22
|
+
codespellrc = { src = "config/.codespellrc", dest = ".wl/.codespellrc" }
|
|
23
|
+
mypy = { src = "config/mypy.ini", dest = ".wl/mypy.ini" }
|
|
24
|
+
precommit = { src = "git/.pre-commit-config.yaml", dest = ".wl/.pre-commit-config.yaml" }
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
[tool.ruff]
|
|
2
|
+
line-length = 88
|
|
3
|
+
target-version = "py312"
|
|
4
|
+
|
|
5
|
+
[tool.ruff.lint]
|
|
6
|
+
select = [
|
|
7
|
+
"E",
|
|
8
|
+
"W",
|
|
9
|
+
"F",
|
|
10
|
+
"I",
|
|
11
|
+
"N",
|
|
12
|
+
"UP",
|
|
13
|
+
"B",
|
|
14
|
+
"C4",
|
|
15
|
+
"SIM",
|
|
16
|
+
"TCH",
|
|
17
|
+
"PTH",
|
|
18
|
+
"PGH",
|
|
19
|
+
"PL",
|
|
20
|
+
"RUF",
|
|
21
|
+
]
|
|
22
|
+
ignore = [
|
|
23
|
+
"E501",
|
|
24
|
+
"PLR0913",
|
|
25
|
+
"PLR0915",
|
|
26
|
+
]
|
|
27
|
+
per-file-ignores = { "tests/*" = ["S101", "ARG"] }
|
|
28
|
+
|
|
29
|
+
[tool.mypy]
|
|
30
|
+
# Python version to target (PEP 8 compatible)
|
|
31
|
+
python_version = "3.12"
|
|
32
|
+
|
|
33
|
+
# Enable strict type checking following PEP 8
|
|
34
|
+
type_checking_mode = "strict"
|
|
35
|
+
|
|
36
|
+
# Error reporting settings
|
|
37
|
+
show_error_codes = true
|
|
38
|
+
show_error_context = true
|
|
39
|
+
show_column_numbers = true
|
|
40
|
+
pretty = true
|
|
41
|
+
|
|
42
|
+
# Incremental mode for faster checks
|
|
43
|
+
incremental = true
|
|
44
|
+
|
|
45
|
+
# Cache directory
|
|
46
|
+
cache_dir = ".mypy_cache"
|
|
47
|
+
|
|
48
|
+
# Basic strictness settings
|
|
49
|
+
warn_return_any = true
|
|
50
|
+
warn_unused_configs = true
|
|
51
|
+
warn_unused_ignores = true
|
|
52
|
+
|
|
53
|
+
# Typing discipline settings
|
|
54
|
+
allow_untyped_defs = false
|
|
55
|
+
allow_untyped_calls = false
|
|
56
|
+
allow_untyped_decorators = false
|
|
57
|
+
allow_incomplete_defs = false
|
|
58
|
+
strict_optional = true
|
|
59
|
+
|
|
60
|
+
# Import settings
|
|
61
|
+
no_implicit_optional = true
|
|
62
|
+
|
|
63
|
+
# Error handling
|
|
64
|
+
warn_redundant_casts = true
|
|
65
|
+
|
|
66
|
+
# Exclude specific directories
|
|
67
|
+
exclude = [
|
|
68
|
+
"__pycache__",
|
|
69
|
+
"build",
|
|
70
|
+
"dist",
|
|
71
|
+
"*.egg-info",
|
|
72
|
+
".ruff_cache",
|
|
73
|
+
".venv",
|
|
74
|
+
".git",
|
|
75
|
+
"rust/"
|
|
76
|
+
]
|