Skip to content

Commit

Permalink
Rework the specifiers documentation
Browse files Browse the repository at this point in the history
Moving the content into inline docstrings makes it easier to ensure that
they are updated/evolve with the implementation.

This also expands the behaviors shown, by documenting the relevant
details for each function. These examples are doctest'd in CI.
  • Loading branch information
pradyunsg committed Jul 10, 2022
1 parent 790759c commit fe5a6f1
Show file tree
Hide file tree
Showing 2 changed files with 375 additions and 199 deletions.
137 changes: 9 additions & 128 deletions docs/specifiers.rst
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
Specifiers
==========

.. currentmodule:: packaging.specifiers
A core requirement of dealing with dependencies is the ability to
specify what versions of a dependency are acceptable for you.

A core requirement of dealing with dependencies is the ability to specify what
versions of a dependency are acceptable for you. `PEP 440`_ defines the
standard specifier scheme which has been implemented by this module.
See `Version Specifiers Specification`_ for more details on the exact
format implemented in this module, for use in Python Packaging tooling.

.. _Version Specifiers Specification: https://packaging.python.org/en/latest/specifications/version-specifiers/

Usage
-----
Expand Down Expand Up @@ -48,127 +50,6 @@ Usage
Reference
---------

.. class:: SpecifierSet(specifiers="", prereleases=None)

This class abstracts handling specifying the dependencies of a project. It
can be passed a single specifier (``>=3.0``), a comma-separated list of
specifiers (``>=3.0,!=3.1``), or no specifier at all. Each individual
specifier will be attempted to be parsed as a PEP 440 specifier
(:class:`Specifier`). You may combine :class:`SpecifierSet` instances using
the ``&`` operator (``SpecifierSet(">2") & SpecifierSet("<4")``).

Both the membership tests and the combination support using raw strings
in place of already instantiated objects.

:param str specifiers: The string representation of a specifier or a
comma-separated list of specifiers which will
be parsed and normalized before use.
:param bool prereleases: This tells the SpecifierSet if it should accept
prerelease versions if applicable or not. The
default of ``None`` will autodetect it from the
given specifiers.
:raises InvalidSpecifier: If the given ``specifiers`` are not parseable
than this exception will be raised.

.. attribute:: prereleases

A boolean value indicating whether this :class:`SpecifierSet`
represents a specifier that includes a pre-release versions. This can be
set to either ``True`` or ``False`` to explicitly enable or disable
prereleases or it can be set to ``None`` (the default) to enable
autodetection.

.. method:: __contains__(version)

This is the more Pythonic version of :meth:`contains()`, but does
not allow you to override the ``prereleases`` argument. If you
need that, use :meth:`contains()`.

See :meth:`contains()`.

.. method:: contains(version, prereleases=None)

Determines if ``version``, which can be either a version string, a
:class:`Version` is contained within this set of specifiers.

This will either match or not match prereleases based on the
``prereleases`` parameter. When ``prereleases`` is set to ``None``
(the default) it will use the ``Specifier().prereleases`` attribute to
determine if to allow them. Otherwise it will use the boolean value of
the passed in value to determine if to allow them or not.

.. method:: __len__()

Returns the number of specifiers in this specifier set.

.. method:: __iter__()

Returns an iterator over all the underlying :class:`Specifier` instances
in this specifier set.

.. method:: filter(iterable, prereleases=None)

Takes an iterable that can contain version strings, :class:`~.Version`,
instances and will then filter them, returning an iterable that contains
only items which match the rules of this specifier object.

This method is smarter than just
``filter(Specifier().contains, [...])`` because it implements the rule
from PEP 440 where a prerelease item SHOULD be accepted if no other
versions match the given specifier.

The ``prereleases`` parameter functions similarly to that of the same
parameter in ``contains``. If the value is ``None`` (the default) then
it will intelligently decide if to allow prereleases based on the
specifier, the ``Specifier().prereleases`` value, and the PEP 440
rules. Otherwise it will act as a boolean which will enable or disable
all prerelease versions from being included.


.. class:: Specifier(specifier, prereleases=None)

This class abstracts the handling of a single `PEP 440`_ compatible
specifier. It is generally not required to instantiate this manually,
preferring instead to work with :class:`SpecifierSet`.

:param str specifier: The string representation of a specifier which will
be parsed and normalized before use.
:param bool prereleases: This tells the specifier if it should accept
prerelease versions if applicable or not. The
default of ``None`` will autodetect it from the
given specifiers.
:raises InvalidSpecifier: If the ``specifier`` does not conform to PEP 440
in any way then this exception will be raised.

.. attribute:: operator

The string value of the operator part of this specifier.

.. attribute:: version

The string version of the version part of this specifier.

.. attribute:: prereleases

See :attr:`SpecifierSet.prereleases`.

.. method:: __contains__(version)

See :meth:`SpecifierSet.__contains__()`.

.. method:: contains(version, prereleases=None)

See :meth:`SpecifierSet.contains()`.

.. method:: filter(iterable, prereleases=None)

See :meth:`SpecifierSet.filter()`.


.. exception:: InvalidSpecifier

Raised when attempting to create a :class:`Specifier` with a specifier
string that does not conform to `PEP 440`_.


.. _`PEP 440`: https://www.python.org/dev/peps/pep-0440/
.. automodule:: packaging.specifiers
:members:
:special-members:

0 comments on commit fe5a6f1

Please sign in to comment.