Metadata-Version: 2.4
Name: devpi-constrained
Version: 2.1.0
Summary: "devpi-constrained: an index for devpi-server that provides a constrained list of packages from it's bases"
Home-page: https://github.com/devpi/devpi-constrained
Author: Florian Schulze
Author-email: mail@florian-schulze.net
License: MIT
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Plugins
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: POSIX
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Topic :: Utilities
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Requires-Python: >=3.7
License-File: LICENSE
Requires-Dist: devpi-common
Requires-Dist: devpi-server>=6.10.0
Requires-Dist: packaging-legacy
Dynamic: license-file

devpi-constrained: releases filter for devpi-server
===================================================

This plugin adds a *constrained* index to `devpi-server`_.
The *constrained* index is read-only and filters releases from its bases similar to `Constraints Files`_ in `pip`_.

.. _devpi-server: http://pypi.python.org/pypi/devpi-server
.. _Constraints Files: https://pip.pypa.io/en/stable/user_guide/#constraints-files
.. _pip: https://pip.pypa.io/


Installation
------------

``devpi-constrained`` needs to be installed alongside ``devpi-server`` to enable *constrained* indexes.

You can install it with::

    pip install devpi-constrained

There is no configuration needed as ``devpi-server`` will automatically discover the plugin through calling hooks using the setuptools entry points mechanism.


Motivation
----------

It is often useful to filter Python packages available for installation.
For example:

- Filter package versions with known security issues
- Provide a "Known Good Set" of packages which have been tested
- Prevent installation of packages with incompatible licenses
- Only allowing vetted packages
- Block package versions with breaking changes

With ``devpi-constrained`` it is possible to provide a package index which enables all of the above and more.


Usage
-----

Create a *constrained* index with ``root/pypi`` as base:

.. code-block::

    $ devpi index -c prod/devpi type=constrained bases=root/pypi
    https://example.com/prod/devpi:
      type=constrained
      bases=root/pypi
      volatile=True
      acl_upload=root
      acl_toxresult_upload=:ANONYMOUS:
      constraints=
      mirror_whitelist=

    $ devpi use prod/devpi

With no constraints set, all releases are available from ``root/pypi``.

Lets add a constraint for ``pip``:

.. code-block::

    $ devpi index constraints+="pip==6.0"
    /prod/devpi constraints+=pip==6.0
    https://example.com/prod/devpi?no_projects=:
      type=constrained
      bases=root/pypi
      volatile=True
      acl_upload=root
      acl_toxresult_upload=:ANONYMOUS:
      constraints=pip==6.0
      mirror_whitelist=

Now only ``pip 6.0`` will be listed when looking for releases of ``pip``:

.. code-block::

    $ devpi list --all pip
    http://localhost:3141/root/pypi/+f/610/3897f1bb68d3f/pip-6.0.tar.gz
    http://localhost:3141/root/pypi/+f/5ec/6732505bd8be4/pip-6.0-py2.py3-none-any.whl

All other packages are still unconstrained.

To block everything else we add the ``*`` constraint:

.. code-block::

    $ devpi index constraints+="*"
    /prod/devpi constraints+=*
    https://example.com/prod/devpi?no_projects=:
      type=constrained
      bases=root/pypi
      volatile=True
      acl_upload=root
      acl_toxresult_upload=:ANONYMOUS:
      constraints=pip==6.0,*
      mirror_whitelist=

This is the difference to ``pip`` constraints, where this isn't possible.

.. code-block::

    $ devpi list --all devpi-server
    GET https://example.com/prod/devpi/devpi-server/
    404 Not Found: no project 'devpi-server'

The ``constraints`` option can be set in bulk from a file.
Create a file ``constraints.txt`` with each constraint in one line::

    pip<8,>4
    # a comment
    devpi-server>=4

Set the ``constraints`` option on your index from the file::

    $ devpi index constraints="$(cat constraints.txt)"


Legacy versions
---------------

Support for legacy (non `PEP440 <https://peps.python.org/pep-0440/>`_) versions is limited.
When the constraint contains any filtering on the version, then no legacy version will pass.
Technically legacy versions sort before any PEP440 compliant version,
but the ``packaging`` library doesn't expose the operator publicly in an easily usable way,
so this compromise was chosen to not have to deal with possibly changing internals.

Changelog
=========

2.1.0 - 2026-05-08
------------------

- With devpi-server 7.0.0 filtering when inheriting from a constrained index works as expected.
  [fschulze]

- Fix version filtering with "*" (all) constraint.
  [fschulze]

- Rudimentary support for legacy (non PEP440) versions.
  [fschulze]

- Require devpi-server >= 6.10.0.
  [fschulze]

- Add support for Python 3.12, 3.13 and 3.14.
  [fschulze]

- Fix devpi import/export
  [amoutaux (Aurélien Moutaux)]


2.0.1 - 2023-03-18
------------------

- Fix filtering of simple links page.
  [EvaSDK (Gilles Dartiguelongue)]


2.0.0 - 2023-02-21
------------------

- Remove support for Python <= 3.6.
  [fschulze]

- Add testing for Python 3.8, 3.9, 3.10, 3.11 and PyPy-3.7.
  [fschulze]

- Require devpi-server >= 6.2.0.
  [fschulze]


1.0.0 - 2019-08-05
------------------

- Initial release.
  [fschulze (Florian Schulze)]
