Tools to help build and install Jupyter Python packages that require a pre-build step that may include JavaScript build steps.
pip install jupyter-packaging
There are three ways to use jupyter-packaging in another package. In general, you should not depend on jupyter_packaging as a runtime dependency, only as a build dependency.
Use a pyproject.toml file as outlined in pep-518. An example:
[build-system] requires = ["jupyter_packaging>=0.10,<2"] build-backend = "setuptools.build_meta"Below is an example setup.py using the above config. It assumes the rest of your metadata is in setup.cfg. We wrap the import in a try/catch to allow the file to be run without jupyter_packaging so that python setup.py can be run directly when not building.
from setuptools import setup try: from jupyter_packaging import wrap_installers, npm_builder builder = npm_builder() cmdclass = wrap_installers(pre_develop=builder, pre_dist=builder) except ImportError: cmdclass = {} setup(cmdclass=cmdclass))Use the jupyter_packaging build backend. The pre-build command is specified as metadata in pyproject.toml:
[build-system] requires = ["jupyter_packaging>=0.10,<2"] build-backend = "jupyter_packaging.build_api" [tool.jupyter-packaging.builder] factory = "jupyter_packaging.npm_builder" [tool.jupyter-packaging.build-args] build_cmd = "build:src"The corresponding setup.py would be greatly simplified:
from setuptools import setup setup()The tool.jupyter-packaging.builder section expects a func value that points to an importable module and a function with dot separators. If not given, no pre-build function will run.
The optional tool.jupyter-packaging.build-args sections accepts a dict of keyword arguments to give to the pre-build command.
The build backend does not handle the develop command (pip install -e .). If desired, you can wrap just that command:
import setuptools try: from jupyter_packaging import wrap_installers, npm_builder builder = npm_builder(build_cmd="build:dev") cmdclass = wrap_installers(pre_develop=builder) except ImportError: cmdclass = {} setup(cmdclass=cmdclass))The optional tool.jupyter-packaging.options section accepts the following options:
skip-if-exists: A list of local files whose presence causes the prebuild to skipensured-targets: A list of local file paths that should exist when the dist commands are run
Vendor setupbase.py locally alongside setup.py and import the module directly.
import setuptools from setupbase import wrap_installers, npm_builder func = npm_builder() cmdclass = wrap_installers(post_develop=func, pre_dist=func) setup(cmdclass=cmdclass)- This package does not work with the deprecated
python setup.py bdist_wheelorpython setup.py sdistcommands, PyPA recommends using the build package (pip install build && python -m build .). - We recommend using
include_package_data=TrueandMANIFEST.into control the assets included in the package. - Tools like
check-manifestormanifixcan be used to ensure the desired assets are included. - Simple uses of
data_filescan be handled insetup.cfgor insetup.py. If recursive directories are needed useget_data_files()from this package. - Unfortunately
data_filesare not supported indevelopmode (a limitation ofsetuptools). You can work around it by doing a full install (pip install .) before the develop install (pip install -e .), or by adding a script to push the data files tosys.base_prefix.
git clone https://github.com/jupyter/jupyter-packaging.git cd jupyter-packaging pip install -e .[test] pre-commit installYou can test changes locally by creating a pyproject.toml with the following, replacing the local path to the git checkout:
[build-system] requires = ["jupyter_packaging@file://<path-to-git-checkout>"] build-backend = "setuptools.build_meta"Note: you need to run pip cache remove jupyter_packaging any time changes are made to prevent pip from using a cached version of the source.