ruff-sync 0.0.1.dev3__tar.gz → 0.0.2.dev0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/.github/dependabot.yml +1 -1
  2. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/.github/workflows/ci.yaml +1 -0
  3. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/PKG-INFO +84 -8
  4. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/README.md +83 -7
  5. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/pyproject.toml +2 -1
  6. ruff_sync-0.0.2.dev0/ruff_sync.py +536 -0
  7. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/scripts/dogfood.sh +1 -1
  8. ruff_sync-0.0.2.dev0/scripts/dogfood_check.sh +48 -0
  9. ruff_sync-0.0.2.dev0/tasks.py +199 -0
  10. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/lifecycle_tomls/no_ruff_cfg_final.toml +4 -2
  11. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/lifecycle_tomls/standard_final.toml +4 -2
  12. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/test_basic.py +132 -10
  13. ruff_sync-0.0.2.dev0/tests/test_check.py +223 -0
  14. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/test_e2e.py +65 -4
  15. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/test_project.py +12 -1
  16. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/test_whitespace.py +44 -0
  17. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/uv.lock +3 -1
  18. ruff_sync-0.0.1.dev3/ruff_sync.py +0 -301
  19. ruff_sync-0.0.1.dev3/tasks.py +0 -90
  20. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/.agents/TESTING.md +0 -0
  21. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/.agents/workflows/add-test-case.md +0 -0
  22. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/.github/workflows/complexity.yaml +0 -0
  23. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/.gitignore +0 -0
  24. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/.pre-commit-config.yaml +0 -0
  25. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/AGENTS.md +0 -0
  26. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/LICENSE.md +0 -0
  27. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/codecov.yml +0 -0
  28. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/ruff_sync_banner.png +0 -0
  29. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/__init__.py +0 -0
  30. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/lifecycle_tomls/no_changes_final.toml +0 -0
  31. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/lifecycle_tomls/no_changes_initial.toml +0 -0
  32. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/lifecycle_tomls/no_changes_upstream.toml +0 -0
  33. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/lifecycle_tomls/no_dotted_keys_final.toml +0 -0
  34. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/lifecycle_tomls/no_dotted_keys_initial.toml +0 -0
  35. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/lifecycle_tomls/no_dotted_keys_upstream.toml +0 -0
  36. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/lifecycle_tomls/no_ruff_cfg_initial.toml +0 -0
  37. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/lifecycle_tomls/no_ruff_cfg_upstream.toml +0 -0
  38. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/lifecycle_tomls/standard_initial.toml +0 -0
  39. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/lifecycle_tomls/standard_upstream.toml +0 -0
  40. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/ruff.toml +0 -0
  41. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/test_corner_cases.py +0 -0
  42. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/test_toml_operations.py +0 -0
  43. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/w_ruff_sync_cfg/pyproject.toml +0 -0
  44. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/wo_ruff_cfg/pyproject.toml +0 -0
  45. {ruff_sync-0.0.1.dev3 → ruff_sync-0.0.2.dev0}/tests/wo_ruff_sync_cfg/pyproject.toml +0 -0
@@ -3,7 +3,7 @@
3
3
 
4
4
  version: 2
5
5
  updates:
6
- - package-ecosystem: "pip" # Documentation: For package managers such as pipenv and poetry, you need to use the pip YAML value.
6
+ - package-ecosystem: "uv"
7
7
  directory: "/" # Location of package manifests
8
8
  schedule:
9
9
  interval: daily
@@ -33,6 +33,7 @@ jobs:
33
33
 
34
34
  tests:
35
35
  strategy:
36
+ fail-fast: ${{ github.event.pull_request.draft == true }}
36
37
  matrix:
37
38
  python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
38
39
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ruff-sync
3
- Version: 0.0.1.dev3
3
+ Version: 0.0.2.dev0
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://github.com/Kilo59/ruff-sync#readme
@@ -52,6 +52,7 @@ Description-Content-Type: text/markdown
52
52
  - [Install](#install)
53
53
  - [Usage](#usage)
54
54
  - [Key Features](#key-features)
55
+ - [CI Integration](#ci-integration)
55
56
  - [Configuration](#configuration)
56
57
  - [Contributing](#contributing)
57
58
  - [License](#license)
@@ -142,34 +143,100 @@ uv tool install git+https://github.com/Kilo59/ruff-sync
142
143
  # Sync from a GitHub URL (blob URLs are auto-converted to raw)
143
144
  ruff-sync https://github.com/my-org/standards/blob/main/pyproject.toml
144
145
 
146
+ # Once configured in pyproject.toml (see below), simply run:
147
+ ruff-sync
148
+
145
149
  # Sync into a specific project directory
146
- ruff-sync https://github.com/my-org/standards/blob/main/pyproject.toml --source ./my-project
150
+ ruff-sync --source ./my-project
147
151
 
148
152
  # Exclude specific sections from being overwritten using dotted paths
149
- ruff-sync https://github.com/my-org/standards/blob/main/pyproject.toml --exclude lint.per-file-ignores lint.ignore
153
+ ruff-sync --exclude lint.per-file-ignores lint.ignore
154
+
155
+ # Check if your local config is in sync (useful in CI)
156
+ ruff-sync check https://github.com/my-org/standards/blob/main/pyproject.toml
157
+
158
+ # Semantic check — ignore cosmetic differences like comments and whitespace
159
+ ruff-sync check --semantic
150
160
  ```
151
161
 
152
162
  ### CLI Reference
153
163
 
164
+ #### `ruff-sync`
165
+
166
+ ```
167
+ usage: ruff-sync [-h] [--source SOURCE] [--exclude EXCLUDE [EXCLUDE ...]] [-v] [upstream]
168
+
169
+ positional arguments:
170
+ upstream The URL to download the pyproject.toml file from.
171
+ Optional if defined in [tool.ruff-sync]
172
+
173
+ optional arguments:
174
+ -h, --help show this help message and exit
175
+ --source SOURCE The directory or file to sync. Default: .
176
+ --exclude EXCLUDE [EXCLUDE ...]
177
+ Exclude certain ruff config keys. Default: lint.per-file-ignores
178
+ -v, --verbose Increase verbosity. -v for INFO, -vv for DEBUG.
179
+ ```
180
+
181
+ #### `ruff-sync check`
182
+
154
183
  ```
155
- usage: ruff-sync [-h] [--source SOURCE] [--exclude EXCLUDE [EXCLUDE ...]] upstream
184
+ usage: ruff-sync check [-h] [--source SOURCE] [--exclude EXCLUDE [EXCLUDE ...]] [--semantic] [--no-diff] [-v] [upstream]
156
185
 
157
186
  positional arguments:
158
187
  upstream The URL to download the pyproject.toml file from.
188
+ Optional if defined in [tool.ruff-sync]
159
189
 
160
190
  optional arguments:
161
191
  -h, --help show this help message and exit
162
- --source SOURCE The directory to sync the pyproject.toml file to. Default: .
192
+ --source SOURCE The directory or file to check. Default: .
163
193
  --exclude EXCLUDE [EXCLUDE ...]
164
- Exclude certain ruff configs. Default: lint.per-file-ignores
194
+ Exclude certain ruff config keys.
195
+ --semantic Ignore cosmetic differences (whitespace, comments);
196
+ only fail on actual value changes.
197
+ --no-diff Suppress the diff output.
198
+ -v, --verbose Increase verbosity. -v for INFO, -vv for DEBUG.
165
199
  ```
166
200
 
201
+ Exits **0** if in sync, **1** if out of sync.
202
+
167
203
  ## Key Features
168
204
 
169
205
  - **Format-preserving merges** — Uses [tomlkit](https://github.com/sdispater/tomlkit) under the hood, so your comments, whitespace, and TOML structure are preserved. No reformatting surprises.
170
206
  - **GitHub URL support** — Paste a GitHub blob URL and it will automatically convert it to the raw content URL.
171
207
  - **Selective exclusions** — Keep project-specific overrides (like `target-version`) from being clobbered by the upstream config.
172
208
  - **Works with any host** — GitHub, GitLab, Bitbucket, or any raw URL that serves a `pyproject.toml`.
209
+ - **CI-ready `check` command** — Verify that your local config is in sync without modifying anything. Exits 1 if out of sync, making it perfect for pre-merge gates.
210
+ - **Semantic mode** — Use `--semantic` to ignore cosmetic differences (comments, whitespace) and only fail on real value changes.
211
+
212
+ ## CI Integration
213
+
214
+ The `check` command is designed for use in CI pipelines. Add it as a step to catch config drift before it merges:
215
+
216
+ ```yaml
217
+ # .github/workflows/ci.yaml
218
+ - name: Check ruff config is in sync
219
+ run: |
220
+ ruff-sync check --semantic
221
+ ```
222
+
223
+ With `--semantic`, minor reformatting of your local file won't cause a false positive — only actual rule or value differences will fail the check.
224
+
225
+ To see exactly what's drifted, omit `--no-diff` (the default) and the output will include a unified diff:
226
+
227
+ ```console
228
+ $ ruff-sync check --semantic
229
+ 🔍 Checking Ruff sync status...
230
+ ❌ Ruff configuration at pyproject.toml is out of sync!
231
+ --- local (semantic)
232
+ +++ upstream (semantic)
233
+ @@ -5,6 +5,7 @@
234
+ "select": [
235
+ + "PERF",
236
+ "RUF",
237
+ ...
238
+ ]
239
+ ```
173
240
 
174
241
  ## Configuration
175
242
 
@@ -177,6 +244,9 @@ You can configure `ruff-sync` itself in your `pyproject.toml`:
177
244
 
178
245
  ```toml
179
246
  [tool.ruff-sync]
247
+ # The source of truth for your ruff configuration
248
+ upstream = "https://github.com/my-org/standards/blob/main/pyproject.toml"
249
+
180
250
  # Use simple names for top-level keys, and dotted paths for nested keys
181
251
  exclude = [
182
252
  "target-version", # A top-level key under [tool.ruff]
@@ -225,9 +295,15 @@ uv run pytest -vv # test
225
295
 
226
296
  ## Dogfooding
227
297
 
228
- To see `ruff-sync` in action on a complex, real-world configuration, you can "dogfood" it by syncing this project's own `pyproject.toml` with a large upstream config like Pydantic's.
298
+ To see `ruff-sync` in action, you can "dogfood" it on this project's own config.
299
+
300
+ **Check if this project is in sync with its upstream:**
301
+
302
+ ```console
303
+ ./scripts/dogfood_check.sh
304
+ ```
229
305
 
230
- We've provided a script to make this easy:
306
+ **Or sync from a large upstream like Pydantic's config:**
231
307
 
232
308
  ```console
233
309
  ./scripts/dogfood.sh
@@ -22,6 +22,7 @@
22
22
  - [Install](#install)
23
23
  - [Usage](#usage)
24
24
  - [Key Features](#key-features)
25
+ - [CI Integration](#ci-integration)
25
26
  - [Configuration](#configuration)
26
27
  - [Contributing](#contributing)
27
28
  - [License](#license)
@@ -112,34 +113,100 @@ uv tool install git+https://github.com/Kilo59/ruff-sync
112
113
  # Sync from a GitHub URL (blob URLs are auto-converted to raw)
113
114
  ruff-sync https://github.com/my-org/standards/blob/main/pyproject.toml
114
115
 
116
+ # Once configured in pyproject.toml (see below), simply run:
117
+ ruff-sync
118
+
115
119
  # Sync into a specific project directory
116
- ruff-sync https://github.com/my-org/standards/blob/main/pyproject.toml --source ./my-project
120
+ ruff-sync --source ./my-project
117
121
 
118
122
  # Exclude specific sections from being overwritten using dotted paths
119
- ruff-sync https://github.com/my-org/standards/blob/main/pyproject.toml --exclude lint.per-file-ignores lint.ignore
123
+ ruff-sync --exclude lint.per-file-ignores lint.ignore
124
+
125
+ # Check if your local config is in sync (useful in CI)
126
+ ruff-sync check https://github.com/my-org/standards/blob/main/pyproject.toml
127
+
128
+ # Semantic check — ignore cosmetic differences like comments and whitespace
129
+ ruff-sync check --semantic
120
130
  ```
121
131
 
122
132
  ### CLI Reference
123
133
 
134
+ #### `ruff-sync`
135
+
136
+ ```
137
+ usage: ruff-sync [-h] [--source SOURCE] [--exclude EXCLUDE [EXCLUDE ...]] [-v] [upstream]
138
+
139
+ positional arguments:
140
+ upstream The URL to download the pyproject.toml file from.
141
+ Optional if defined in [tool.ruff-sync]
142
+
143
+ optional arguments:
144
+ -h, --help show this help message and exit
145
+ --source SOURCE The directory or file to sync. Default: .
146
+ --exclude EXCLUDE [EXCLUDE ...]
147
+ Exclude certain ruff config keys. Default: lint.per-file-ignores
148
+ -v, --verbose Increase verbosity. -v for INFO, -vv for DEBUG.
149
+ ```
150
+
151
+ #### `ruff-sync check`
152
+
124
153
  ```
125
- usage: ruff-sync [-h] [--source SOURCE] [--exclude EXCLUDE [EXCLUDE ...]] upstream
154
+ usage: ruff-sync check [-h] [--source SOURCE] [--exclude EXCLUDE [EXCLUDE ...]] [--semantic] [--no-diff] [-v] [upstream]
126
155
 
127
156
  positional arguments:
128
157
  upstream The URL to download the pyproject.toml file from.
158
+ Optional if defined in [tool.ruff-sync]
129
159
 
130
160
  optional arguments:
131
161
  -h, --help show this help message and exit
132
- --source SOURCE The directory to sync the pyproject.toml file to. Default: .
162
+ --source SOURCE The directory or file to check. Default: .
133
163
  --exclude EXCLUDE [EXCLUDE ...]
134
- Exclude certain ruff configs. Default: lint.per-file-ignores
164
+ Exclude certain ruff config keys.
165
+ --semantic Ignore cosmetic differences (whitespace, comments);
166
+ only fail on actual value changes.
167
+ --no-diff Suppress the diff output.
168
+ -v, --verbose Increase verbosity. -v for INFO, -vv for DEBUG.
135
169
  ```
136
170
 
171
+ Exits **0** if in sync, **1** if out of sync.
172
+
137
173
  ## Key Features
138
174
 
139
175
  - **Format-preserving merges** — Uses [tomlkit](https://github.com/sdispater/tomlkit) under the hood, so your comments, whitespace, and TOML structure are preserved. No reformatting surprises.
140
176
  - **GitHub URL support** — Paste a GitHub blob URL and it will automatically convert it to the raw content URL.
141
177
  - **Selective exclusions** — Keep project-specific overrides (like `target-version`) from being clobbered by the upstream config.
142
178
  - **Works with any host** — GitHub, GitLab, Bitbucket, or any raw URL that serves a `pyproject.toml`.
179
+ - **CI-ready `check` command** — Verify that your local config is in sync without modifying anything. Exits 1 if out of sync, making it perfect for pre-merge gates.
180
+ - **Semantic mode** — Use `--semantic` to ignore cosmetic differences (comments, whitespace) and only fail on real value changes.
181
+
182
+ ## CI Integration
183
+
184
+ The `check` command is designed for use in CI pipelines. Add it as a step to catch config drift before it merges:
185
+
186
+ ```yaml
187
+ # .github/workflows/ci.yaml
188
+ - name: Check ruff config is in sync
189
+ run: |
190
+ ruff-sync check --semantic
191
+ ```
192
+
193
+ With `--semantic`, minor reformatting of your local file won't cause a false positive — only actual rule or value differences will fail the check.
194
+
195
+ To see exactly what's drifted, omit `--no-diff` (the default) and the output will include a unified diff:
196
+
197
+ ```console
198
+ $ ruff-sync check --semantic
199
+ 🔍 Checking Ruff sync status...
200
+ ❌ Ruff configuration at pyproject.toml is out of sync!
201
+ --- local (semantic)
202
+ +++ upstream (semantic)
203
+ @@ -5,6 +5,7 @@
204
+ "select": [
205
+ + "PERF",
206
+ "RUF",
207
+ ...
208
+ ]
209
+ ```
143
210
 
144
211
  ## Configuration
145
212
 
@@ -147,6 +214,9 @@ You can configure `ruff-sync` itself in your `pyproject.toml`:
147
214
 
148
215
  ```toml
149
216
  [tool.ruff-sync]
217
+ # The source of truth for your ruff configuration
218
+ upstream = "https://github.com/my-org/standards/blob/main/pyproject.toml"
219
+
150
220
  # Use simple names for top-level keys, and dotted paths for nested keys
151
221
  exclude = [
152
222
  "target-version", # A top-level key under [tool.ruff]
@@ -195,9 +265,15 @@ uv run pytest -vv # test
195
265
 
196
266
  ## Dogfooding
197
267
 
198
- To see `ruff-sync` in action on a complex, real-world configuration, you can "dogfood" it by syncing this project's own `pyproject.toml` with a large upstream config like Pydantic's.
268
+ To see `ruff-sync` in action, you can "dogfood" it on this project's own config.
269
+
270
+ **Check if this project is in sync with its upstream:**
271
+
272
+ ```console
273
+ ./scripts/dogfood_check.sh
274
+ ```
199
275
 
200
- We've provided a script to make this easy:
276
+ **Or sync from a large upstream like Pydantic's config:**
201
277
 
202
278
  ```console
203
279
  ./scripts/dogfood.sh
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ruff-sync"
3
- version = "0.0.1.dev3"
3
+ version = "0.0.2.dev0"
4
4
  description = "Synchronize Ruff linter configuration across projects"
5
5
  keywords = ["ruff", "linter", "config", "synchronize", "python", "linting", "automation", "tomlkit"]
6
6
  authors = [
@@ -43,6 +43,7 @@ dev = [
43
43
  "coverage>=7.4.4",
44
44
  "invoke>=2.2.0",
45
45
  "mypy>=1.10.0",
46
+ "packaging>=26.0",
46
47
  "pre-commit>=3.7.0",
47
48
  "pyfakefs>=5.4.1",
48
49
  "pytest>=8.0.0",