30 Commits
v0.1.2 ... main

Author SHA1 Message Date
pacnpal
24fa3971bf Update claude-review.yml 2024-12-10 18:58:44 -05:00
pacnpal
7ee17f6479 bump 2024-12-10 18:53:57 -05:00
pacnpal
330bc93df6 Update 2024-12-10 18:52:44 -05:00
pacnpal
7712950aed Update and rename cr.yml to claude-review.yml 2024-12-10 14:52:48 -05:00
pacnpal
40b618f97f Update cr.yml 2024-12-10 14:41:57 -05:00
pacnpal
6f125da2cb Update cr.yml 2024-12-10 14:40:57 -05:00
pacnpal
228ff8aae9 Create cr.yml 2024-12-10 14:39:47 -05:00
deepsource-io[bot]
99cfafa3fa ci: add .deepsource.toml 2024-12-10 19:24:42 +00:00
pacnpal
ee077907e8 Update README.md 2024-12-10 14:03:56 -05:00
pacnpal
141c6c8294 Update python-multiversion.yml 2024-12-10 14:02:21 -05:00
pacnpal
d780ea9092 Update setup.py 2024-12-10 14:01:56 -05:00
pacnpal
a81a56a55a Update setup.py 2024-12-10 14:00:04 -05:00
pacnpal
6019d260fc Update python-multiversion.yml 2024-12-10 13:59:51 -05:00
pacnpal
5672586ce0 Update setup.py 2024-12-10 13:58:21 -05:00
pacnpal
e046250444 Update python-multiversion.yml 2024-12-10 13:57:04 -05:00
pacnpal
78e4b463f9 Create python-multiversion.yml 2024-12-10 13:56:13 -05:00
pacnpal
08be12c63e Update README.md
Add codecov badge
2024-12-10 13:52:40 -05:00
pacnpal
ec082f4174 Update python-tests.yml 2024-12-10 13:50:40 -05:00
pacnpal
fd44299f11 Fix tests 2024-12-10 13:33:54 -05:00
pacnpal
5047dc8093 pytests added 2024-12-10 13:30:16 -05:00
pacnpal
7092c203f9 Create codecov.yml 2024-12-10 13:25:41 -05:00
pacnpal
7292393eec Update publish.yml 2024-12-10 13:24:41 -05:00
PacNPal
af517b1283 Fixed details in README 2024-11-19 09:56:38 -05:00
PacNPal
e821ca9ec4 docs: add virtual environment and pipx installation notes
- Add recommendation to install within virtual environment
- Include pipx installation option for global use
- Improve installation section organization
2024-11-19 09:53:06 -05:00
PacNPal
854c784eab docs: add virtual environment and pipx installation notes
- Add recommendation to install within virtual environment
- Include pipx installation option for global use
- Improve installation section organization
2024-11-19 09:52:33 -05:00
PacNPal
5d6c25a50e fix: remove invalid classifier and bump version to 0.2.3 2024-11-19 09:45:18 -05:00
PacNPal
1067ba9529 updated to 0.2.2 2024-11-19 09:41:47 -05:00
PacNPal
b6fe7168c9 chore: enhance package classifiers
Added classifiers for:
- Environment (Console)
- Intended Audience (System Administrators)
- Operating System (OS Independent)
- Python Implementation (CPython)
- Natural Language (English)
- Additional Topics (Installation/Setup, Distribution)
- Framework (pip)
2024-11-19 09:40:25 -05:00
PacNPal
b41794765c chore: bump version to 0.2.1 for PyPI release 2024-11-19 09:36:53 -05:00
PacNPal
0d507f79f0 feat: add custom requirements file support
- Add -f/--requirements-file option to specify custom requirements file paths
- Enhance requirements file detection with clear user guidance
- Show available files and usage example when multiple files found
- Update documentation with examples and troubleshooting guidance
- Improve error handling for custom file paths
2024-11-19 09:35:08 -05:00
10 changed files with 308 additions and 34 deletions

7
.deepsource.toml Normal file
View File

@@ -0,0 +1,7 @@
version = 1
[[analyzers]]
name = "python"
[analyzers.meta]
runtime_version = "3.x.x"

34
.github/workflows/claude-review.yml vendored Normal file
View File

@@ -0,0 +1,34 @@
name: Claude Code Review
permissions:
contents: read
pull-requests: write
on:
# Run on new/updated PRs
pull_request:
types: [opened, reopened, synchronize]
# Allow manual triggers for existing PRs
workflow_dispatch:
inputs:
pr_number:
description: 'Pull Request Number'
required: true
type: string
jobs:
code-review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run Claude Review
uses: pacnpal/claude-code-review@v1.0.6
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
anthropic-key: ${{ secrets.ANTHROPIC_API_KEY }}
pr-number: ${{ github.event.pull_request.number || inputs.pr_number }}

View File

@@ -25,6 +25,14 @@ jobs:
run: | run: |
python -m pip install --upgrade pip python -m pip install --upgrade pip
pip install build pip install build
- name: Run Pytest tests
run: |
pip install pytest pytest-cov
pytest --cov --cov-report=xml
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
- name: Build package - name: Build package
run: python -m build run: python -m build

View File

@@ -0,0 +1,41 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
name: Python test for 3.8, 3.9, 3.10, 3.11, 3.12, 3.13
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install flake8 pytest
python -m pip install .
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pytest

37
.github/workflows/python-tests.yml vendored Normal file
View File

@@ -0,0 +1,37 @@
name: Python pytest and upload to Codecov
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: "3.x"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install .
pip install pytest pytest-cov
- name: Run coverage & upload to Codecov
run: |
pytest --cov --cov-report=xml
- name: Upload results to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
- name: Run pytest tests
run: |
pytest --cov --junitxml=junit.xml -o junit_family=legacy
- name: Upload test results to Codecov
if: ${{ !cancelled() }}
uses: codecov/test-results-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}

112
README.md
View File

@@ -2,7 +2,9 @@
A command-line tool that combines package installation and requirements.txt management. Install, update, or remove Python packages and their dependencies with automatic requirements.txt handling. A command-line tool that combines package installation and requirements.txt management. Install, update, or remove Python packages and their dependencies with automatic requirements.txt handling.
Compatible with Python 3.11, 3.12, and 3.13. Compatible with Python 3.9, 3.10, 3.11, 3.12, and 3.13.
[![codecov](https://codecov.io/gh/pacnpal/pip-add/graph/badge.svg?token=ATTR6TXNUL)](https://codecov.io/gh/pacnpal/pip-add)
## Features ## Features
@@ -14,11 +16,19 @@ Compatible with Python 3.11, 3.12, and 3.13.
- Clean, informative output with version information - Clean, informative output with version information
- Preserves requirements.txt comments and formatting - Preserves requirements.txt comments and formatting
- Creates requirements.txt if it doesn't exist - Creates requirements.txt if it doesn't exist
- Full support for Python 3.11, 3.12, and 3.13 - Support for custom requirements file paths
- Smart detection of multiple requirements files
- Full support for Python 3.8, 3.9, 3.10, 3.11, 3.12, and 3.13
## Installation ## Installation
It's recommended to install pip-add within a virtual environment to avoid conflicts with system packages:
```bash ```bash
# Create and activate virtual environment
python -m venv venv
source venv/bin/activate # or `venv\Scripts\activate` on Windows
# Install from PyPI # Install from PyPI
pip install pip-add pip install pip-add
@@ -26,9 +36,16 @@ pip install pip-add
pip install --upgrade pip-add pip install --upgrade pip-add
``` ```
For global installation (use with caution), you can install with pipx:
```bash
# Install globally using pipx
pipx install pip-add
```
## Usage ## Usage
### Installation ### Package Installation
```bash ```bash
# Basic package installation # Basic package installation
@@ -53,6 +70,34 @@ pip-add -d requests
# - requests (2.32.3) # - requests (2.32.3)
# - urllib3 (2.2.3) # - urllib3 (2.2.3)
# ✓ Updated requirements.txt # ✓ Updated requirements.txt
# Install using custom requirements file
pip-add -f requirements/dev.txt requests
# Output:
# Installing requests...
# ✓ Successfully installed requests (2.32.3)
# ✓ Updated requirements/dev.txt
```
### Multiple Requirements Files
When multiple requirements files are found in your project:
```bash
# Tool will show available files:
pip-add requests
# Output:
# Found multiple requirements files:
# - requirements.txt
# - requirements/dev.txt
# - requirements/prod.txt
#
# Using: requirements.txt
# To use a specific file, run the command with -f/--requirements-file option:
# Example: pip-add -f requirements/dev.txt requests
# Specify which file to use:
pip-add -f requirements/dev.txt requests
``` ```
### Removal ### Removal
@@ -79,12 +124,19 @@ pip-add -d -r requests
# - idna (needed by: email-validator, cryptography) # - idna (needed by: email-validator, cryptography)
# #
# ✓ Updated requirements.txt # ✓ Updated requirements.txt
# Remove from specific requirements file
pip-add -r -f requirements/dev.txt requests
# Output:
# Removing packages...
# ✓ Successfully uninstalled requests (2.32.3)
# ✓ Updated requirements/dev.txt
``` ```
## Command Line Options ## Command Line Options
``` ```bash
pip-add [-h] [-d] [-e] [-r] package pip-add [-h] [-d] [-e] [-r] [-f REQUIREMENTS_FILE] package
positional arguments: positional arguments:
package Package to install or remove package Package to install or remove
@@ -94,6 +146,8 @@ options:
-d, --dependencies Include dependencies when installing or removing -d, --dependencies Include dependencies when installing or removing
-e, --exact Use == instead of >= for version specification -e, --exact Use == instead of >= for version specification
-r, --remove Remove package(s) and their entries from requirements.txt -r, --remove Remove package(s) and their entries from requirements.txt
-f, --requirements-file
Path to custom requirements.txt file
``` ```
## How It Works ## How It Works
@@ -103,7 +157,7 @@ options:
1. Installs the specified package using pip 1. Installs the specified package using pip
2. Retrieves installed version information 2. Retrieves installed version information
3. With `-d`: tracks and installs all dependencies 3. With `-d`: tracks and installs all dependencies
4. Updates requirements.txt with new package(s) 4. Updates requirements.txt (or specified requirements file) with new package(s)
5. Uses `>=` by default or `==` with `-e` flag 5. Uses `>=` by default or `==` with `-e` flag
### Removal Process ### Removal Process
@@ -112,9 +166,21 @@ options:
2. Identifies which dependencies are safe to remove 2. Identifies which dependencies are safe to remove
3. Checks if any dependencies are needed by other packages 3. Checks if any dependencies are needed by other packages
4. Safely removes unused packages 4. Safely removes unused packages
5. Updates requirements.txt 5. Updates requirements.txt (or specified requirements file)
6. Reports kept dependencies and their dependents 6. Reports kept dependencies and their dependents
### Requirements File Handling
1. By default, looks for requirements.txt in the current directory
2. Creates requirements.txt if it doesn't exist
3. With `-f`: uses specified requirements file path
4. Creates directories if needed for custom file paths
5. Preserves comments and formatting in existing files
6. When multiple files are found:
- Lists all available requirements files
- Shows which file will be used by default
- Provides example command to specify a particular file
## Safe Dependency Handling ## Safe Dependency Handling
The tool is designed to safely handle dependencies: The tool is designed to safely handle dependencies:
@@ -130,31 +196,22 @@ The tool is designed to safely handle dependencies:
- pip - pip
- setuptools - setuptools
## Development
### Local Setup
```bash
# Clone the repository
git clone https://github.com/PacNPal/pip-add.git
cd pip-add
# Create virtual environment
python -m venv venv
source venv/bin/activate # or `venv\Scripts\activate` on Windows
# Install in development mode
pip install -e .
```
## Common Scenarios ## Common Scenarios
### New Project ### New Project
```bash ```bash
# First time setup # First time setup
pip-add flask
# Creates requirements.txt and adds Flask
pip-add -d flask pip-add -d flask
# Creates requirements.txt and adds Flask with dependencies # Creates requirements.txt and adds Flask with dependencies
# Multiple requirements files
pip-add -f requirements/dev.txt pytest
pip-add -f requirements/prod.txt gunicorn
# Manages separate requirement files for different environments
``` ```
### Updating Dependencies ### Updating Dependencies
@@ -178,6 +235,7 @@ pip-add -d -r flask
1. **Package not found in requirements.txt** 1. **Package not found in requirements.txt**
- The file will be created automatically - The file will be created automatically
- Existing comments are preserved - Existing comments are preserved
- Use `-f` to specify a different requirements file
2. **Dependency conflicts** 2. **Dependency conflicts**
- Uses `>=` by default to minimize conflicts - Uses `>=` by default to minimize conflicts
@@ -186,3 +244,9 @@ pip-add -d -r flask
3. **Dependencies not removing** 3. **Dependencies not removing**
- Check the output for dependencies kept - Check the output for dependencies kept
- Tool will show which packages need them - Tool will show which packages need them
4. **Multiple requirements files**
- Tool will list all available requirements files
- Shows which file will be used by default
- Provides example command to specify a particular file
- Use `-f` to specify which file to use

View File

@@ -4,14 +4,27 @@ import subprocess
import pkg_resources import pkg_resources
import argparse import argparse
from pkg_resources import working_set from pkg_resources import working_set
from .utils import find_requirements as utils_find_requirements
def find_requirements(): def find_requirements(custom_path=None):
"""Find requirements.txt in current directory or create it""" """Find requirements.txt using utils or use custom path"""
req_file = 'requirements.txt' if custom_path:
# If custom path provided, ensure directory exists
os.makedirs(os.path.dirname(os.path.abspath(custom_path)), exist_ok=True)
if not os.path.exists(custom_path):
with open(custom_path, 'w') as f:
f.write('# Python dependencies\n')
return custom_path
if not os.path.exists(req_file): # Use utils.find_requirements() to search for requirements files
with open(req_file, 'w') as f: req_file, found_files = utils_find_requirements()
f.write('# Python dependencies\n') if len(found_files) > 1:
print("\n Found multiple requirements files:")
for f in found_files:
print(f" - {f}")
print(f"\nUsing: {req_file}")
print("To use a specific file, run the command with -f/--requirements-file option:")
print(f"Example: pip-add -f {found_files[0]} <package>")
return req_file return req_file
@@ -168,10 +181,12 @@ def main():
help='Use == instead of >= for version specification') help='Use == instead of >= for version specification')
parser.add_argument('-r', '--remove', action='store_true', parser.add_argument('-r', '--remove', action='store_true',
help='Remove package(s) and their entries from requirements.txt') help='Remove package(s) and their entries from requirements.txt')
parser.add_argument('-f', '--requirements-file',
help='Path to custom requirements.txt file')
args = parser.parse_args() args = parser.parse_args()
package = args.package package = args.package
req_file = find_requirements() req_file = find_requirements(args.requirements_file)
try: try:
if args.remove: if args.remove:
@@ -235,4 +250,4 @@ def main():
sys.exit(1) sys.exit(1)
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup( setup(
name="pip-add", name="pip-add",
version="0.1.2", version="0.2.5",
packages=find_packages(), packages=find_packages(),
install_requires=[ install_requires=[
"pip", "pip",
@@ -21,13 +21,23 @@ setup(
url="https://github.com/PacNPal/pip-add", url="https://github.com/PacNPal/pip-add",
classifiers=[ classifiers=[
"Development Status :: 4 - Beta", "Development Status :: 4 - Beta",
"Environment :: Console",
"Intended Audience :: Developers", "Intended Audience :: Developers",
"Intended Audience :: Information Technology",
"Intended Audience :: System Administrators",
"License :: OSI Approved :: MIT License", "License :: OSI Approved :: MIT License",
"Natural Language :: English",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.13",
"Programming Language :: Python :: Implementation :: CPython",
"Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: System :: Installation/Setup",
"Topic :: System :: Software Distribution",
"Topic :: System :: Systems Administration",
"Topic :: Utilities",
], ],
python_requires=">=3.11", python_requires=">=3.8",
) )

48
tests/test_cli.py Normal file
View File

@@ -0,0 +1,48 @@
import pytest
from pip_add.cli import (
find_requirements,
get_package_dependencies,
find_dependent_packages,
analyze_dependencies,
remove_from_requirements,
add_to_requirements,
install_package,
uninstall_packages,
main
)
def test_find_requirements():
# Add test cases for find_requirements
pass
def test_get_package_dependencies():
# Add test cases for get_package_dependencies
pass
def test_find_dependent_packages():
# Add test cases for find_dependent_packages
pass
def test_analyze_dependencies():
# Add test cases for analyze_dependencies
pass
def test_remove_from_requirements():
# Add test cases for remove_from_requirements
pass
def test_add_to_requirements():
# Add test cases for add_to_requirements
pass
def test_install_package():
# Add test cases for install_package
pass
def test_uninstall_packages():
# Add test cases for uninstall_packages
pass
def test_main():
# Add test cases for main
pass

10
tests/test_utils.py Normal file
View File

@@ -0,0 +1,10 @@
import pytest
from pip_add.utils import find_requirements, add_to_requirements
def test_find_requirements():
# Add test cases for find_requirements
pass
def test_add_to_requirements():
# Add test cases for add_to_requirements
pass