From bb0263bdac91d2120f7d7133b1f504657d1754f5 Mon Sep 17 00:00:00 2001 From: Danila Vershinin Date: Wed, 13 Jan 2021 00:20:44 +0300 Subject: [PATCH] Allow handling version specifiers; ability to update programs --- README.md | 17 +++++++++++------ pip_safe/__about__.py | 2 +- pip_safe/__init__.py | 37 +++++++++++++++++++++++++++---------- 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 7b1b2b6..3541f6d 100644 --- a/README.md +++ b/README.md @@ -31,8 +31,8 @@ then run `source ~/.bashrc` to apply to current shell. ### CentOS/RHEL 7, 8 - sudo yum install https://extras.getpagespeed.com/release-latest.rpm - sudo yum install pip-safe + sudo yum -y install https://extras.getpagespeed.com/release-latest.rpm + sudo yum -y install pip-safe Using `pip-safe` command installs stuff using Python 3. @@ -69,17 +69,18 @@ Ensure `virtualenv-3` is installed and `/usr/local/bin` is in your `PATH`, then: ## Usage ``` -usage: pip-safe [-h] [-v] [-y] [--system] [package-name] +Safely install and remove PyPi (pip) programs without breaking your system positional arguments: - + Command to run, e.g. install, update, remove or list package-name optional arguments: -h, --help show this help message and exit -v, --verbose -y, --assumeyes - --system + --system Install for all users + --version show program's version number and exit ``` ### Installing a program @@ -90,7 +91,7 @@ To see what's going on under the hood, pass `--verbose` flag. There is limited support for installing directly from Git URLs, e.g.: - pip-safe install git+https://github.com/dvershinin/lastversion.git + pip-safe install git+https://github.com/dvershinin/lastversion.git #### Global installation @@ -105,6 +106,10 @@ so it's still safe :-) ### Removing a program pip-safe remove + +### Updating a program + + pip-safe update ### Listing installed packages diff --git a/pip_safe/__about__.py b/pip_safe/__about__.py index 034f46c..6526deb 100644 --- a/pip_safe/__about__.py +++ b/pip_safe/__about__.py @@ -1 +1 @@ -__version__ = "0.0.6" +__version__ = "0.0.7" diff --git a/pip_safe/__init__.py b/pip_safe/__init__.py index 7127ece..8e4e761 100644 --- a/pip_safe/__init__.py +++ b/pip_safe/__init__.py @@ -39,6 +39,8 @@ def get_venv_dir(name, system_wide=False): # as a dumb way to make result directory creatable name = name.replace('https://', '') name = name.replace('/', '_') + # sanitize version specifier if user installs, e.g. lastversion==1.2.4 + name = name.split('==')[0] venvs_dir = get_venvs_dir(system_wide=system_wide) return os.path.join(venvs_dir, name) @@ -59,7 +61,8 @@ def get_venv_executable_names(name, system_wide=False): log.debug("Checking what was installed to virtualenv's bin") bin_names = [] venv_pip = get_venv_pip(name, system_wide) - main_package_name = name + # sanitize version specifier if user installs, e.g. lastversion==1.2.4 + main_package_name = name.split('==')[0] # if the passed name was a URL, we have to figure out the name of the "main" # package that was installed, by listing non-dependent packages and weeding # out known stuff like wheel and pip itself @@ -110,7 +113,7 @@ def get_current_version(name, system_wide=False): return v -def install_package(name, system_wide=False): +def install_package(name, system_wide=False, upgrade=False): # create and activate the virtual environment bin_dir = get_bin_dir(system_wide=system_wide) @@ -118,9 +121,14 @@ def install_package(name, system_wide=False): make_sure_path_exists(venv_dir) install_for = 'system-wide' if system_wide else 'for current user' - log.info( - 'Installing {} {} ...'.format(name, install_for) - ) + if not upgrade: + log.info( + 'Installing {} {} ...'.format(name, install_for) + ) + else: + log.info( + 'Upgrading {} {} ...'.format(name, install_for) + ) log.debug('Creating virtualenv at {}'.format(venv_dir)) try: virtualenv.create_environment(venv_dir) @@ -131,8 +139,12 @@ def install_package(name, system_wide=False): log.debug("Running virtualenv's pip install {}".format(name)) # call_subprocess here is used for convinience: since we already import # this, why not :) - call_subprocess( - [venv_dir + '/bin/pip', 'install', name, '--quiet']) + args = [venv_dir + '/bin/pip', 'install'] + if upgrade: + args.append('-U') + args.append(name) + args.append('--quiet') + call_subprocess(args) pkg_bin_names = get_venv_executable_names(name, system_wide) for bin_name in pkg_bin_names: @@ -234,8 +246,8 @@ def main(): 'without breaking your system', prog='pip-safe') parser.add_argument('command', metavar='', default=None, - choices=['install', 'list', 'remove'], - help='Command to run, e.g. install, remove or list') + choices=['install', 'update', 'upgrade', 'list', 'remove'], + help='Command to run, e.g. install, update, remove or list') parser.add_argument('package', metavar='package-name', nargs='?', default=None) parser.add_argument('-v', '--verbose', dest='verbose', action='store_true') @@ -255,7 +267,12 @@ def main(): log.basicConfig(format="%(levelname)s: %(message)s", level=log.INFO) if args.command == 'install': - install_package(name=args.package, system_wide=args.system) + install_package(name=args.package, + system_wide=args.system) + elif args.command in ['update', 'upgrade']: + install_package(name=args.package, + system_wide=args.system, + upgrade=True) elif args.command == 'list': list_packages() elif args.command == 'remove':