Skip to content

Commit

Permalink
Merge pull request #14 from dstufft/rearrange-specifiers
Browse files Browse the repository at this point in the history
Move specifier support into packaging.specifiers
  • Loading branch information
dstufft committed Oct 6, 2014
2 parents 51c984b + 9270fb4 commit 9542495
Show file tree
Hide file tree
Showing 8 changed files with 1,253 additions and 1,184 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ Changelog

.. note:: This version is not yet released and is under active development.

* **BACKWARDS INCOMPATIBLE** Move the specifier support out of
``packaging.version`` into ``packaging.specifiers``.


14.2 - 2014-09-10
~~~~~~~~~~~~~~~~~
Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ API
:maxdepth: 1

version
specifiers


Project
Expand Down
115 changes: 115 additions & 0 deletions docs/specifiers.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
Specifiers
==========

.. currentmodule:: packaging.specifiers

A core requirement of dealing with dependency 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.

Usage
-----

.. doctest::

>>> from packaging.specifiers import Specifier
>>> from packaging.version import Version
>>> spec1 = Specifier("~=1.0")
>>> spec1
<Specifier('~=1.0')>
>>> spec2 = Specifier(">=1.0")
>>> spec2
<Specifier('>=1.0')>
>>> # We can combine specifiers
>>> combined_spec = spec1 & spec2
>>> combined_spec
<Specifier('>=1.0,~=1.0')>
>>> # We can also implicitly combine a string specifier
>>> combined_spec &= "!=1.1"
>>> combined_spec
<Specifier('!=1.1,>=1.0,~=1.0')>
>>> # Create a few versions to check for contains.
>>> v1 = Version("1.0a5")
>>> v2 = Version("1.0")
>>> # We can check a version object to see if it falls within a specifier
>>> combined_spec.contains(v1)
False
>>> combined_spec.contains(v2)
True
>>> # We can even do the same with a string based version
>>> combined_spec.contains("1.4")
True
>>> # Finally we can filter a list of versions to get only those which are
>>> # contained within our specifier.
>>> list(combined_spec.filter([v1, v2, "1.4"]))
[<Version('1.0')>, '1.4']


Reference
---------

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

This class abstracts handling of specifying the dependencies of a project.
It implements the scheme defined in `PEP 440`_. You may combine Specifier
instances using the ``&`` operator (``Specifier(">2") & Specifier(">3")``).

Both the membership test and the combination supports using raw strings
in place of already instantiated objects.

: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:: prereleases

A boolean value indicating whether this :class:`Specifier` represents
a specifier that includesa 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, prereleases=None)

Determines if ``version``, which can be either a version string, a
:class:`Version`, or a :class:`LegacyVersion` object, is contained
within this specifier.

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:: filter(iterable, prereleases=None)

Takes an iterable that can contain version strings, :class:`Version`,
and :class:`LegacyVersion` instances and will then filter it, 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.


.. 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/
92 changes: 1 addition & 91 deletions docs/version.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Usage

.. doctest::

>>> from packaging.version import Version, Specifier, parse
>>> from packaging.version import Version, parse
>>> v1 = parse("1.0a5")
>>> v2 = Version("1.0")
>>> v1
Expand All @@ -29,32 +29,6 @@ Usage
Traceback (most recent call last):
...
InvalidVersion: Invalid version: 'french toast'
>>> spec1 = Specifier("~=1.0")
>>> spec1
<Specifier('~=1.0')>
>>> spec2 = Specifier(">=1.0")
>>> spec2
<Specifier('>=1.0')>
>>> # We can combine specifiers
>>> combined_spec = spec1 & spec2
>>> combined_spec
<Specifier('>=1.0,~=1.0')>
>>> # We can also implicitly combine a string specifier
>>> combined_spec &= "!=1.1"
>>> combined_spec
<Specifier('!=1.1,>=1.0,~=1.0')>
>>> # We can check a version object to see if it falls within a specifier
>>> combined_spec.contains(v1)
False
>>> combined_spec.contains(v2)
True
>>> # We can even do the same with a string based version
>>> combined_spec.contains("1.4")
True
>>> # Finally we can filter a list of versions to get only those which are
>>> # contained within our specifier.
>>> list(combined_spec.filter([v1, v2, "1.4"]))
[<Version('1.0')>, '1.4']


Reference
Expand Down Expand Up @@ -125,74 +99,10 @@ Reference
`False` and exists for compatibility with :class:`Version`.


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

This class abstracts handling of specifying the dependencies of a project.
It implements the scheme defined in `PEP 440`_. You may combine Specifier
instances using the ``&`` operator (``Specifier(">2") & Specifier(">3")``).

Both the membership test and the combination supports using raw strings
in place of already instantiated objects.

: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:: prereleases

A boolean value indicating whether this :class:`Specifier` represents
a specifier that includesa 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, prereleases=None)

Determines if ``version``, which can be either a version string, a
:class:`Version`, or a :class:`LegacyVersion` object, is contained
within this specifier.

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:: filter(iterable, prereleases=None)

Takes an iterable that can contain version strings, :class:`Version`,
and :class:`LegacyVersion` instances and will then filter it, 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.


.. exception:: InvalidVersion

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


.. 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/
Loading

0 comments on commit 9542495

Please sign in to comment.