depkeeper 0.1.0.dev2__tar.gz → 0.1.1__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 (46) hide show
  1. depkeeper-0.1.1/PKG-INFO +474 -0
  2. depkeeper-0.1.1/README.md +417 -0
  3. {depkeeper-0.1.0.dev2 → depkeeper-0.1.1}/depkeeper/__init__.py +2 -3
  4. {depkeeper-0.1.0.dev2 → depkeeper-0.1.1}/depkeeper/__main__.py +3 -4
  5. depkeeper-0.1.1/depkeeper/__version__.py +11 -0
  6. {depkeeper-0.1.0.dev2 → depkeeper-0.1.1}/depkeeper/cli.py +31 -14
  7. depkeeper-0.1.1/depkeeper/commands/__init__.py +7 -0
  8. depkeeper-0.1.1/depkeeper/commands/check.py +625 -0
  9. depkeeper-0.1.1/depkeeper/commands/update.py +959 -0
  10. depkeeper-0.1.1/depkeeper/config.py +307 -0
  11. {depkeeper-0.1.0.dev2 → depkeeper-0.1.1}/depkeeper/constants.py +57 -4
  12. {depkeeper-0.1.0.dev2 → depkeeper-0.1.1}/depkeeper/context.py +11 -7
  13. depkeeper-0.1.1/depkeeper/core/__init__.py +26 -0
  14. depkeeper-0.1.1/depkeeper/core/checker.py +505 -0
  15. depkeeper-0.1.1/depkeeper/core/data_store.py +766 -0
  16. depkeeper-0.1.1/depkeeper/core/dependency_analyzer.py +1273 -0
  17. depkeeper-0.1.1/depkeeper/core/parser.py +1095 -0
  18. {depkeeper-0.1.0.dev2 → depkeeper-0.1.1}/depkeeper/exceptions.py +33 -6
  19. depkeeper-0.1.1/depkeeper/models/__init__.py +22 -0
  20. depkeeper-0.1.1/depkeeper/models/conflict.py +164 -0
  21. depkeeper-0.1.1/depkeeper/models/package.py +365 -0
  22. depkeeper-0.1.1/depkeeper/models/requirement.py +207 -0
  23. depkeeper-0.1.1/depkeeper/utils/__init__.py +122 -0
  24. depkeeper-0.1.1/depkeeper/utils/console.py +301 -0
  25. depkeeper-0.1.1/depkeeper/utils/filesystem.py +506 -0
  26. depkeeper-0.1.1/depkeeper/utils/http.py +384 -0
  27. depkeeper-0.1.1/depkeeper/utils/logger.py +167 -0
  28. depkeeper-0.1.1/depkeeper/utils/naming.py +55 -0
  29. depkeeper-0.1.1/depkeeper/utils/version_utils.py +393 -0
  30. depkeeper-0.1.1/depkeeper.egg-info/PKG-INFO +474 -0
  31. depkeeper-0.1.1/depkeeper.egg-info/SOURCES.txt +39 -0
  32. {depkeeper-0.1.0.dev2 → depkeeper-0.1.1}/depkeeper.egg-info/requires.txt +8 -3
  33. {depkeeper-0.1.0.dev2 → depkeeper-0.1.1}/pyproject.toml +20 -9
  34. depkeeper-0.1.1/tests/test_config.py +400 -0
  35. depkeeper-0.1.1/tests/test_context.py +122 -0
  36. depkeeper-0.1.1/tests/test_main.py +129 -0
  37. depkeeper-0.1.0.dev2/PKG-INFO +0 -218
  38. depkeeper-0.1.0.dev2/README.md +0 -167
  39. depkeeper-0.1.0.dev2/depkeeper/__version__.py +0 -12
  40. depkeeper-0.1.0.dev2/depkeeper.egg-info/PKG-INFO +0 -218
  41. depkeeper-0.1.0.dev2/depkeeper.egg-info/SOURCES.txt +0 -16
  42. {depkeeper-0.1.0.dev2 → depkeeper-0.1.1}/LICENSE +0 -0
  43. {depkeeper-0.1.0.dev2 → depkeeper-0.1.1}/depkeeper.egg-info/dependency_links.txt +0 -0
  44. {depkeeper-0.1.0.dev2 → depkeeper-0.1.1}/depkeeper.egg-info/entry_points.txt +0 -0
  45. {depkeeper-0.1.0.dev2 → depkeeper-0.1.1}/depkeeper.egg-info/top_level.txt +0 -0
  46. {depkeeper-0.1.0.dev2 → depkeeper-0.1.1}/setup.cfg +0 -0
@@ -0,0 +1,474 @@
1
+ Metadata-Version: 2.4
2
+ Name: depkeeper
3
+ Version: 0.1.1
4
+ Summary: Modern Python dependency management for requirements.txt files
5
+ Author: Rahul Kaushal
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/rahulkaushal04/depkeeper
8
+ Project-URL: Documentation, https://rahulkaushal04.github.io/depkeeper/
9
+ Project-URL: Repository, https://github.com/rahulkaushal04/depkeeper
10
+ Project-URL: Bug Tracker, https://github.com/rahulkaushal04/depkeeper/issues
11
+ Project-URL: Changelog, https://github.com/rahulkaushal04/depkeeper/blob/main/CHANGELOG.md
12
+ Keywords: dependencies,requirements,pip,package-management,security,updates
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: Apache Software License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Programming Language :: Python :: 3.8
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Classifier: Topic :: System :: Software Distribution
25
+ Requires-Python: >=3.8
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Requires-Dist: click>=8.1.8
29
+ Requires-Dist: packaging>=23.2
30
+ Requires-Dist: httpx[http2]>=0.24.1
31
+ Requires-Dist: rich>=13.9.4
32
+ Requires-Dist: tomli>=2.4.0
33
+ Provides-Extra: dev
34
+ Requires-Dist: pytest>=7.4.4; extra == "dev"
35
+ Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
36
+ Requires-Dist: pytest-asyncio>=0.23.8; extra == "dev"
37
+ Requires-Dist: pytest-mock>=3.14.1; extra == "dev"
38
+ Requires-Dist: pytest-httpx>=0.22.0; extra == "dev"
39
+ Requires-Dist: mypy>=1.14.1; extra == "dev"
40
+ Requires-Dist: types-setuptools; extra == "dev"
41
+ Requires-Dist: pre-commit>=3.5.0; extra == "dev"
42
+ Provides-Extra: test
43
+ Requires-Dist: pytest>=7.4.4; extra == "test"
44
+ Requires-Dist: pytest-cov>=4.1.0; extra == "test"
45
+ Requires-Dist: pytest-asyncio>=0.23.8; extra == "test"
46
+ Requires-Dist: pytest-mock>=3.14.1; extra == "test"
47
+ Requires-Dist: pytest-httpx>=0.22.0; extra == "test"
48
+ Provides-Extra: docs
49
+ Requires-Dist: mkdocs<2.0,>=1.6.1; extra == "docs"
50
+ Requires-Dist: mkdocs-material<10.0,>=9.7.1; extra == "docs"
51
+ Requires-Dist: mkdocstrings[python]<2.0,>=0.26.1; extra == "docs"
52
+ Requires-Dist: pymdown-extensions<11.0,>=10.15; extra == "docs"
53
+ Requires-Dist: mkdocs-minify-plugin<1.0,>=0.8.0; extra == "docs"
54
+ Requires-Dist: mike<3.0,>=2.2.0; extra == "docs"
55
+ Requires-Dist: black>=24.10.0; extra == "docs"
56
+ Dynamic: license-file
57
+
58
+ # depkeeper
59
+
60
+ [![Tests](https://github.com/rahulkaushal04/depkeeper/actions/workflows/tests.yml/badge.svg)](https://github.com/rahulkaushal04/depkeeper/actions/workflows/tests.yml)
61
+ [![Coverage](https://codecov.io/gh/rahulkaushal04/depkeeper/branch/main/graph/badge.svg)](https://codecov.io/gh/rahulkaushal04/depkeeper)
62
+ [![PyPI](https://img.shields.io/pypi/v/depkeeper.svg)](https://pypi.org/project/depkeeper/)
63
+ [![Python versions](https://img.shields.io/pypi/pyversions/depkeeper.svg)](https://pypi.org/project/depkeeper/)
64
+ [![License: Apache-2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)
65
+ [![Docs](https://img.shields.io/badge/docs-github.io-blue)](https://rahulkaushal04.github.io/depkeeper/)
66
+
67
+ **Safe, conflict-aware dependency updates for pip requirements files.**
68
+
69
+ depkeeper analyses `requirements.txt`-style files, computes a safe upgrade target for every
70
+ requirement, cross-validates those targets against each other, and rewrites the file in place —
71
+ without discarding the constraints you authored.
72
+
73
+ It is a single-purpose CLI. It does not manage virtual environments, install packages, replace
74
+ `pip`, or introduce a lock file format.
75
+
76
+ ---
77
+
78
+ ## Contents
79
+
80
+ - [Why depkeeper](#why-depkeeper) · [What it guarantees](#what-it-guarantees)
81
+ - [Install](#install) · [Quick start](#quick-start) · [Commands](#commands)
82
+ - [Configuration](#configuration) · [Common workflows](#common-workflows)
83
+ - [Architecture](#architecture) · [Limitations](#limitations)
84
+ - [Troubleshooting](#troubleshooting) · [Documentation](#documentation) · [Contributing](#contributing)
85
+
86
+ ---
87
+
88
+ ## Why depkeeper
89
+
90
+ `pip list --outdated` reports the **latest** version, which is frequently a major release that
91
+ will break your build. Lock-file tools solve this properly but require adopting a new workflow and
92
+ file format.
93
+
94
+ depkeeper fills the gap. It answers one question, precisely:
95
+
96
+ > What is the largest upgrade I can take for each requirement **without** crossing a major
97
+ > version, **without** breaking Python compatibility, **without** violating the constraints I
98
+ > declared, and **without** conflicting with the other packages in my file?
99
+
100
+ Then it applies the answer to the file you already have.
101
+
102
+ | | pip | pip-tools | Poetry | depkeeper |
103
+ |---|---|---|---|---|
104
+ | Reports available updates | latest only | no | yes | yes, with a *safe* target |
105
+ | Enforces major-version boundaries | no | no | no | **yes** |
106
+ | Preserves your declared ranges on write | n/a | regenerates | rewrites | **yes** |
107
+ | Full transitive resolution | at install time | yes | yes | no — see [Limitations](#limitations) |
108
+ | Requires a new file format | no | `.in` files | `pyproject.toml` + lock | **no** |
109
+
110
+ ---
111
+
112
+ ## What it guarantees
113
+
114
+ These are enforced in code, not advisory:
115
+
116
+ | Guarantee | Meaning |
117
+ |---|---|
118
+ | **Major-version boundary** | A package on `1.x` is never moved to `2.x`. |
119
+ | **Python compatibility** | Releases whose `requires_python` excludes your interpreter are never proposed. |
120
+ | **Constraint preservation** | Upper bounds, exclusions and `~=` bands are preserved verbatim and never violated. |
121
+ | **No pre-releases** | Alpha/beta/rc versions are excluded from every candidate list. |
122
+ | **Atomic, reversible writes** | Multi-file updates are all-or-nothing, with rollback and optional backups. |
123
+ | **Hash integrity** | Updates that would strip `--hash` entries are refused unless explicitly allowed. |
124
+ | **Clean stdout** | `--format json` puts the payload on stdout and every diagnostic on stderr. |
125
+ | **Idempotency** | Re-running produces no change. Safe to run on a schedule. |
126
+
127
+ The trade-off is explicit: depkeeper is deliberately conservative. It will never propose the major
128
+ upgrade you eventually need.
129
+
130
+ ---
131
+
132
+ ## Install
133
+
134
+ ```bash
135
+ python -m pip install depkeeper # into the project's environment (recommended)
136
+ pipx install depkeeper # isolated global tool
137
+ ```
138
+
139
+ Requires **Python 3.8+**.
140
+
141
+ > [!IMPORTANT]
142
+ > depkeeper filters candidate versions against **the interpreter it runs on**, not your project's.
143
+ > Installing it on 3.8 while your service targets 3.12 makes recommendations silently
144
+ > conservative. Install it into the project environment, or use
145
+ > `pipx install --python python3.12 depkeeper`.
146
+
147
+ Verify:
148
+
149
+ ```bash
150
+ depkeeper --version # depkeeper 0.1.1
151
+ python -m depkeeper --help # equivalent module entry point
152
+ ```
153
+
154
+ ---
155
+
156
+ ## Quick start
157
+
158
+ Given this file:
159
+
160
+ ```text
161
+ requests==2.28.0
162
+ flask>=2.0,<2.3
163
+ celery[redis]>=5.0,<6.0
164
+ click~=8.0
165
+ certifi
166
+ urllib3==1.26.0
167
+ ```
168
+
169
+ **1. Inspect (read-only, never writes):**
170
+
171
+ ```console
172
+ $ depkeeper check
173
+ ┏━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━┓
174
+ ┃ Status ┃ Package ┃ Current ┃ Latest ┃ Recommended ┃ Update Type ┃ Conflicts ┃
175
+ ┡━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━┩
176
+ │ [OUTDATED] │ requests │ 2.28.0 │ 2.34.2 │ 2.34.2 │ minor │ - │
177
+ │ [OUTDATED] │ flask │ 2.0 │ 3.1.3 │ 2.2.5 │ minor │ - │
178
+ │ [OUTDATED] │ celery │ 5.0 │ 5.6.3 │ 5.6.3 │ minor │ - │
179
+ │ [OUTDATED] │ click │ 8.0 │ 8.4.2 │ 8.4.2 │ minor │ - │
180
+ │ [OK] │ certifi │ - │ 2026.7.22 │ - │ - │ - │
181
+ │ [OUTDATED] │ urllib3 │ 1.26.0 │ 2.7.0 │ 1.26.20 │ patch │ - │
182
+ └────────────┴──────────┴─────────┴───────────┴─────────────┴─────────────┴───────────┘
183
+ [WARNING] 5 package(s) have updates available
184
+ ```
185
+
186
+ **2. Preview the exact write:**
187
+
188
+ ```bash
189
+ depkeeper update --dry-run
190
+ ```
191
+
192
+ **3. Apply:**
193
+
194
+ ```console
195
+ $ depkeeper update --backup
196
+ Update 6 packages? (y, n) [y]: y
197
+ [OK] ✓ Successfully updated 6 package(s)
198
+ ```
199
+
200
+ ```text
201
+ requests==2.34.2
202
+ flask>=2.2.5,<2.3 # your <2.3 cap held — latest is 3.1.3
203
+ celery[redis]>=5.6.3,<6.0 # extra and upper bound preserved
204
+ click~=8.4 # compatible-release form preserved
205
+ certifi==2026.7.22 # unversioned requirement gained a pin
206
+ urllib3==1.26.20 # major boundary held — latest is 2.7.0
207
+ ```
208
+
209
+ **4. Verify — this step is not optional:**
210
+
211
+ ```bash
212
+ python -m pip install -r requirements.txt && pytest
213
+ ```
214
+
215
+ depkeeper validates the packages you declared against each other. It does not expand the
216
+ transitive graph, so `pip` remains the authority on whether the set installs.
217
+
218
+ ---
219
+
220
+ ## Commands
221
+
222
+ ### `depkeeper check [FILE]`
223
+
224
+ Read-only analysis. Never modifies the filesystem. Exits `0` on success regardless of findings.
225
+
226
+ | Option | Description |
227
+ |---|---|
228
+ | `--outdated-only` | Show only packages with an update or a conflict |
229
+ | `-f`, `--format table\|simple\|json` | Output format (default `table`) |
230
+ | `--strict-version-matching` | Only a sole `==` pin counts as a current version |
231
+ | `--check-conflicts` / `--no-check-conflicts` | Cross-package conflict resolution (default on) |
232
+
233
+ ### `depkeeper update [FILE]`
234
+
235
+ Applies recommended versions in place.
236
+
237
+ | Option | Description |
238
+ |---|---|
239
+ | `--dry-run` | Run the full pipeline, print the plan, write nothing |
240
+ | `-y`, `--yes` | Skip the confirmation prompt |
241
+ | `--backup` | Timestamped backup of **every** affected file before writing |
242
+ | `--pin` | Replace every specifier with an exact `==` pin |
243
+ | `--allow-hash-removal` | Permit updating `--hash`-pinned requirements (removes the digests) |
244
+ | `-p`, `--packages NAME` | Restrict to specific packages (repeatable) |
245
+ | `--strict-version-matching` | As above |
246
+ | `--check-conflicts` / `--no-check-conflicts` | As above |
247
+
248
+ ### Global options
249
+
250
+ `-c/--config PATH` · `-v` / `-vv` (INFO / DEBUG, always on stderr) · `--color/--no-color` ·
251
+ `--version` · `-h/--help`
252
+
253
+ Global options must precede the subcommand: `depkeeper -v check`, not `depkeeper check -v`.
254
+
255
+ Full specification: **[CLI reference](https://rahulkaushal04.github.io/depkeeper/reference/cli-commands/)**.
256
+
257
+ ### Exit codes
258
+
259
+ | Code | Meaning |
260
+ |---|---|
261
+ | `0` | Success — **including** "updates are available" |
262
+ | `1` | Application error (parse, config, write, refused hash removal) |
263
+ | `2` | Usage error (unknown option, missing file) |
264
+ | `130` | Interrupted (`Ctrl+C`) |
265
+
266
+ Gate automation on the JSON payload, never on `check`'s exit code.
267
+
268
+ ---
269
+
270
+ ## Configuration
271
+
272
+ Two settings are persistable, in `depkeeper.toml` or `pyproject.toml`. Everything else is a
273
+ per-invocation flag, deliberately — options that change what gets *written* stay visible in the
274
+ command line.
275
+
276
+ ```toml
277
+ # depkeeper.toml
278
+ [depkeeper]
279
+ check_conflicts = true # cross-package conflict resolution
280
+ strict_version_matching = false # treat only `==` as a current version
281
+ ```
282
+
283
+ ```toml
284
+ # pyproject.toml
285
+ [tool.depkeeper]
286
+ check_conflicts = true
287
+ strict_version_matching = false
288
+ ```
289
+
290
+ Precedence: **defaults < config file < CLI flag**. Unknown keys and wrong types are hard errors.
291
+ Discovery is limited to the current working directory (not recursive).
292
+
293
+ Environment: `DEPKEEPER_CONFIG`, `DEPKEEPER_COLOR`, `NO_COLOR`, `CI`, plus `httpx`'s
294
+ `HTTPS_PROXY` / `SSL_CERT_FILE`.
295
+
296
+ ---
297
+
298
+ ## Common workflows
299
+
300
+ **Daily**
301
+
302
+ ```bash
303
+ depkeeper check --outdated-only
304
+ depkeeper update --dry-run
305
+ depkeeper update --backup && pip install -r requirements.txt && pytest
306
+ ```
307
+
308
+ **One package at a time** (keeps regressions bisectable)
309
+
310
+ ```bash
311
+ depkeeper update -p django -y && pytest
312
+ ```
313
+
314
+ **Application release — freeze to exact versions**
315
+
316
+ ```bash
317
+ depkeeper update --pin --backup
318
+ ```
319
+
320
+ **CI drift report** — stdout stays parseable even with `-v`
321
+
322
+ ```bash
323
+ depkeeper -v check --format json --no-check-conflicts > report.json 2> depkeeper.log
324
+ jq '[.[] | select(.status == "outdated")] | length' report.json
325
+ ```
326
+
327
+ **Multi-file projects** — `-r` includes are followed and rewritten
328
+
329
+ ```bash
330
+ depkeeper update requirements/dev.txt --dry-run # also writes base.txt
331
+ ```
332
+
333
+ **Hash-pinned files** — depkeeper refuses these by default
334
+
335
+ ```bash
336
+ depkeeper update --allow-hash-removal -y
337
+ pip-compile --generate-hashes requirements.in # regenerate; not optional
338
+ ```
339
+
340
+ More: **[User guide](https://rahulkaushal04.github.io/depkeeper/guides/)** ·
341
+ **[CI/CD integration](https://rahulkaushal04.github.io/depkeeper/guides/ci-cd-integration/)**
342
+
343
+ ---
344
+
345
+ ## Architecture
346
+
347
+ Synchronous CLI around an asynchronous core. No daemon, no persistent state, no cache directory.
348
+
349
+ ```text
350
+ requirements.txt
351
+ │
352
+ ▼
353
+ RequirementsParser ──► PyPIDataStore ──► VersionChecker ──► DependencyAnalyzer ──┐
354
+ (text → model) (one HTTP call (per-package (cross-package │
355
+ per package) target version) consistency) │
356
+ ▼
357
+ renderer (table/simple/json)
358
+ writer (atomic, rollback-safe)
359
+ ```
360
+
361
+ | Component | Responsibility |
362
+ |---|---|
363
+ | `core/parser.py` | Requirements text → `Requirement` objects, `-r`/`-c` resolution, provenance |
364
+ | `core/data_store.py` | PyPI metadata cache with per-key request coalescing |
365
+ | `core/checker.py` | Per-package recommendation under boundary, Python and constraint filters |
366
+ | `core/dependency_analyzer.py` | Iterative conflict resolution within major boundaries |
367
+ | `commands/` | User interaction, rendering, the write pipeline, exit codes |
368
+ | `utils/` | HTTP, console, logging, atomic filesystem, naming, version algebra |
369
+
370
+ See **[ARCHITECTURE.md](ARCHITECTURE.md)** for the contributor-facing map, or the
371
+ **[architecture deep dive](https://rahulkaushal04.github.io/depkeeper/concepts/architecture/)**
372
+ for design decisions, concurrency model and error propagation.
373
+
374
+ ---
375
+
376
+ ## Limitations
377
+
378
+ Honest, verified, and documented in full at
379
+ **[Known limitations](https://rahulkaushal04.github.io/depkeeper/reference/limitations/)**.
380
+ The ones most likely to affect you:
381
+
382
+ - **Not a resolver.** The transitive graph is not expanded. Always `pip install` and test.
383
+ - **Only `pypi.org` is queried.** `--index-url` lines are parsed and ignored; private packages
384
+ report as errors.
385
+ - **Calendar versions hit the major boundary.** `certifi 2023.x` never auto-bumps to `2024.x`.
386
+ - **Major upgrades are yours to make.** Raise the floor by hand, then let depkeeper continue.
387
+ - **Backslash line continuations are not parsed**, so default
388
+ `pip-compile --generate-hashes` output is unreadable to depkeeper.
389
+ - **No runtime tuning.** Timeouts, retries and concurrency are constants; override them via the
390
+ Python API if you must.
391
+
392
+ ---
393
+
394
+ ## Troubleshooting
395
+
396
+ Start here:
397
+
398
+ ```bash
399
+ depkeeper -vv check --format json > report.json 2> debug.log
400
+ ```
401
+
402
+ `debug.log` names the file parsed, the effective configuration, every HTTP retry and every
403
+ resolution decision.
404
+
405
+ | Symptom | Cause |
406
+ |---|---|
407
+ | Recommendation far below `Latest` | Your declared cap, the major boundary, a conflict, or `requires_python` |
408
+ | Recommendations differ between laptop and CI | Different Python versions running depkeeper |
409
+ | `✗ ERROR` rows | Package not on public PyPI, network/proxy failure, or TLS interception |
410
+ | `update` changed a package `check` showed as `✓ OK` | Unversioned requirement — it received a pin |
411
+ | A proposed **downgrade** | Declared version is unusable; review before accepting |
412
+
413
+ Full guide: **[Troubleshooting](https://rahulkaushal04.github.io/depkeeper/guides/troubleshooting/)**
414
+
415
+ ---
416
+
417
+ ## Documentation
418
+
419
+ Published at **[rahulkaushal04.github.io/depkeeper](https://rahulkaushal04.github.io/depkeeper/)**.
420
+
421
+ | Section | Contents |
422
+ |---|---|
423
+ | [Getting started](https://rahulkaushal04.github.io/depkeeper/getting-started/) | Install, quick start, reading the output |
424
+ | [Concepts](https://rahulkaushal04.github.io/depkeeper/concepts/) | Architecture, version recommendation, conflict resolution, parsing, write safety |
425
+ | [User guide](https://rahulkaushal04.github.io/depkeeper/guides/) | Checking, updating, configuration, CI/CD, operations, best practices, troubleshooting |
426
+ | [Reference](https://rahulkaushal04.github.io/depkeeper/reference/) | CLI, config, exit codes, file formats, JSON schema, errors, limitations, Python API |
427
+ | [Contributing](https://rahulkaushal04.github.io/depkeeper/contributing/) | Setup, code style, testing, extending, releases |
428
+
429
+ Repository documents: [ARCHITECTURE.md](ARCHITECTURE.md) ·
430
+ [CONTRIBUTING.md](CONTRIBUTING.md) · [CHANGELOG.md](CHANGELOG.md) ·
431
+ [SECURITY.md](SECURITY.md) · [SUPPORT.md](SUPPORT.md) ·
432
+ [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)
433
+
434
+ ---
435
+
436
+ ## Project status
437
+
438
+ Version **0.1.1**, classified `Development Status :: 4 - Beta`.
439
+
440
+ The write path is defensive — atomic replacement, two-phase commit, rollback, optional backups —
441
+ and behaviour is documented and covered by tests across Linux, macOS and Windows on Python
442
+ 3.8–3.12. Pin the version in automation: recommendation logic is a behavioural contract, and a
443
+ version bump can legitimately change an update plan.
444
+
445
+ ---
446
+
447
+ ## Contributing
448
+
449
+ Contributions are welcome. Start with [CONTRIBUTING.md](CONTRIBUTING.md), and read the
450
+ [system invariants](https://rahulkaushal04.github.io/depkeeper/concepts/#non-negotiable-invariants)
451
+ before changing anything in `core/`.
452
+
453
+ ```bash
454
+ git clone https://github.com/rahulkaushal04/depkeeper.git
455
+ cd depkeeper
456
+ pip install -e ".[dev,docs]"
457
+ pre-commit install
458
+
459
+ python -m pytest tests -q --no-cov
460
+ python -m mypy depkeeper --python-version 3.13
461
+ ```
462
+
463
+ Report vulnerabilities privately — see [SECURITY.md](SECURITY.md), never a public issue.
464
+
465
+ ---
466
+
467
+ ## License
468
+
469
+ [Apache License 2.0](LICENSE). Copyright 2025-2026 Rahul Kaushal.
470
+
471
+ Built with [Click](https://click.palletsprojects.com/),
472
+ [Rich](https://rich.readthedocs.io/), [httpx](https://www.python-httpx.org/) and
473
+ [packaging](https://packaging.pypa.io/) — the last of which is why depkeeper agrees with `pip`
474
+ about what a version means.