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

Add pyproject.toml & modern packaging to introduction. #1668

Merged
merged 12 commits into from Aug 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
113 changes: 89 additions & 24 deletions README.rst
Expand Up @@ -50,7 +50,8 @@ Example usage for ``pip-compile``
=================================

The ``pip-compile`` command lets you compile a ``requirements.txt`` file from
your dependencies, specified in either ``setup.py`` or ``requirements.in``.
your dependencies, specified in either ``pyproject.toml``, ``setup.cfg``,
``setup.py``, or ``requirements.in``.

Run it with ``pip-compile`` or ``python -m piptools compile``. If you use
multiple Python versions, you can also run ``py -X.Y -m piptools compile`` on
Expand All @@ -67,39 +68,105 @@ available. To compile from scratch, first delete the existing
``requirements.txt`` file, or see `Updating requirements`_ for alternative
approaches.

Requirements from ``setup.py``
------------------------------
Requirements from ``pyproject.toml``
------------------------------------

Suppose you have a Django project, and want to pin it for production.
If you have a ``setup.py`` with ``install_requires=['django']``, then run
``pip-compile`` without any arguments:
The ``pyproject.toml`` file is the
`latest standard <https://peps.python.org/pep-0621/>`_ for configuring
packages and applications, and is recommended for new projects. ``pip-compile``
supports both installing your ``project.dependencies`` as well as your
``project.optional-dependencies``. Thanks to the fact that this is an
official standard, you can use ``pip-compile`` to pin the dependencies
in projects that use modern standards-adhering packaging tools like
`Hatch <https://hatch.pypa.io/>`_ or `flit <https://flit.pypa.io/>`_.

.. code-block:: bash
Suppose you have a Django application that is packaged using ``Hatch``, and you
want to pin it for production. You also want to pin your development tools
in a separate pin file. You declare ``django`` as a dependency and create an
optional dependency ``dev`` that includes ``pytest``:

$ pip-compile
.. code-block:: toml

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "my-cool-django-app"
version = "42"
dependencies = ["django"]

[project.optional-dependencies]
dev = ["pytest"]

You can produce your pin files as easily as:

.. code-block:: console

$ pip-compile -o requirements.txt pyproject.toml
#
hynek marked this conversation as resolved.
Show resolved Hide resolved
# This file is autogenerated by pip-compile
# This file is autogenerated by pip-compile with python 3.10
# To update, run:
#
# pip-compile
# pip-compile --output-file=requirements.txt pyproject.toml
#
asgiref==3.2.3

asgiref==3.5.2
# via django
django==4.1
# via my-cool-django-app (pyproject.toml)
sqlparse==0.4.2
# via django
django==3.0.3
# via my_django_project (setup.py)
pytz==2019.3

$ pip-compile --extra dev -o dev-requirements.txt pyproject.toml
#
# This file is autogenerated by pip-compile with python 3.10
# To update, run:
#
# pip-compile --extra=dev --output-file=dev-requirements.txt pyproject.toml
#

asgiref==3.5.2
# via django
sqlparse==0.3.0
attrs==22.1.0
# via pytest
django==4.1
# via my-cool-django-app (pyproject.toml)
iniconfig==1.1.1
# via pytest
packaging==21.3
# via pytest
pluggy==1.0.0
# via pytest
py==1.11.0
# via pytest
pyparsing==3.0.9
# via packaging
pytest==7.1.2
# via my-cool-django-app (pyproject.toml)
sqlparse==0.4.2
# via django
tomli==2.0.1
# via pytest

This is great for both pinning your applications, but also to keep the CI
of your open-source Python package stable.

Requirements from ``setup.py`` and ``setup.cfg``
------------------------------------------------

``pip-compile`` will produce your ``requirements.txt``, with all the Django
dependencies (and all underlying dependencies) pinned.
``pip-compile`` has also full support for ``setup.py``- and
``setup.cfg``-based projects that use ``setuptools``.

Without ``setup.py``
--------------------
Just define your dependencies and extras as usual and run
``pip-compile`` as above.

If you don't use ``setup.py`` (`it's easy to write one`_), you can create a
``requirements.in`` file to declare the Django dependency:
Requirements from ``requirements.in``
-------------------------------------

You can also use plain text files for your requirements (e.g. if you don't
want your application to be a package). To use a ``requirements.in`` file to
declare the Django dependency:

.. code-block:: ini

Expand Down Expand Up @@ -129,15 +196,13 @@ Now, run ``pip-compile requirements.in``:
And it will produce your ``requirements.txt``, with all the Django dependencies
(and all underlying dependencies) pinned.

.. _it's easy to write one: https://packaging.python.org/guides/distributing-packages-using-setuptools/#configuring-your-project

.. _Updating requirements:

Updating requirements
---------------------

``pip-compile`` generates a ``requirements.txt`` file using the latest versions
that fulfil the dependencies of ``setup.py`` or ``requirements.in``.
that fulfil the dependencies you specify in the supported files.

If ``pip-compile`` finds an existing ``requirements.txt`` file that fulfils the
dependencies then no changes will be made, even if updates are available.
Expand Down
5 changes: 4 additions & 1 deletion piptools/scripts/compile.py
Expand Up @@ -287,7 +287,10 @@ def cli(
emit_options: bool,
unsafe_package: Tuple[str, ...],
) -> None:
"""Compiles requirements.txt from requirements.in specs."""
"""
Compiles requirements.txt from requirements.in, pyproject.toml, setup.cfg,
or setup.py specs.
"""
log.verbosity = verbose - quiet

if len(src_files) == 0:
Expand Down