pip.py - Wrappers for various pip-based commands

Purpose:

This module provides the functionality related to calls to pip.

Platform:

Linux/Windows | Python 3.10+

Developer:

J Berendt

Email:

development@s3dev.uk

Comments:

n/a

Example:

Download pandas:

>>> from ppklib.pip import Download

>>> pipdl = Download('pandas')
>>> pipdl.get()

# Display the path to the downloaded target package.
>>> pipdl.pkgpath

# Optional cleanup after the wheels are no longer needed.
>>> pipdl.cleanup()

Download pandas version 2.2.3 for Windows and Python 3.13 into a specified download directory:

>>> from ppklib.pip import Download

>>> pipdl = Download('pandas',
                     version='2.2.3',
                     args={'platform': 'win_amd64', 'python_version': '313'},
                     tmpdir='/tmp/c0ff33')
>>> pipdl.get()

# Display the path to the downloaded target package.
>>> pipdl.pkgpath

# Optional cleanup after the wheels are no longer needed.
>>> pipdl.cleanup()
class Download(name: str, *, version: str = None, args: dict | Namespace = None, reqfile: str = None, tmpdir: str = None)[source]

Bases: object

Processing related to the pip download command.

Parameters:
  • name (str) – Name of the target library to be downloaded.

  • version (str, optional) – Specific version of the target library to be downloaded. If None, the latest version will be downloaded. Defaults to None.

  • args (dict | Namespace, optional) – A dict or the Namespace object directly from the ppk argument parser. This will contain all the parameters required for the download. Generally, these will match pip’s CLI arguments which are implemented in this library, with the hyphens converted to underscores. For example: pip’s --python-version is python_version. Defaults to None.

  • reqfile (str, optional) – Full path to the requirements.txt file, if applicable. If using a requirements file, pass None to the name argument. Defaults to None.

  • tmpdir (str, optional) – Full path to the temp (download) directory. If None, a temp directory is automatically created. Defaults to None.

property pkgpath: str | None

Accessor to the full path of the downloaded target package.

Returns:

The full path to the downloaded target package if downloaded successfully, otherwise None.

Return type:

str | None

cleanup() None[source]

Remove the temporary directory and all downloaded files.

Note

Cleanup is only called automatically on pip error. Otherwise, it’s the user’s (or caller’s) decision to call for a cleanup.

get() str | None[source]

Collect the specified package and version (if provided).

Note

The full path to the downloaded package can be accessed via the pkgpath property.

Example:

For example usage, please refer to this module’s docstring.

_cleanup()[source]

Class tear-down and internal cleanup method.

_download()[source]

Using a subprocess call, download the package via pip.

By design, the output from pip is streamed to the terminal and therefore not captured by a subprocess.PIPE.

The --only-binary=:all: argument is added to the pip command if any of the following arguments are passed, as this is a requirement by pip, unless --no_deps is specified.

  • --only_binary

  • --platform

  • --python_version

If the pip download fails for any reason (returning a non-zero exit code), the program is exited with an exit code of 1 and a force cleanup is performed.

_find() None[source]

Find the downloaded target package and store the filename.

For case agnostic searching, (e.g. in the case of libraries such as ‘sqlalchemy’ which downloads as ‘SQLAlchemy’), the search is carried out using a filter() applied to the sorted return value from os.listdir().

If the target package is found in the download directory, the filename is stored to the _pkg: attribute.

_fix_missing(msg: bytes)[source]

Update the requirements file to fix the missing binary library.

Parameters:

msg (bytes) – Error message thrown by pip to stderr, directly from the subprocess.Popen.communicate call.

Using pip’s error message, the offending package name is extracted. Then, a line (as shown below) is appended to the requirements file, instructing pip to download the source distribution:

--no-binary=<pkg_name>

Finally, re-call _pip_download() to re-try the download with the modified requirements file.

static _parse_err__no_matching_dist(msg: bytes) str[source]

Extract the relevant package name from the error message.

Parameters:

msg (bytes) – Error message directly from the Popen.communicate stderr pipe.

Returns:

Name of the offending package.

Return type:

str

_set_tmpdir_name(name: str = None) None[source]

Set the name of the temp directory.

Parameters:

name (str, optional) – Name of the temp directory from class instance. Defaults to None.

If passed as None, a temp directory name is derived and used by pip, then destroyed afterwords. If a name is provided by the caller, this name is used instead.