ruff-sync 0.1.6.dev1__tar.gz → 0.1.6.dev2__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.
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/plans/issue-116-config-validation.md +6 -6
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/ruff-sync-usage/SKILL.md +3 -2
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/ruff-sync-usage/references/troubleshooting.md +20 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/AGENTS.md +1 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/PKG-INFO +1 -1
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/configuration.md +3 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/usage.md +4 -1
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/pyproject.toml +1 -1
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/src/ruff_sync/core.py +1 -1
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/src/ruff_sync/validation.py +102 -4
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_config_validation.py +164 -2
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/uv.lock +1 -1
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/DEPENDENCIES.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/TESTING.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/decisions/0001-type-refactoring-strategy.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/decisions/0002-tui-node-ast.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/decisions/README.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/doc-fix.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/formatters-architecture.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/gitlab-reports.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/issue-102-context.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/plans/issue-100-roadmap-plan.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/ruff.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/adr/SKILL.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/dirty-equals/SKILL.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/dirty-equals/references/common-matchers.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/dirty-equals/references/toml-matching.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/dirty-equals/trigger_eval.json +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/gh-issues/SKILL.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/mike/SKILL.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/mike/references/commands.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/mkdocs-generation/SKILL.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/mkdocs-generation/examples.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/mkdocs-generation/templates/api-reference.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/mkdocs-generation/templates/getting-started.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/mkdocs-generation/templates/index.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/mkdocs-generation/templates/mkdocs.yml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/release-notes-generation/SKILL.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/ruff-sync-usage/references/ci-integration.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/ruff-sync-usage/references/configuration.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/skill-creator/SKILL.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/skill-creator/references/best-practices.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/skill-creator/references/evaluating-skills.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/skill-creator/references/optimizing-descriptions.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/skill-creator/references/quickstart.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/skill-creator/references/sources.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/skill-creator/references/using-scripts.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/skill-creator/scripts/scaffold_skill.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/textual/SKILL.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/textual/examples/basic_app.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/textual/examples/reactive_example.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/textual/references/events.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/textual/references/styling.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/textual/references/testing.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/textual/references/widgets.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/SKILL.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/evals.json +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/references/advanced-narrowing.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/references/error-code-lookup.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/references/generics.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/references/naming.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/references/protocol-patterns.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/references/quickstart.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/references/refactoring-patterns.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/scripts/audit_types.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/warnings-control/SKILL.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/tui_design.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/tui_requirements.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/tui_rule_browsing.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/tui_rule_browsing_design.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/workflows/add-test-case.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/workflows/update-screenshots.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.git-blame-ignore-revs +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.github/dependabot.yml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.github/workflows/ci.yaml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.github/workflows/complexity.yaml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.gitignore +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.pre-commit-config.yaml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.pre-commit-hooks.yaml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/CONTRIBUTING.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/LICENSE.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/README.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/codecov.yml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/configs/data-science-engineering/ruff.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/configs/fastapi/ruff.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/configs/kitchen-sink/ruff.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/agent-skill.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/assets/favicon.png +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/assets/github-job-summary.png +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/assets/github-pr-annotation.png +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/assets/inspect-main.png +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/assets/inspect-search.png +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/assets/logo.png +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/assets/ruff_sync_banner.png +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/assets/screenshots/dashboard.svg +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/assets/screenshots/legend_help.svg +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/assets/screenshots/rule_details.svg +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/assets/screenshots/screenshot_sample.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/assets/screenshots/search_omnibox.svg +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/best-practices.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/ci-integration.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/contributing.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/examples/advanced-config.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/examples/basic-config.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/gen_ref_pages.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/index.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/inspect.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/installation.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/overrides/main.html +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/overrides/partials/version_warning.html +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/pre-commit.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/pre-defined-configs.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/troubleshooting.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/docs/url-resolution.md +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/mkdocs.yml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/scripts/check_dogfood.sh +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/scripts/generate_tui_screenshots.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/scripts/gitclone_dogfood.sh +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/scripts/pull_dogfood.sh +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/skills-lock.json +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/src/ruff_sync/__init__.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/src/ruff_sync/__main__.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/src/ruff_sync/cli.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/src/ruff_sync/config_io.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/src/ruff_sync/constants.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/src/ruff_sync/dependencies.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/src/ruff_sync/formatters.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/src/ruff_sync/pre_commit.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/src/ruff_sync/system.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/src/ruff_sync/tui/__init__.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/src/ruff_sync/tui/app.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/src/ruff_sync/tui/constants.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/src/ruff_sync/tui/screens.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/src/ruff_sync/tui/themes.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/src/ruff_sync/tui/types_.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/src/ruff_sync/tui/widgets.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/src/ruff_sync/types_.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tasks.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/__init__.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/conftest.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/multi_upstream_final.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/multi_upstream_initial.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/multi_upstream_up1.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/multi_upstream_up2.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/no_changes_final.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/no_changes_initial.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/no_changes_upstream.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/no_dotted_keys_final.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/no_dotted_keys_initial.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/no_dotted_keys_upstream.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/no_ruff_cfg_final.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/no_ruff_cfg_initial.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/no_ruff_cfg_upstream.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/readme_excludes_final.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/readme_excludes_initial.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/readme_excludes_upstream.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/standard_final.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/standard_initial.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/lifecycle_tomls/standard_upstream.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/ruff.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_basic.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_check.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_ci_integration.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_ci_validation.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_config_io.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_constants.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_corner_cases.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_dependencies.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_deprecation.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_e2e.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_formatters.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_git_fetch.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_minimal_imports.sh +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_pre_commit.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_project.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_rule_logic.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_scaffold.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_serialization.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_system.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_toml_operations.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_url_handling.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/test_whitespace.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/tui/__init__.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/tui/conftest.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/tui/test_themes.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/tui/test_tui.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/tui/test_tui_types.py +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/w_ruff_sync_cfg/pyproject.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/wo_ruff_cfg/pyproject.toml +0 -0
- {ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/tests/wo_ruff_sync_cfg/pyproject.toml +0 -0
|
@@ -24,12 +24,12 @@ passing both.
|
|
|
24
24
|
> Use this to pick your agent tier. Simple phases can be handled by a weak/cheap model;
|
|
25
25
|
> Complex phases need a capable reasoning model.
|
|
26
26
|
|
|
27
|
-
| Priority | Label | Complexity | Feature | Scope |
|
|
28
|
-
|
|
29
|
-
| 1 (Must Have) | 🔴 | 🟡 Moderate | TOML syntax + Ruff CLI validation | New `validation.py` module; gated by `--validate` in `pull()` |
|
|
30
|
-
| 2 (Should Have) | 🟠 | 🟢 Simple | Python version consistency check | `validation.py` + warn when `--validate` is active |
|
|
31
|
-
| 3 (Could Have) | 🟡 | 🔴 Complex | Rule deprecation warnings | `validation.py` + subprocess + JSON + DI; gated by `--validate` |
|
|
32
|
-
| 4 (Nice to Have) | 🟢 | 🟢 Simple | `--strict` flag | Upgrades warnings to failures; implies `--validate` |
|
|
27
|
+
| Priority | Label | Complexity | Feature | Scope | Status |
|
|
28
|
+
|---|---|---|---|---|---|
|
|
29
|
+
| 1 (Must Have) | 🔴 | 🟡 Moderate | TOML syntax + Ruff CLI validation | New `validation.py` module; gated by `--validate` in `pull()` | ✅ Completed |
|
|
30
|
+
| 2 (Should Have) | 🟠 | 🟢 Simple | Python version consistency check | `validation.py` + warn when `--validate` is active | ✅ Completed |
|
|
31
|
+
| 3 (Could Have) | 🟡 | 🔴 Complex | Rule deprecation warnings | `validation.py` + subprocess + JSON + DI; gated by `--validate` | ⏳ Pending |
|
|
32
|
+
| 4 (Nice to Have) | 🟢 | 🟢 Simple | `--strict` flag | Upgrades warnings to failures; implies `--validate` | 🚧 In Progress |
|
|
33
33
|
|
|
34
34
|
---
|
|
35
35
|
|
|
@@ -127,8 +127,9 @@ ruff-sync git@github.com:my-org/standards.git # SSH (shallow clone)
|
|
|
127
127
|
## Gotchas
|
|
128
128
|
|
|
129
129
|
- **`exclude` uses dotted paths, not TOML paths.** `lint.per-file-ignores` refers to the `per-file-ignores` key inside `[tool.ruff.lint]`. Do NOT write `tool.ruff.lint.per-file-ignores`.
|
|
130
|
-
- **`--validate` is opt-in.** Validation is off by default. Pass `--validate` (or `--strict`) to run the merged config through Ruff before writing. The sync is aborted if Ruff rejects the config, leaving the local file untouched.
|
|
131
|
-
-
|
|
130
|
+
- **`--validate` is opt-in.** Validation is off by default. Pass `--validate` (or `--strict`) to run the merged config through Ruff before writing. The sync is aborted if Ruff rejects the config, leaving the local file untouched. This includes a **Python version consistency check** that compares upstream `target-version` against local `requires-python`.
|
|
131
|
+
- **Excluding `target-version` skips consistency validation.** If `target-version` (or `tool.ruff.target-version`) is in the `exclude` list, `ruff-sync` will skip the version consistency check and log a warning. This is useful for projects that intentionally deviate from upstream Python versions.
|
|
132
|
+
- **`--strict` implies `--validate`.** If you want warnings (like version mismatches or deprecated rules) treated as failures, only `--strict` is needed — don't pass both.
|
|
132
133
|
- **Validation soft-fails if `ruff` is not on PATH.** If the `ruff` binary can't be found, a warning is logged and the sync continues normally.
|
|
133
134
|
- **Use `--init` only for new projects.** `ruff-sync` requires an existing `pyproject.toml` or `ruff.toml`. Pass `--init` to scaffold one if the directory is empty. This will automatically generate a `[tool.ruff-sync]` configuration block for future syncs.
|
|
134
135
|
- **Use `--save` to persist CLI arguments.** If you want to update an existing `pyproject.toml` with a new upstream URL or exclusion, pass `--save` to write the new configuration to the file.
|
|
@@ -77,6 +77,26 @@ ruff-sync # pulls config AND updates the hook rev (if pre-commit-versio
|
|
|
77
77
|
```
|
|
78
78
|
|
|
79
79
|
To suppress this check entirely, omit `--pre-commit` from `ruff-sync check` or set `pre-commit-version-sync = false`.
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Python Version Mismatch Warning
|
|
83
|
+
|
|
84
|
+
**Symptom:** Sync succeeds but logs a warning like:
|
|
85
|
+
```
|
|
86
|
+
⚠️ Version mismatch: upstream [tool.ruff] target-version='py39' targets Python 3.9, but local [project] requires-python='>=3.10' requires Python >= 3.10.
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Cause:** The upstream configuration is targeting an older Python version than your project requires. This can lead to Ruff not using newer rules or features available to your project.
|
|
90
|
+
|
|
91
|
+
**Fix:**
|
|
92
|
+
1. **Update Upstream:** The ideal fix is to update the `target-version` in the upstream repository to a newer version (e.g., `py311`).
|
|
93
|
+
2. **Exclude the key:** If you need to stay on a specific version locally, add `target-version` to your `exclude` list:
|
|
94
|
+
```toml
|
|
95
|
+
[tool.ruff-sync]
|
|
96
|
+
exclude = ["target-version"]
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
In **`--strict`** mode, this warning is upgraded to a hard failure and will abort the sync.
|
|
80
100
|
|
|
81
101
|
---
|
|
82
102
|
|
|
@@ -20,6 +20,7 @@ Specific workflows, libraries, and tools are documented in `.agents/skills/`. Be
|
|
|
20
20
|
|
|
21
21
|
- **Python** ≥ 3.10 (target version `py310`)
|
|
22
22
|
- **Package Manager**: [uv](https://docs.astral.sh/uv/) — Use `uv run <command>` for all executions to ensure the correct environment.
|
|
23
|
+
- **Note on PATH**: On macOS, `uv` is often installed in `~/.local/bin`. If `uv` is not found, add this to your `PATH`: `export PATH="$PATH:$HOME/.local/bin"`.
|
|
23
24
|
- **Linter / Formatter**: [Ruff](https://docs.astral.sh/ruff/) (`>=0.15.0`)
|
|
24
25
|
- **Type Checker**: [mypy](https://mypy-lang.org/) (strict mode)
|
|
25
26
|
- **Test Framework**: [pytest](https://docs.pytest.org/) with `pytest-asyncio`, `respx`, `pyfakefs` (See [Testing Standards](.agents/TESTING.md))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ruff-sync
|
|
3
|
-
Version: 0.1.6.
|
|
3
|
+
Version: 0.1.6.dev2
|
|
4
4
|
Summary: Synchronize Ruff linter configuration across projects
|
|
5
5
|
Project-URL: Homepage, https://github.com/Kilo59/ruff-sync
|
|
6
6
|
Project-URL: Documentation, https://kilo59.github.io/ruff-sync/
|
|
@@ -62,6 +62,9 @@ If your projects are on different Python versions but share linting rules:
|
|
|
62
62
|
exclude = ["target-version"]
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
+
> [!NOTE]
|
|
66
|
+
> Excluding `target-version` also automatically skips the Python version consistency check otherwise performed during `--validate` or `--strict` runs.
|
|
67
|
+
|
|
65
68
|
#### Sequential merging of multiple sources
|
|
66
69
|
|
|
67
70
|
You can specify multiple upstream sources as a list. They will be merged in order—from top to bottom—with later sources overriding or extending earlier ones.
|
|
@@ -122,12 +122,15 @@ ruff-sync --validate
|
|
|
122
122
|
|
|
123
123
|
If Ruff rejects the merged config (e.g., because the upstream introduced an unknown key), the sync is aborted and your local file is left untouched.
|
|
124
124
|
|
|
125
|
-
For stricter enforcement, use `--strict`. This upgrades any validation *warnings*
|
|
125
|
+
For stricter enforcement, use `--strict`. This upgrades any validation *warnings* into hard failures. This includes a **Python version consistency check** that compares the upstream `[tool.ruff] target-version` against your local `[project] requires-python`:
|
|
126
126
|
|
|
127
127
|
```bash
|
|
128
128
|
ruff-sync --strict
|
|
129
129
|
```
|
|
130
130
|
|
|
131
|
+
> [!TIP]
|
|
132
|
+
> If you intentionally manage your Python version locally and it differs from the upstream, you can add `target-version` to your `exclude` list. `ruff-sync` will then skip the consistency check and log a warning explaining why.
|
|
133
|
+
|
|
131
134
|
> [!NOTE]
|
|
132
135
|
> `--strict` implies `--validate`. You do not need to pass both flags.
|
|
133
136
|
>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "ruff-sync"
|
|
3
|
-
version = "0.1.6.
|
|
3
|
+
version = "0.1.6.dev2"
|
|
4
4
|
description = "Synchronize Ruff linter configuration across projects"
|
|
5
5
|
keywords = ["ruff", "linter", "config", "synchronize", "python", "linting", "automation", "tomlkit", "pre-commit"]
|
|
6
6
|
authors = [
|
|
@@ -1164,7 +1164,7 @@ async def pull(
|
|
|
1164
1164
|
|
|
1165
1165
|
is_ruff_toml = is_ruff_toml_file(_source_toml_path.name)
|
|
1166
1166
|
if not validate_merged_config(
|
|
1167
|
-
source_doc, is_ruff_toml=is_ruff_toml, strict=args.strict
|
|
1167
|
+
source_doc, is_ruff_toml=is_ruff_toml, strict=args.strict, exclude=args.exclude
|
|
1168
1168
|
):
|
|
1169
1169
|
fmt.error(
|
|
1170
1170
|
"❌ Merged config failed validation. Local file left unchanged.",
|
|
@@ -4,12 +4,17 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import logging
|
|
6
6
|
import pathlib
|
|
7
|
+
import re
|
|
7
8
|
import subprocess
|
|
8
9
|
import tempfile
|
|
10
|
+
from typing import TYPE_CHECKING
|
|
9
11
|
|
|
10
12
|
import tomlkit
|
|
11
13
|
from tomlkit import TOMLDocument
|
|
12
14
|
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from collections.abc import Iterable
|
|
17
|
+
|
|
13
18
|
__all__ = [
|
|
14
19
|
"validate_merged_config",
|
|
15
20
|
"validate_ruff_accepts_config",
|
|
@@ -18,6 +23,91 @@ __all__ = [
|
|
|
18
23
|
|
|
19
24
|
LOGGER = logging.getLogger(__name__)
|
|
20
25
|
|
|
26
|
+
_RUFF_TARGET_VERSION_PATTERN = re.compile(r"^py(\d)(\d+)$")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _ruff_target_to_tuple(target_version: str) -> tuple[int, int] | None:
|
|
30
|
+
"""Parse a Ruff target-version string (e.g. 'py311') into a (major, minor) tuple."""
|
|
31
|
+
m = _RUFF_TARGET_VERSION_PATTERN.match(target_version)
|
|
32
|
+
if not m:
|
|
33
|
+
return None
|
|
34
|
+
return int(m.group(1)), int(m.group(2))
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _requires_python_min_version(requires_python: str) -> tuple[int, int] | None:
|
|
38
|
+
"""Extract the minimum Python version from a PEP 440 requires-python string.
|
|
39
|
+
|
|
40
|
+
Examples:
|
|
41
|
+
'>=3.10' -> (3, 10)
|
|
42
|
+
'^3.11' -> (3, 11)
|
|
43
|
+
'~=3.9' -> (3, 9)
|
|
44
|
+
"""
|
|
45
|
+
# TODO: Consider using packaging.specifiers.SpecifierSet optionally if available
|
|
46
|
+
# Match all version specifiers of the form X.Y
|
|
47
|
+
matches = re.findall(r"(\d+)\.(\d+)", requires_python)
|
|
48
|
+
if matches:
|
|
49
|
+
# Convert to list of (int, int) and return the minimum semantic version
|
|
50
|
+
versions = [(int(major), int(minor)) for major, minor in matches]
|
|
51
|
+
return min(versions)
|
|
52
|
+
return None
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def check_python_version_consistency(
|
|
56
|
+
doc: TOMLDocument, strict: bool = False, exclude: Iterable[str] = ()
|
|
57
|
+
) -> bool:
|
|
58
|
+
"""Warn if the merged ruff target-version conflicts with requires-python.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
doc: The merged TOML document (pyproject.toml format).
|
|
62
|
+
strict: If True, treat version mismatch as a failure.
|
|
63
|
+
exclude: List of keys excluded from the ruff configuration.
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
True if versions are consistent or if check is skipped.
|
|
67
|
+
False if strict=True and versions are inconsistent.
|
|
68
|
+
"""
|
|
69
|
+
if "target-version" in exclude or "tool.ruff.target-version" in exclude:
|
|
70
|
+
LOGGER.warning(
|
|
71
|
+
"Skipping Python version consistency check: 'target-version' is "
|
|
72
|
+
"excluded in [tool.ruff-sync]."
|
|
73
|
+
)
|
|
74
|
+
return True
|
|
75
|
+
try:
|
|
76
|
+
ruff_section = doc.get("tool", {}).get("ruff", {})
|
|
77
|
+
target_version = ruff_section.get("target-version")
|
|
78
|
+
requires_python = doc.get("project", {}).get("requires-python")
|
|
79
|
+
except (AttributeError, TypeError):
|
|
80
|
+
return True # Don't crash on unexpected doc shapes
|
|
81
|
+
|
|
82
|
+
if not target_version or not requires_python:
|
|
83
|
+
missing = []
|
|
84
|
+
if not target_version:
|
|
85
|
+
missing.append("[tool.ruff] target-version")
|
|
86
|
+
if not requires_python:
|
|
87
|
+
missing.append("[project] requires-python")
|
|
88
|
+
LOGGER.warning(f"Skipping Python version consistency check: missing {', '.join(missing)}.")
|
|
89
|
+
return True # Nothing to compare
|
|
90
|
+
|
|
91
|
+
ruff_min = _ruff_target_to_tuple(str(target_version))
|
|
92
|
+
proj_min = _requires_python_min_version(str(requires_python))
|
|
93
|
+
|
|
94
|
+
if ruff_min is None or proj_min is None:
|
|
95
|
+
return True # Couldn't parse one of the versions
|
|
96
|
+
|
|
97
|
+
if ruff_min < proj_min:
|
|
98
|
+
msg = (
|
|
99
|
+
f"Version mismatch: upstream [tool.ruff] target-version='{target_version}' "
|
|
100
|
+
f"targets Python {ruff_min[0]}.{ruff_min[1]}, but local [project] requires-python="
|
|
101
|
+
f"'{requires_python}' requires Python >= {proj_min[0]}.{proj_min[1]}. "
|
|
102
|
+
"Consider updating target-version in the upstream config."
|
|
103
|
+
)
|
|
104
|
+
if strict:
|
|
105
|
+
LOGGER.error(f"❌ {msg}")
|
|
106
|
+
return False
|
|
107
|
+
LOGGER.warning(f"⚠️ {msg}")
|
|
108
|
+
|
|
109
|
+
return True
|
|
110
|
+
|
|
21
111
|
|
|
22
112
|
def validate_toml_syntax(doc: TOMLDocument) -> bool:
|
|
23
113
|
"""Return True if the document serializes to valid TOML.
|
|
@@ -61,8 +151,8 @@ def validate_ruff_accepts_config(
|
|
|
61
151
|
dummy_py.write_text("# ruff-sync config validation\n", encoding="utf-8")
|
|
62
152
|
|
|
63
153
|
config_flag = f"--config={tmp_path}"
|
|
64
|
-
#
|
|
65
|
-
cmd = ["ruff", "check",
|
|
154
|
+
# Using --config should be enough to isolate from project config
|
|
155
|
+
cmd = ["ruff", "check", config_flag, str(dummy_py)]
|
|
66
156
|
LOGGER.debug(f"Running ruff config validation: {' '.join(cmd)}")
|
|
67
157
|
|
|
68
158
|
try:
|
|
@@ -105,7 +195,10 @@ def validate_ruff_accepts_config(
|
|
|
105
195
|
|
|
106
196
|
|
|
107
197
|
def validate_merged_config(
|
|
108
|
-
doc: TOMLDocument,
|
|
198
|
+
doc: TOMLDocument,
|
|
199
|
+
is_ruff_toml: bool = False,
|
|
200
|
+
strict: bool = False,
|
|
201
|
+
exclude: Iterable[str] = (),
|
|
109
202
|
) -> bool:
|
|
110
203
|
"""Run all validation checks on the merged TOML document.
|
|
111
204
|
|
|
@@ -116,10 +209,15 @@ def validate_merged_config(
|
|
|
116
209
|
doc: The merged TOML document to validate.
|
|
117
210
|
is_ruff_toml: True if the document is a standalone ruff.toml.
|
|
118
211
|
strict: If True, treat configuration warnings as hard failures.
|
|
212
|
+
exclude: List of keys excluded from the ruff configuration.
|
|
119
213
|
|
|
120
214
|
Returns:
|
|
121
215
|
True if all validation checks pass, False otherwise.
|
|
122
216
|
"""
|
|
123
217
|
if not validate_toml_syntax(doc):
|
|
124
218
|
return False
|
|
125
|
-
|
|
219
|
+
if not validate_ruff_accepts_config(doc, is_ruff_toml=is_ruff_toml, strict=strict):
|
|
220
|
+
return False
|
|
221
|
+
if not is_ruff_toml:
|
|
222
|
+
return check_python_version_consistency(doc, strict=strict, exclude=exclude)
|
|
223
|
+
return True
|
|
@@ -21,6 +21,7 @@ import ruff_sync
|
|
|
21
21
|
from ruff_sync import get_config
|
|
22
22
|
from ruff_sync.cli import LOGGER
|
|
23
23
|
from ruff_sync.validation import (
|
|
24
|
+
check_python_version_consistency,
|
|
24
25
|
validate_merged_config,
|
|
25
26
|
validate_ruff_accepts_config,
|
|
26
27
|
validate_toml_syntax,
|
|
@@ -326,8 +327,8 @@ def test_validate_merged_config_valid(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
|
326
327
|
cmd = cast("list[str]", called["cmd"])
|
|
327
328
|
# Check that some argument refers to a ruff.toml-specific path.
|
|
328
329
|
assert any("ruff.toml" in str(part) for part in cmd)
|
|
329
|
-
#
|
|
330
|
-
assert "--isolated" in cmd
|
|
330
|
+
# verify --isolated is NOT present because it conflicts with --config
|
|
331
|
+
assert "--isolated" not in cmd
|
|
331
332
|
|
|
332
333
|
|
|
333
334
|
def test_validate_merged_config_returns_false_on_invalid(
|
|
@@ -491,5 +492,166 @@ async def test_pull_succeeds_when_validate_passes(
|
|
|
491
492
|
assert "line-length = 100" in source_path.read_text()
|
|
492
493
|
|
|
493
494
|
|
|
495
|
+
# ===========================================================================
|
|
496
|
+
# Priority 2 — Python Version Consistency Check
|
|
497
|
+
# ===========================================================================
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
@pytest.mark.parametrize(
|
|
501
|
+
"toml_content, expected_warn, expected_msg",
|
|
502
|
+
[
|
|
503
|
+
pytest.param(
|
|
504
|
+
'[project]\nrequires-python = ">=3.10"\n\n[tool.ruff]\ntarget-version = "py39"\n',
|
|
505
|
+
True,
|
|
506
|
+
"Version mismatch",
|
|
507
|
+
id="mismatch-warn",
|
|
508
|
+
),
|
|
509
|
+
pytest.param(
|
|
510
|
+
'[project]\nrequires-python = ">=3.10"\n\n[tool.ruff]\ntarget-version = "py310"\n',
|
|
511
|
+
False,
|
|
512
|
+
None,
|
|
513
|
+
id="compatible-exact",
|
|
514
|
+
),
|
|
515
|
+
pytest.param(
|
|
516
|
+
'[project]\nrequires-python = ">=3.10"\n',
|
|
517
|
+
False,
|
|
518
|
+
None,
|
|
519
|
+
id="missing-target-version",
|
|
520
|
+
),
|
|
521
|
+
pytest.param(
|
|
522
|
+
'[tool.ruff]\ntarget-version = "py39"\n',
|
|
523
|
+
False,
|
|
524
|
+
None,
|
|
525
|
+
id="missing-requires-python",
|
|
526
|
+
),
|
|
527
|
+
pytest.param(
|
|
528
|
+
'[project]\nrequires-python = "foo"\n\n[tool.ruff]\ntarget-version = "py310"\n',
|
|
529
|
+
False,
|
|
530
|
+
None,
|
|
531
|
+
id="unparsable-requires-python",
|
|
532
|
+
),
|
|
533
|
+
pytest.param(
|
|
534
|
+
'[project]\nrequires-python = ">=3.10"\n\n[tool.ruff]\ntarget-version = "3.10"\n',
|
|
535
|
+
False,
|
|
536
|
+
None,
|
|
537
|
+
id="unparsable-target-version",
|
|
538
|
+
),
|
|
539
|
+
pytest.param(
|
|
540
|
+
'[project]\nrequires-python = "==3.11.*,>=3.8"\n'
|
|
541
|
+
'\n[tool.ruff]\ntarget-version = "py39"\n',
|
|
542
|
+
False,
|
|
543
|
+
None,
|
|
544
|
+
id="multiple-specifiers-ok",
|
|
545
|
+
),
|
|
546
|
+
pytest.param(
|
|
547
|
+
'[project]\nrequires-python = ">=3.10, <4"\n\n[tool.ruff]\ntarget-version = "py39"\n',
|
|
548
|
+
True,
|
|
549
|
+
"Version mismatch",
|
|
550
|
+
id="multiple-specifiers-warn",
|
|
551
|
+
),
|
|
552
|
+
],
|
|
553
|
+
)
|
|
554
|
+
def test_version_consistency_cases(
|
|
555
|
+
caplog: pytest.LogCaptureFixture,
|
|
556
|
+
toml_content: str,
|
|
557
|
+
expected_warn: bool,
|
|
558
|
+
expected_msg: str | None,
|
|
559
|
+
) -> None:
|
|
560
|
+
"""Parametrized test for Python version consistency validation."""
|
|
561
|
+
doc = tomlkit.parse(toml_content)
|
|
562
|
+
|
|
563
|
+
with caplog.at_level(logging.WARNING, logger="ruff_sync.validation"):
|
|
564
|
+
result = check_python_version_consistency(doc)
|
|
565
|
+
|
|
566
|
+
# All these cases should return True (warnings only)
|
|
567
|
+
assert result is True
|
|
568
|
+
if expected_warn:
|
|
569
|
+
assert expected_msg is not None
|
|
570
|
+
assert expected_msg in caplog.text
|
|
571
|
+
else:
|
|
572
|
+
assert "Version mismatch" not in caplog.text
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
def test_version_consistency_skipped_for_ruff_toml(caplog: pytest.LogCaptureFixture) -> None:
|
|
576
|
+
"""Standalone ruff.toml files lack [project], so the check should be skipped."""
|
|
577
|
+
doc = tomlkit.parse("target-version = 'py39'\n")
|
|
578
|
+
# validate_merged_config skips the check if is_ruff_toml=True
|
|
579
|
+
with caplog.at_level(logging.WARNING, logger="ruff_sync.validation"):
|
|
580
|
+
result = validate_merged_config(doc, is_ruff_toml=True)
|
|
581
|
+
|
|
582
|
+
assert result is True
|
|
583
|
+
assert "Version mismatch" not in caplog.text
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
@pytest.mark.parametrize(
|
|
587
|
+
"toml_content, expected_suffix",
|
|
588
|
+
[
|
|
589
|
+
pytest.param(
|
|
590
|
+
"",
|
|
591
|
+
"missing [tool.ruff] target-version, [project] requires-python.",
|
|
592
|
+
id="missing-both",
|
|
593
|
+
),
|
|
594
|
+
pytest.param(
|
|
595
|
+
'[project]\nrequires-python = ">=3.10"\n',
|
|
596
|
+
"missing [tool.ruff] target-version.",
|
|
597
|
+
id="missing-target",
|
|
598
|
+
),
|
|
599
|
+
pytest.param(
|
|
600
|
+
'[tool.ruff]\ntarget-version = "py310"\n',
|
|
601
|
+
"missing [project] requires-python.",
|
|
602
|
+
id="missing-requires",
|
|
603
|
+
),
|
|
604
|
+
],
|
|
605
|
+
)
|
|
606
|
+
def test_version_consistency_logs_skip_decision(
|
|
607
|
+
caplog: pytest.LogCaptureFixture, toml_content: str, expected_suffix: str
|
|
608
|
+
) -> None:
|
|
609
|
+
"""It should log a warning message when skipping due to missing version keys."""
|
|
610
|
+
doc = tomlkit.parse(toml_content)
|
|
611
|
+
with caplog.at_level(logging.WARNING, logger="ruff_sync.validation"):
|
|
612
|
+
check_python_version_consistency(doc)
|
|
613
|
+
|
|
614
|
+
expected_msg = f"Skipping Python version consistency check: {expected_suffix}"
|
|
615
|
+
assert expected_msg in caplog.text
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
def test_version_consistency_skipped_when_excluded(caplog: pytest.LogCaptureFixture) -> None:
|
|
619
|
+
"""It should log a specific warning when target-version is explicitly excluded."""
|
|
620
|
+
# mismatch that would normally warn
|
|
621
|
+
toml_content = '[project]\nrequires-python = ">=3.10"\n\n[tool.ruff]\ntarget-version = "py39"\n'
|
|
622
|
+
doc = tomlkit.parse(toml_content)
|
|
623
|
+
|
|
624
|
+
with caplog.at_level(logging.WARNING, logger="ruff_sync.validation"):
|
|
625
|
+
# Case 1: excluded via 'target-version'
|
|
626
|
+
result = check_python_version_consistency(doc, exclude=("target-version",))
|
|
627
|
+
assert result is True
|
|
628
|
+
assert (
|
|
629
|
+
"Skipping Python version consistency check: 'target-version' is "
|
|
630
|
+
"excluded in [tool.ruff-sync]."
|
|
631
|
+
) in caplog.text
|
|
632
|
+
|
|
633
|
+
caplog.clear()
|
|
634
|
+
|
|
635
|
+
# Case 2: excluded via 'tool.ruff.target-version'
|
|
636
|
+
result = check_python_version_consistency(doc, exclude=("tool.ruff.target-version",))
|
|
637
|
+
assert result is True
|
|
638
|
+
assert (
|
|
639
|
+
"Skipping Python version consistency check: 'target-version' is "
|
|
640
|
+
"excluded in [tool.ruff-sync]."
|
|
641
|
+
) in caplog.text
|
|
642
|
+
|
|
643
|
+
|
|
644
|
+
def test_strict_mode_fails_on_version_mismatch(caplog: pytest.LogCaptureFixture) -> None:
|
|
645
|
+
"""In strict mode, a version mismatch should cause validation to fail."""
|
|
646
|
+
doc = tomlkit.parse(
|
|
647
|
+
'[project]\nrequires-python = ">=3.10"\n\n[tool.ruff]\ntarget-version = "py39"\n'
|
|
648
|
+
)
|
|
649
|
+
with caplog.at_level(logging.ERROR, logger="ruff_sync.validation"):
|
|
650
|
+
result = validate_merged_config(doc, strict=True)
|
|
651
|
+
|
|
652
|
+
assert result is False
|
|
653
|
+
assert "Version mismatch" in caplog.text
|
|
654
|
+
|
|
655
|
+
|
|
494
656
|
if __name__ == "__main__":
|
|
495
657
|
pytest.main([__file__, "-vv"])
|
|
File without changes
|
|
File without changes
|
{ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/decisions/0001-type-refactoring-strategy.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/mkdocs-generation/templates/index.md
RENAMED
|
File without changes
|
{ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/mkdocs-generation/templates/mkdocs.yml
RENAMED
|
File without changes
|
{ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/release-notes-generation/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/skill-creator/references/quickstart.md
RENAMED
|
File without changes
|
{ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/skill-creator/references/sources.md
RENAMED
|
File without changes
|
|
File without changes
|
{ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/skill-creator/scripts/scaffold_skill.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/textual/examples/reactive_example.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/references/generics.md
RENAMED
|
File without changes
|
{ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/references/naming.md
RENAMED
|
File without changes
|
|
File without changes
|
{ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/references/quickstart.md
RENAMED
|
File without changes
|
|
File without changes
|
{ruff_sync-0.1.6.dev1 → ruff_sync-0.1.6.dev2}/.agents/skills/type-checking/scripts/audit_types.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|