From 0d507f79f0e693348a559cdcdf22df62b69971ce Mon Sep 17 00:00:00 2001 From: PacNPal <183241239+pacnpal@users.noreply.github.com> Date: Tue, 19 Nov 2024 09:35:08 -0500 Subject: [PATCH] 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 --- README.md | 69 +++++++++++++++++++++++++++++++++++++++++++++++--- pip_add/cli.py | 31 +++++++++++++++++------ 2 files changed, 89 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 3f3df41..fd6dd0b 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ Compatible with Python 3.11, 3.12, and 3.13. - Clean, informative output with version information - Preserves requirements.txt comments and formatting - Creates requirements.txt if it doesn't exist +- Support for custom requirements file paths +- Smart detection of multiple requirements files - Full support for Python 3.11, 3.12, and 3.13 ## Installation @@ -53,6 +55,34 @@ pip-add -d requests # - requests (2.32.3) # - urllib3 (2.2.3) # ✓ 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 @@ -79,12 +109,19 @@ pip-add -d -r requests # - idna (needed by: email-validator, cryptography) # # ✓ 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 ``` -pip-add [-h] [-d] [-e] [-r] package +pip-add [-h] [-d] [-e] [-r] [-f REQUIREMENTS_FILE] package positional arguments: package Package to install or remove @@ -94,6 +131,8 @@ options: -d, --dependencies Include dependencies when installing or removing -e, --exact Use == instead of >= for version specification -r, --remove Remove package(s) and their entries from requirements.txt + -f, --requirements-file + Path to custom requirements.txt file ``` ## How It Works @@ -103,7 +142,7 @@ options: 1. Installs the specified package using pip 2. Retrieves installed version information 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 ### Removal Process @@ -112,9 +151,21 @@ options: 2. Identifies which dependencies are safe to remove 3. Checks if any dependencies are needed by other 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 +### 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 The tool is designed to safely handle dependencies: @@ -155,6 +206,11 @@ pip install -e . # First time setup pip-add -d flask # 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 @@ -178,6 +234,7 @@ pip-add -d -r flask 1. **Package not found in requirements.txt** - The file will be created automatically - Existing comments are preserved + - Use `-f` to specify a different requirements file 2. **Dependency conflicts** - Uses `>=` by default to minimize conflicts @@ -186,3 +243,9 @@ pip-add -d -r flask 3. **Dependencies not removing** - Check the output for dependencies kept - 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 diff --git a/pip_add/cli.py b/pip_add/cli.py index a99b886..da8f494 100644 --- a/pip_add/cli.py +++ b/pip_add/cli.py @@ -4,14 +4,27 @@ import subprocess import pkg_resources import argparse from pkg_resources import working_set +from .utils import find_requirements as utils_find_requirements -def find_requirements(): - """Find requirements.txt in current directory or create it""" - req_file = 'requirements.txt' +def find_requirements(custom_path=None): + """Find requirements.txt using utils or use custom path""" + 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): - with open(req_file, 'w') as f: - f.write('# Python dependencies\n') + # Use utils.find_requirements() to search for requirements files + req_file, found_files = utils_find_requirements() + 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]} ") return req_file @@ -168,10 +181,12 @@ def main(): help='Use == instead of >= for version specification') parser.add_argument('-r', '--remove', action='store_true', 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() package = args.package - req_file = find_requirements() + req_file = find_requirements(args.requirements_file) try: if args.remove: @@ -235,4 +250,4 @@ def main(): sys.exit(1) if __name__ == '__main__': - main() \ No newline at end of file + main()