Metadata-Version: 2.4
Name: philiprehberger-config-diff
Version: 0.4.0
Summary: Compare configuration files across environments
Project-URL: Homepage, https://github.com/philiprehberger/py-config-diff#readme
Project-URL: Repository, https://github.com/philiprehberger/py-config-diff
Project-URL: Issues, https://github.com/philiprehberger/py-config-diff/issues
Project-URL: Changelog, https://github.com/philiprehberger/py-config-diff/blob/main/CHANGELOG.md
Author: Philip Rehberger
License-Expression: MIT
License-File: LICENSE
Keywords: compare,config,configuration,diff,environment
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown

# philiprehberger-config-diff

[![Tests](https://github.com/philiprehberger/py-config-diff/actions/workflows/publish.yml/badge.svg)](https://github.com/philiprehberger/py-config-diff/actions/workflows/publish.yml)
[![PyPI version](https://img.shields.io/pypi/v/philiprehberger-config-diff.svg)](https://pypi.org/project/philiprehberger-config-diff/)
[![Last updated](https://img.shields.io/github/last-commit/philiprehberger/py-config-diff)](https://github.com/philiprehberger/py-config-diff/commits/main)

![philiprehberger-config-diff](https://raw.githubusercontent.com/philiprehberger/py-config-diff/main/package-card.webp)

Compare configuration files across environments.

## Installation

```bash
pip install philiprehberger-config-diff
```

## Usage

```python
from philiprehberger_config_diff import diff_files, diff_dicts

# Compare files (JSON, TOML, INI, .env)
report = diff_files("config.dev.json", "config.prod.json")

for change in report.changes:
    print(change)  # "+ db.name = 'proddb'" / "~ port: 3000 -> 8080"

print(report.summary())
# "Added: 3, Removed: 1, Modified: 5"

# Filter by key patterns
report = diff_files("dev.env", "prod.env", include=["DB_*"])

# Compare dicts directly
report = diff_dicts(dev_config, prod_config)
```

### Regex filter patterns

`include` and `exclude` accept compiled `re.Pattern` objects alongside glob strings, which is handy for redacting secret keys by suffix or prefix.

```python
import re
from philiprehberger_config_diff import diff_dicts

report = diff_dicts(
    dev_config,
    prod_config,
    exclude=[re.compile(r".*_token$"), re.compile(r"^secret\.")],
)
```

### Serializing diffs

`DiffReport.to_dict()` returns a JSON-serializable representation, and
`DiffReport.is_empty()` is a quick check for "no changes" in scripts or CI gates.

```python
import json
from philiprehberger_config_diff import diff_dicts

report = diff_dicts({"a": 1}, {"a": 2, "b": 3})

if report.is_empty():
    print("No drift detected")
else:
    print(json.dumps(report.to_dict(), indent=2))
    # {
    #   "changes": [
    #     {"path": "a", "type": "modified", "old": 1, "new": 2},
    #     {"path": "b", "type": "added", "old": null, "new": 3}
    #   ]
    # }
```

### Unified diff output

```python
from philiprehberger_config_diff import unified_diff

dev = {"db": {"host": "localhost", "port": 5432}}
prod = {"db": {"host": "prod-server", "port": 5432}}

print(unified_diff(dev, prod, left_label="dev", right_label="prod"))
# --- dev
# +++ prod
# @@ -1,2 +1,2 @@
# -db.host = 'localhost'
# +db.host = 'prod-server'
#  db.port = 5432
```

## API

| Function / Class | Description |
|---|---|
| `diff_files(left, right, include=None, exclude=None)` | Compare config files |
| `diff_dicts(left, right, include=None, exclude=None)` | Compare dicts |
| `unified_diff(left, right, *, context=3, left_label, right_label)` | Render `diff -u` style output |
| `report.changes` | List of `Change` objects |
| `report.added` / `report.removed` / `report.modified` | Filtered changes |
| `report.summary()` | Change count summary |
| `report.is_empty()` | `True` when the report contains no changes |
| `report.to_dict()` | JSON-serializable `{"changes": [...]}` representation |

## Development

```bash
pip install -e .
python -m pytest tests/ -v
```

## Support

If you find this project useful:

⭐ [Star the repo](https://github.com/philiprehberger/py-config-diff)

🐛 [Report issues](https://github.com/philiprehberger/py-config-diff/issues?q=is%3Aissue+is%3Aopen+label%3Abug)

💡 [Suggest features](https://github.com/philiprehberger/py-config-diff/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement)

❤️ [Sponsor development](https://github.com/sponsors/philiprehberger)

🌐 [All Open Source Projects](https://philiprehberger.com/open-source-packages)

💻 [GitHub Profile](https://github.com/philiprehberger)

🔗 [LinkedIn Profile](https://www.linkedin.com/in/philiprehberger)

## License

[MIT](LICENSE)
