def uninstall(packages, env_name, global_uninstall, dev, quiet, yes): """If the option --env is supplied, the uninstall will be applied using that named virtual env. Unless the option --global is selected, the uninstall will only affect the current user. Of course, this will have no effect if a virtual env is in use. The desired name of the admin user can be set with the `_DEFAULT_ADMIN_` environment variable. With no packages selected, this will uninstall using a `requirements.txt` or a dev version of that in the current directory. """ if not packages: reqs = get_requirements_file(os.getcwd(), dev=dev) if not reqs: click.echo('Unable to locate a requirements file.') sys.exit(1) packages = ['-r', reqs] # Windows' `runas` allows only a single argument for the # command so we catch this case and turn our command into # a string later. windows_admin_command = None if yes: # no cov packages = ['-y', *packages] if env_name: venv_dir = os.path.join(VENV_DIR, env_name) if not os.path.exists(venv_dir): click.echo('Virtual env named `{}` does not exist.'.format(env_name)) sys.exit(1) with venv(venv_dir): command = [get_proper_pip(), 'uninstall', *packages] + (['-q'] if quiet else []) result = subprocess.run(command, shell=NEED_SUBPROCESS_SHELL) else: command = [get_proper_pip(), 'uninstall'] + (['-q'] if quiet else []) if not venv_active() and global_uninstall: # no cov if ON_WINDOWS: windows_admin_command = get_admin_command() else: command = get_admin_command() + command command.extend(packages) if windows_admin_command: # no cov command = windows_admin_command + [' '.join(command)] result = subprocess.run(command, shell=NEED_SUBPROCESS_SHELL) sys.exit(result.returncode)
def install(packages, env_name, editable, global_install, quiet): """If the option --env is supplied, the install will be applied using that named virtual env. Unless the option --global is selected, the install will only affect the current user. Of course, this will have no effect if a virtual env is in use. The desired name of the admin user can be set with the `_DEFAULT_ADMIN_` environment variable. With no packages selected, this will install using a `setup.py` in the current directory. """ packages = packages or ['.'] # Windows' `runas` allows only a single argument for the # command so we catch this case and turn our command into # a string later. windows_admin_command = None if editable: packages = ['-e', *packages] if env_name: venv_dir = os.path.join(VENV_DIR, env_name) if not os.path.exists(venv_dir): click.echo('Virtual env named `{}` does not exist.'.format(env_name)) sys.exit(1) with venv(venv_dir): command = [get_proper_pip(), 'install', *packages] + (['-q'] if quiet else []) result = subprocess.run(command, shell=NEED_SUBPROCESS_SHELL) else: command = [get_proper_pip(), 'install'] + (['-q'] if quiet else []) if not venv_active(): # no cov if global_install: if ON_WINDOWS: windows_admin_command = get_admin_command() else: command = get_admin_command() + command else: command.append('--user') command.extend(packages) if windows_admin_command: # no cov command = windows_admin_command + [' '.join(command)] result = subprocess.run(command, shell=NEED_SUBPROCESS_SHELL) sys.exit(result.returncode)
def get_editable_package_location(package_name=None): location = '' try: output = subprocess.check_output( [get_proper_pip(), 'list', '-e', '--format', 'columns'], shell=NEED_SUBPROCESS_SHELL).decode().strip().splitlines()[2:] except subprocess.CalledProcessError: # no cov return location if package_name: for line in output: name, _, path = line.split() if name == package_name: return resolve_path(path) else: if len(output) == 1: name, _, path = output[0].split() return name, resolve_path(path) elif len(output) > 1: return None, False else: return None, None return location
def get_package_version(package_name): output = subprocess.check_output( [get_proper_pip(), 'list', '--format', 'json'], shell=NEED_SUBPROCESS_SHELL).decode() packages = json.loads(output) for package in packages: if package['name'] == package_name: return package['version'] return ''
def get_installed_packages(editable=True): editable_packages = get_editable_packages() output = subprocess.check_output( [get_proper_pip(), 'list', '--format', 'json'], shell=NEED_SUBPROCESS_SHELL).decode() packages = [ package['name'] for package in json.loads(output) if editable or package['name'] not in editable_packages ] return packages
def get_editable_package_location(package_name): location = '' try: output = subprocess.check_output( [get_proper_pip(), 'list', '-e', '--format', 'columns'], shell=NEED_SUBPROCESS_SHELL).decode().strip() except subprocess.CalledProcessError: # no cov return location for line in output.splitlines()[2:]: name, _, path = line.split() if name == package_name: return resolve_path(path) return location
def get_editable_packages(): output = subprocess.check_output( [get_proper_pip(), 'list', '-e', '--format', 'json'], shell=NEED_SUBPROCESS_SHELL).decode() return set(package['name'] for package in json.loads(output))
def install_packages(packages): subprocess.run([get_proper_pip(), 'install'] + packages, shell=NEED_SUBPROCESS_SHELL)
def update(packages, env_name, eager, all_packages, infra, global_install, force, dev, as_module, self, quiet): """If the option --env is supplied, the update will be applied using that named virtual env. Unless the option --global is selected, the update will only affect the current user. Of course, this will have no effect if a virtual env is in use. The desired name of the admin user can be set with the `_DEFAULT_ADMIN_` environment variable. When performing a global update, your system may use an older version of pip that is incompatible with some features such as --eager. To force the use of these features, use --force. With no packages nor options selected, this will update packages by looking for a `requirements.txt` or a dev version of that in the current directory. To update this tool, use the --self flag. After the update, you may want to press Enter. All other methods of updating will ignore `hatch`. See: https://github.com/pypa/pip/issues/1299 """ command = ['install', '--upgrade'] + (['-q'] if quiet else []) if not global_install or force: # no cov command.extend(['--upgrade-strategy', 'eager' if eager else 'only-if-needed']) infra_packages = ['pip', 'setuptools', 'wheel'] temp_dir = None # Windows' `runas` allows only a single argument for the # command so we catch this case and turn our command into # a string later. windows_admin_command = None if self: # no cov as_module = True if env_name: venv_dir = os.path.join(VENV_DIR, env_name) if not os.path.exists(venv_dir): click.echo('Virtual env named `{}` does not exist.'.format(env_name)) sys.exit(1) with venv(venv_dir): executable = ( [sys.executable if self else get_proper_python(), '-m', 'pip'] if as_module or (infra and ON_WINDOWS) else [get_proper_pip()] ) command = executable + command if all_packages: installed_packages = infra_packages if infra else get_installed_packages() else: installed_packages = None else: venv_dir = None executable = ( [sys.executable if self else get_proper_python(), '-m', 'pip'] if as_module or (infra and ON_WINDOWS) else [get_proper_pip()] ) command = executable + command if all_packages: installed_packages = infra_packages if infra else get_installed_packages() else: installed_packages = None if not venv_active(): # no cov if global_install: if ON_WINDOWS: windows_admin_command = get_admin_command() else: command = get_admin_command() + command else: command.append('--user') if self: # no cov command.append('hatch') if venv_dir: with venv(venv_dir): subprocess.Popen(command, shell=NEED_SUBPROCESS_SHELL) else: subprocess.Popen(command, shell=NEED_SUBPROCESS_SHELL) sys.exit() elif infra: command.extend(infra_packages) elif all_packages: installed_packages = [ package for package in installed_packages if package not in infra_packages and package != 'hatch' ] if not installed_packages: click.echo('No packages installed.') sys.exit(1) command.extend(installed_packages) elif packages: packages = [package for package in packages if package != 'hatch'] if not packages: click.echo('No packages to install.') sys.exit(1) command.extend(packages) # When https://github.com/pypa/pipfile is finalized, we'll use it. else: reqs = get_requirements_file(os.getcwd(), dev=dev) if not reqs: click.echo('Unable to locate a requirements file.') sys.exit(1) with open(reqs, 'r') as f: lines = f.readlines() matches = [] for line in lines: match = re.match(r'^[^=<>]+', line.lstrip()) if match and match.group(0) == 'hatch': matches.append(line) if matches: for line in matches: lines.remove(line) temp_dir = TemporaryDirectory() reqs = os.path.join(temp_dir.name, basepath(reqs)) with open(reqs, 'w') as f: f.writelines(lines) command.extend(['-r', reqs]) if windows_admin_command: # no cov command = windows_admin_command + [' '.join(command)] if venv_dir: with venv(venv_dir): result = subprocess.run(command, shell=NEED_SUBPROCESS_SHELL) else: result = subprocess.run(command, shell=NEED_SUBPROCESS_SHELL) if temp_dir is not None: temp_dir.cleanup() sys.exit(result.returncode)
def uninstall(packages, no_detect, env_name, global_uninstall, admin, dev, quiet, yes): """If the option --env is supplied, the uninstall will be applied using that named virtual env. Unless the option --global is selected, the uninstall will only affect the current user. Of course, this will have no effect if a virtual env is in use. The desired name of the admin user can be set with the `_DEFAULT_ADMIN_` environment variable. With no packages selected, this will uninstall using a `requirements.txt` or a dev version of that in the current directory. If no --env is chosen, this will attempt to detect a project and use its virtual env before resorting to the default pip. No project detection will occur if a virtual env is active. """ if not packages: reqs = get_requirements_file(os.getcwd(), dev=dev) if not reqs: echo_failure('Unable to locate a requirements file.') sys.exit(1) packages = ['-r', reqs] # Windows' `runas` allows only a single argument for the # command so we catch this case and turn our command into # a string later. windows_admin_command = None if yes: # no cov packages = ['-y', *packages] if env_name: venv_dir = os.path.join(VENV_DIR, env_name) if not os.path.exists(venv_dir): echo_failure('Virtual env named `{}` does not exist.'.format(env_name)) sys.exit(1) with venv(venv_dir): command = [get_proper_pip(), 'uninstall', *packages] + (['-q'] if quiet else []) echo_waiting('Uninstalling in virtual env `{}`...'.format(env_name)) result = subprocess.run(command, shell=NEED_SUBPROCESS_SHELL) elif not venv_active() and not no_detect and os.path.isfile(os.path.join(os.getcwd(), 'setup.py')): venv_dir = os.path.join(os.getcwd(), 'venv') if not is_venv(venv_dir): echo_info('A project has been detected!') echo_waiting('Creating a dedicated virtual env... ', nl=False) create_venv(venv_dir) echo_success('complete!') with venv(venv_dir): echo_waiting('Installing this project in the virtual env... ', nl=False) install_packages(['-q', '-e', '.']) echo_success('complete!') echo_warning('New virtual envs have nothing to uninstall, exiting...') sys.exit(2) with venv(venv_dir): command = [get_proper_pip(), 'uninstall', *packages] + (['-q'] if quiet else []) echo_waiting('Uninstalling for this project...') result = subprocess.run(command, shell=NEED_SUBPROCESS_SHELL) else: command = [get_proper_pip(), 'uninstall'] + (['-q'] if quiet else []) if not venv_active() and global_uninstall: # no cov if not admin: if ON_WINDOWS: windows_admin_command = get_admin_command() else: command = get_admin_command() + command command.extend(packages) if windows_admin_command: # no cov command = windows_admin_command + [' '.join(command)] echo_waiting('Uninstalling...') result = subprocess.run(command, shell=NEED_SUBPROCESS_SHELL) sys.exit(result.returncode)