An interactive pip requirements upgrader that also updates the version in your requirements.txt file
—
User interface for selecting packages to upgrade, presenting upgrade information in formatted tables with interactive prompts and pre-selection options.
Presents available package upgrades in a formatted table and handles user selection through an interactive command-line interface.
class PackageInteractiveSelector:
def __init__(self, packages_map, options):
"""
Initialize interactive package selector.
Args:
packages_map (dict): Package status map from PackagesStatusDetector
options (dict): Command-line options including -p for pre-selection
Raises:
KeyboardInterrupt: If no packages need upgrading
"""
def get_packages(self):
"""
Return the list of packages selected for upgrade.
Returns:
list: List of package status dictionaries for selected packages
"""
def ask_for_packages(self):
"""
Display interactive upgrade table and prompt for user selection.
Displays:
- Formatted table with package names, versions, and upload dates
- Color-coded output for better readability
- Interactive prompt for package selection
Raises:
KeyboardInterrupt: On invalid selection or user cancellation
"""Processes user selection input and validates package choices.
def _select_packages(self, indexes):
"""
Select packages by index numbers from the upgrade table.
Args:
indexes (list): List of integer indexes corresponding to table rows
Returns:
list: List of booleans indicating successful selections
Side effects:
Populates self.selected_packages with selected package dictionaries
"""Provides compatible input handling across Python 2 and 3.
def user_input(prompt=None):
"""
Cross-Python compatible input function.
Args:
prompt (str, optional): Prompt string to display
Returns:
str: User input string
Compatibility:
Uses raw_input for Python 2, input for Python 3
"""When no -p option is provided, displays an interactive table for package selection.
Table Format:
Available upgrades:
┌─────┬─────────────────┬─────────────────┬────────────────┬─────────────────┐
│ No. │ Package │ Current version │ Latest version │ Release date │
├─────┼─────────────────┼─────────────────┼────────────────┼─────────────────┤
│ 1 │ django │ 3.2.0 │ 4.1.0 │ 2022-08-03 │
│ 2 │ requests │ 2.25.1 │ 2.28.1 │ 2022-06-29 │
│ 3 │ flask │ 2.0.0 │ 2.2.2 │ 2022-08-08 │
└─────┴─────────────────┴─────────────────┴────────────────┴─────────────────┘
Please choose which packages should be upgraded. Choices: "all", "q" (quit), "x" (exit) or "1 2 3"
Choice:Selection Options:
all - Select all available upgradesq or x - Quit/exit without upgrading1 2 3 - Space-separated list of package numbersWhen -p option is provided, skips interactive prompts.
All Packages:
pip-upgrade requirements.txt -p allSpecific Packages:
pip-upgrade requirements.txt -p django -p flaskMatches package names case-insensitively.
from pip_upgrader.packages_interactive_selector import PackageInteractiveSelector
# Package status map from status detector
packages_map = {
'django': {
'name': 'django',
'current_version': Version('3.2.0'),
'latest_version': Version('4.1.0'),
'upgrade_available': True,
'upload_time': '2022-08-03 08:15:30'
},
'requests': {
'name': 'requests',
'current_version': Version('2.25.1'),
'latest_version': Version('2.28.1'),
'upgrade_available': True,
'upload_time': '2022-06-29 14:22:18'
}
}
# Interactive selection (no -p option)
options = {'-p': []}
selector = PackageInteractiveSelector(packages_map, options)
selected = selector.get_packages()
# User sees table and chooses "1 2"
print(len(selected)) # 2 packages selected# Select all packages automatically
options = {'-p': ['all']}
selector = PackageInteractiveSelector(packages_map, options)
selected = selector.get_packages()
print(len(selected)) # All upgradeable packages selected# Pre-select specific packages
options = {'-p': ['django', 'flask']}
selector = PackageInteractiveSelector(packages_map, options)
selected = selector.get_packages()
# Only django and flask will be selected (if available for upgrade)The interface uses colorclass for enhanced terminal output:
"all" # Select all packages
"1" # Select package #1
"1 2 3" # Select packages #1, #2, #3
"q" # Quit
"x" # Exit"" # Empty input -> "No choice selected"
" " # Whitespace only -> "No choice selected"
"5 6 7" # Non-existent indexes -> "No valid choice selected"
"abc" # Non-numeric -> "Invalid choice"All invalid inputs raise KeyboardInterrupt with appropriate error messages.
When all packages are up-to-date:
# Prints colored message and raises KeyboardInterrupt
print(Color('{autogreen}All packages are up-to-date.{/autogreen}'))
raise KeyboardInterrupt()Only packages with upgrade_available: True are included in the interactive table. Up-to-date packages are filtered out automatically.
Pre-selected package names are matched case-insensitively:
# These are equivalent:
-p Django
-p django
-p DJANGOInteractive selection uses 1-based indexing for user-friendliness, but internally maps to 0-based dictionary keys.
Requires package status map with specific structure:
{
'package_name': {
'name': str,
'current_version': Version,
'latest_version': Version,
'upgrade_available': bool,
'upload_time': str
}
}Produces list of package dictionaries for upgrade processing:
[
{
'name': 'django',
'current_version': Version('3.2.0'),
'latest_version': Version('4.1.0'),
'upgrade_available': True,
'upload_time': '2022-08-03 08:15:30'
}
]Install with Tessl CLI
npx tessl i tessl/pypi-pip-upgrader