Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating _run_get_stderr() to not break on failed installs from pip() #35

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 37 additions & 21 deletions ipydeps/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ def importlib_invalidate_caches():
_pip_run_args = [sys.executable, '-m', 'pip']

def _get_pip_exec(config_options):
def _pip_exec(args1, args2):
return _run_get_stderr(_pip_run_args+args1+args2)
def _pip_exec(args1, args2, **kwargs):
return _run_get_stderr(_pip_run_args+args1+args2, **kwargs)

if '--use-pypki2' in config_options:
import pypki2pip
Expand Down Expand Up @@ -290,22 +290,21 @@ def _find_overrides(packages, dep_link):

return overrides

def _run_get_stderr(cmd):
def _run_get_stderr(cmd, progress=False):
returncode = 0
err = None

try:
subprocess.check_output(cmd, stderr=subprocess.PIPE)
except subprocess.CalledProcessError as e:
returncode = e.returncode

if sys.version_info.major == 3:
err = _bytes_to_str(e.stderr)
elif sys.version_info.major == 2:
err = e.output
else:
raise Exception('Invalid version of Python')

return returncode, err

def _get_freeze_package_name(info):
Expand Down Expand Up @@ -335,10 +334,11 @@ def _subtract_stdlib(stdlib_packages, packages):
return packages - stdlib_packages

def _run_and_log_error(cmd):
returncode, err = _run_get_stderr(cmd)

if returncode != 0 and err is not None:
_logger.error(err)
package_errs = _run_get_stderr(cmd)
if package_errs:
for package, (returncode, err) in package_errs.items():
if returncode != 0 and err is not None:
_logger.error(err)

def package(pkg_name):
packages = _pkg_name_list(pkg_name)
Expand Down Expand Up @@ -371,15 +371,17 @@ def _log_stdlib_packages(stdlib_packages, packages):
if package in stdlib_packages:
_logger.warning('{0} is part of the Python standard library and will be skipped. Remove it from the list to remove this warning.'.format(package))

def _log_before_after(before, after):
def _log_before_after(before, after, errors):
new_packages = after - before

if len(new_packages) == 0:
_logger.warning('No new packages installed')
elif len(new_packages) > 0:
_logger.info('New packages installed: {0}'.format(', '.join(sorted(list(new_packages)))))
if errors:
_logger.error('Unable to install the following packages: {0}'.format(', '.join(sorted(list(errors)))))

def pip(pkg_name, verbose=False):
def pip(pkg_name, verbose=False, progress=False):
args = [
'install',
]
Expand Down Expand Up @@ -410,24 +412,38 @@ def pip(pkg_name, verbose=False):

# calculate and subtract what's installed again after overrides installed
packages = _subtract_installed(packages)

packages = list(packages)
args.extend(_remove_internal_options(_remove_per_package_options(_config_options)))
args.extend(_per_package_args(packages, _config_options))

if progress:
import tqdm
if _in_ipython():
progress_bar = tqdm.tqdm_notebook(total=len(packages), desc='Installing packages')
else:
progress_bar = tqdm.tqdm(total=len(packages), desc='Installing packages')

if len(packages) > 0:
_logger.debug('Running pip to install {0}'.format(', '.join(sorted(packages))))
pip_exec = _get_pip_exec(_config_options)
returncode, err = pip_exec(args + packages)

if returncode != 0 and err is not None:
_logger.error(err)

_invalidate_cache()
_refresh_available_packages()
package_errs = {}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gershwinlabs After a couple of adjustments, I like your idea of bringing the package iteration and progress bar out to pip() (much cleaner!) -- as for wrapping it up in a function for added cleanliness, do you mean lines 429-436 in this commit?

for package in packages:
_logger.debug('Installing {0}...'.format(package))
returncode, err = pip_exec(args + [package], progress=progress)
if err:
package_errs[package] = err
# only update the bar if a package is successfully installed?
if progress and not err:
progress_bar.update()
_invalidate_cache()
_refresh_available_packages()

packages_after_install = _already_installed()
_log_before_after(packages_before_install, packages_after_install)
_log_before_after(packages_before_install, packages_after_install, list(package_errs.keys()))

for package, err in package_errs.items():
_logger.error(err)

_logger.debug('Done')

def _make_user_site_packages():
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
url='https://github.com/nbgallery/ipydeps',
packages=['ipydeps'],
package_data={'ipydeps': ['data/*.txt']},
install_requires=['pip', 'setuptools', 'pypki2>=0.10.1'],
install_requires=['pip', 'setuptools', 'pypki2>=0.10.1', 'tqdm'],
classifiers=[
'Development Status :: 4 - Beta',
'Topic :: Utilities',
Expand Down