Skip to content

Instantly share code, notes, and snippets.

@mgaitan
Created August 16, 2024 12:05
Show Gist options
  • Save mgaitan/7d75ff2dc7063e67639a6568151d65f3 to your computer and use it in GitHub Desktop.
Save mgaitan/7d75ff2dc7063e67639a6568151d65f3 to your computer and use it in GitHub Desktop.
#!/usr/env python
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "pip-requirements-parser",
# "rich",
# ]
# ///
"""
This script compares two Python requirements files, providing a set of operations to analyze the differences and commonalities between them.
Usage:
$ pip install pip-requirements-parser
$ python compare_reqs.py <path_to_first_requirements_file> <path_to_second_requirements_file> [--operation <operation>]
Arguments:
<path_to_first_requirements_file> : The file path to the first requirements file to be compared.
<path_to_second_requirements_file> : The file path to the second requirements file to be compared.
Options:
-o, --operation <operation> : Specify the set operation to perform. Choices are:
- "intersection": Shows packages present in both files.
- "diff1": Shows packages present in the first file (r1) but not in the second file (r2).
- "diff2": Shows packages present in the second file (r2) but not in the first file (r1).
Default is "intersection".
Output:
The script outputs a table with the results of the specified operation. The table includes the package name and version (if available) from both requirements files. The comparison is color-coded:
- Green: The versions match in both files.
- Red: The versions differ between the files or the package is only present in one of them.
Dependencies:
- pip-requirements-parser: A package used to parse the requirements files.
- rich: A package for formatting and displaying rich text, tables, and other elements in the console.
If you run this via `uv run` these are automatically installed.
Example:
To compare two requirements files and find the intersection:
$ python compare_reqs.py requirements1.txt requirements2.txt --operation intersection
To find packages in the first file that are not in the second:
$ python compare_reqs.py requirements1.txt requirements2.txt --operation diff1
To find packages in the second file that are not in the first:
$ python compare_reqs.py requirements1.txt requirements2.txt --operation diff2
"""
import argparse
from pip_requirements_parser import RequirementsFile
from rich.console import Console
from rich.table import Table
# Create the argument parser
parser = argparse.ArgumentParser(description="Compare two requirement files.")
# Add arguments for file paths
parser.add_argument("r1_path", type=str, help="Path to the first requirements file")
parser.add_argument("r2_path", type=str, help="Path to the second requirements file")
parser.add_argument(
"-o",
"--operation",
default="intersection",
choices=["intersection", "diff1", "diff2"],
help="Set operation to perform: intersection, diff1 (r1 not in r2), diff2 (r2 not in r1)",
)
# Parse the arguments
args = parser.parse_args()
# Use the provided file paths
r1 = RequirementsFile.from_file(args.r1_path)
r2 = RequirementsFile.from_file(args.r2_path)
# Convert the requirements to dictionaries
r1_dict = {
r["name"]: r["specifier"][0].replace("==", "") if r["specifier"] else "" for r in r1.to_dict()["requirements"]
}
r2_dict = {
r["name"]: r["specifier"][0].replace("==", "") if r["specifier"] else "" for r in r2.to_dict()["requirements"]
}
if args.operation == "intersection":
title = "Packages in both files"
result_keys = set(r2_dict) & set(r1_dict)
elif args.operation == "diff1":
title = "Packages in r1 and not r2"
result_keys = set(r1_dict) - set(r2_dict)
elif args.operation == "diff2":
title = "Packages in r2 and not r1"
result_keys = set(r2_dict) - set(r1_dict)
comparison_result = {pkg: (r1_dict.get(pkg, ''), r2_dict.get(pkg, "")) for pkg in result_keys}
table = Table(title=title)
table.add_column("Package")
table.add_column(args.r1_path)
table.add_column(args.r2_path)
# Print the sorted comparison results
for p, (v1, v2) in sorted(comparison_result.items()):
color = "green" if v1 == v2 else "red"
table.add_row(f"[{color}]{p}[/{color}]", v1, v2)
console = Console()
console.print(table)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment