"""
infoml.pkg
----------
This module contains functions for managing - install, uninstall, check -
python packages with both `pip` and `conda`.
"""
# Imports from standard library
import sys
# Imports from local source
from .utils import system
[docs]def check_package(importname: str) -> bool:
"""
Check if a package is installed.
Parameters
----------
importname : str
Name used when importing the package
Returns
-------
bool
True if package is installed, False otherwise
"""
try:
__import__(importname)
except ImportError:
return False
return True
[docs]def pipinstall(
packagename: str,
importname: str = "",
version: str = "",
reinstall: bool = False,
) -> None:
"""
Install a python package with `pip`.
Modified from the `bmes` package by Ahmet Sacan.
Parameters
----------
packagename : str, optional
Name used for installing the package
importname : str
Name used when importing the package, by default None
In most cases, this is identical to `packagename` but both must be
provided when they are different.
version : str, optional
Version of the package to install, by default None
reinstall : bool, optional
Should the package be reinstalled, by default False
Examples
--------
>>> pipinstall('numpy');
>>> pipinstall('pandas', version='1.0.0');
>>> pipinstall('biopython', 'Bio')
"""
# Function for construction commands
def __construct_cmd():
if version is None:
cmd = f"{sys.executable} -m pip install -U {packagename}"
else:
cmd = f"{sys.executable} -m pip install -U {packagename}=={version}"
return cmd
# Set the import name
importname = importname or packagename
# Check if the package is already installed
if check_package(importname):
if reinstall:
print(f"Reinstalling {packagename}...")
pipuninstall(packagename, importname)
else:
print(f"{packagename} is already installed.")
return
# Install the package
out = system(__construct_cmd())
known_errors = [
"ERROR: Could not install packages",
"Consider using the `--user` option",
]
# Try again with `--user` option
if known_errors[0] in str(out) and known_errors[1] in str(out):
out = system(__construct_cmd() + " --user")
# Check if package was installed
if check_package(importname):
print(f"{packagename} is installed.")
else:
print(f"{packagename} could not be installed.")
print(out)
return
[docs]def pipuninstall(packagename: str, importname: str = "") -> None:
"""
Uninstall a python package with `pip`.
Parameters
----------
packagename : str
Name used for installing the package
importname : str, optional
Name used when importing the package, by default None
In most cases, this is identical to `packagename` but both must be
provided when they are different.
Examples
--------
>>> pipuninstall('numpy');
"""
# Set the import name
importname = importname or packagename
# Check if the package is installed
if not check_package(importname):
print(f"{packagename} is not installed.")
return
# Uninstall the package
out = system(f"{sys.executable} -m pip uninstall -y {packagename}")
# Check if package was uninstalled
if not check_package(importname):
print(f"{packagename} is uninstalled.")
else:
print(f"{packagename} could not be uninstalled.")
print(out)
return
if __name__ == "__main__":
print("This module is not intended to be run directly.")
else:
# Define module I/O
__all__ = [
"check_package",
"pipinstall",
"pipuninstall",
]
__all__ += [m for m in dir() if m.startswith("__")]
def __dir__():
"""Override default dir() behavior"""
return __all__
def __getattr__(name):
"""Override default getattr() behavior"""
if name not in __all__:
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
return globals()[name]