Skip to main content

A PyPI to PKGBUILD converter.

Project description

PyPI

Convert PyPI packages to Arch Linux packages, inspired from pip2arch.

Handles packages of all sizes, from the simplest (pure Python, no dependencies) to the most complex (C-level dependencies, external C libraries, etc., e.g. most of the scientific Python stack, or GUI toolkits such as PyGObject and wxPython) [1].

Dependencies and installation

pypi2pkgbuild.py depends on the Arch Linux packages namcap, pkgfile, and python-pip [2].

The script can be installed with pip install [--user] ., or can also be run directly.

One can even run pypi2pkgbuild.py on itself to create a proper Arch package (pypi2pkgbuild.py git+https://github.com/anntzer/pypi2pkgbuild).

A minimal test suite (checking that pypi2pkgbuild.py can indeed package itself) can by run with pytest≥3.9 (pytest -s to keep the output to the terminal).

Usage

pypi2pkgbuild.py PYPINAME creates a PKGBUILD for the latest version of the given PyPI package and the current version of the Python interpreter (Python 3 only). Prereleases are considered if the --pre flag is passed. Because PyPI’s dependency information is somewhat unreliable, it installs the package in a venv to figure out the dependencies. Note that thanks to pip’s wheel cache, the build is later reused; i.e. the procedure entails very little extra work.

A -git package can be built with pypi2pkgbuild.py git+https://....

The package is then built and verified with namcap.

The goal is to make this tool as automated as possible: if all the information to build a package is (reasonably) accessible, this tool should be able to build it.

In order to provide additional information to makepkg, edit PKGBUILD_EXTRAS (which can also be done with the --pkgbuild-extras flag). This file is sourced at the end of PKGBUILD. For ease of patching, the build, package, and, where applicable, pkgver functions are defined by forwarding to _build, _package, and _pkgver. A _check function is also available, but not used (due to the lack of standard testing CLI). Some useful examples of PKGBUILD_EXTRAS are listed in the pkgbuild-extras directory.

Usage notes

  • It is suggested to create an alias with standard options set, e.g.

alias pypi2pkgbuild.py='PKGEXT=.pkg.tar pypi2pkgbuild.py -g cython -b /tmp/pypi2pkgbuild/ -f'
  • By default, the pkgrel of (standard) packages is set to 00. This allows automatic upgrading into official packages (and AUR ones, if an AUR helper is used) whenever the repositories are updated. Additionally, the use of 00 rather than 0 serves as a (weak) marker that the package was automatically generated by this tool. In order to prevent such an upgrade, one can use the --pkgrel flag to set pkgrel to, e.g., 99.

  • If one wishes to completely bypass AUR Python packages while maintaining the use of an AUR helper for non-Python packages, one can define a shell function that excludes pypi2pkgbuild.py-generated packages that do not appear in the official repositories, e.g., for pacaur:

    pacaur() {
       if [[ "$1" = "-Syu" ]]; then
          # Update, in case some packages moved in or out of the official repos.
          sudo pacman -Sy
          # Upgrade everything except python packages with pkgver=00 or 99.
          PKGEXT=.pkg.tar command pacaur -Su --ignore \
                "$(pacman -Qm | grep '^python-.*-\(00\|99\)$' | cut -d' ' -f1 | paste -sd,)"
       else
          command pacaur "$@"
       fi
    }

    This function will not bypass Python packages explicitly installed from the AUR, as the user may have done so to bypass some incorrect packaging by pypi2pkgbuild.py. It is recommended to use the -i flag to calls to pypi2pkgbuild.py (e.g. in an alias) to exclude packages that are mishandled by pypi2pkgbuild.py (see mispackaged packages). The -i flag can be passed multiple times; passing an empty argument to it will clear the ignore list defined so far.

  • In order to package a locally available git repository, use

    $ pypi2pkgbuild.py git+file://$absolute_path_to_repo  # (e.g. file:///home/...)

    In order to package a locally available sdist or wheel, use

    $ pypi2pkgbuild.py file://$absolute_path_to_file  # (e.g. file:///home/...)

    Note that in both cases absolute paths are necessary.

    Building packages from local repos or wheels needs to be done in topological order of the dependencies (so that pypi2pkgbuild.py can find that the dependencies are actually present), or by passing the -d flag (“do not build dependencies”); if it is used, the Arch package may not use the correct dependency names (if they are not of the form python-pep503-normalized-name).

  • By default, pypi2pkgbuild.py ignores pip config files such as ~/.config/pip/pip.conf. An explicitly set PIP_CONFIG_FILE will be respected, but may cause pypi2pkgbuild.py to fail as some pip calls will be unexpectedly modified.

    Likewise, user-site packages are ignored unless PYTHONNOUSERSITE is explicitly set to an empty value.

Build-time dependencies of packages

pypi2pkgbuild.py attempts to guess whether Cython and SWIG are build-time dependencies by checking for the presence of .pyx and .i files, respectively. If this is not desired, set the --guess-makedepends option accordingly.

pypi2pkgbuild.py guesses whether numpy is a build-time dependency by attempting a build without numpy, then, in case of failure, a build with numpy.

Additional Python build-time dependencies (i.e., setup_requires) can be specified (as PyPI names) using the --setup-requires flag, or just as normal entries using --pkgbuild-extras (they will be installed into the build virtualenv).

Additional non-Python build-time dependencies can be set as makedepends using --pkgbuild-extras; they will be installed before pypi2pkgbuild.py attempts to build a wheel for the package.

Vendored packages

Some Arch packages (e.g. ipython) include a number of smaller PyPI packages.

Because it is not possible to assign a meaningful version automatically, pypi2pkgbuild.py instead creates an independent Arch package for each of the PyPI packages (with two dashes in the name, to prevent name conflicts) and a master package that depends on all of them. The pkgrel of the master package is set to $official_pkgrel.99, so that the package appears more recent than the current official version but older than any future official version. All these packages conflict with all versions of the official package (except the newly created package), so upgrading should work fine when the official package is actually updated.

However, dependencies are still expressed using the master package (to avoid breakage on upgrade into an official package), so internal dependencies will appear be circular.

All the packages are placed in a subfolder named meta:$pkgname, so one can easily install everything by cd’ing there and running

$ sudo pacman -U --asdeps **/*.xz
$ sudo pacman -D --asexplicit $pkgname/$pkgname.tar.xz

Handling Python upgrades

When the Python minor version (x in 3.x) is upgraded, it is necessary to regenerate all self-built packages. This can be done e.g. with

$ pypi2pkgbuild.py $(
     ls /usr/lib/python3.$oldver/site-packages |
     grep -Po '.*(?=-.*.dist-info)'
  )

Comparison with other tools

Other similar tools include pip2arch, pip2pkgbuild, and fpm. To the best of my knowledge, the features below are unique to PyPI2PKGBUILD; please let me know if this is incorrect.

  • Supports wheels (the default is to prefer any-platform wheels, then sdists, then manylinux1 wheels, but this can be changed using --pkgtypes).

  • Resolves Python dependencies via installation in a temporary virtualenv, and also creates PKGBUILDs for those that are not available as official packages.

  • Resolves binary dependencies via namcap and adds them to the depends array if they are installed (thus, it is suggested to first install them as --asdeps and then let the generated PKGBUILD pick them up as dependencies). Note that some packages are distributed with a copy of the required libraries; in this case, pypi2pkgbuild.py’s behavior will depend on whether the package defaults to using the system-wide library or its own copy.

  • Automatically tries to fetch a missing license file from Github, if applicable.

  • Automatically builds the package (with options given in --makepkg=...) and run namcap.

  • Automatically builds all outdated dependencies via -u.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pypi2pkgbuild-0.3.tar.gz (30.2 kB view details)

Uploaded Source

File details

Details for the file pypi2pkgbuild-0.3.tar.gz.

File metadata

  • Download URL: pypi2pkgbuild-0.3.tar.gz
  • Upload date:
  • Size: 30.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.1 importlib_metadata/3.7.3 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.59.0 CPython/3.9.2

File hashes

Hashes for pypi2pkgbuild-0.3.tar.gz
Algorithm Hash digest
SHA256 eae7aa06c2a05175d5e6a37b91fc07d728a3d788c210af9028ecffb18b69fcdd
MD5 c5a97c461827ff5e98d91c64c2bbdde6
BLAKE2b-256 3cd7f2eb113bab3a9452d0d8da3047a4761a16b19cdb58ad60de74b42ed14c2f

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page