-
Notifications
You must be signed in to change notification settings - Fork 251
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
PEP 440 Implementation #1
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
7a194d1
Require 100% test coverage
dstufft fbd039c
Implement PEP 440 versions
dstufft 55c58bc
Implement PEP 440 specifiers
dstufft edb18dd
Create an invoke task to check PEP440 compliance with PyPI
dstufft c96bae1
Allow alternative syntax for backwards compatability
dstufft 8fc910b
Allow identity comparisons, even for non PEP 440 compliant versions
dstufft 77eee20
Normalize post releases like pre-releases and development releases
dstufft 4b016f0
Do not throw away trailing digits for representation
dstufft 314effa
Fix the normalization of letter versions and local versions
dstufft 6e3268a
Switch from : to ! to denote an Epoch
dstufft c26a427
Allow empty specifiers
dstufft 854565a
Implement LegacyVersion which can support arbitrary versions
dstufft 38ddbb1
Rename identity to arbitrary and assure it operates on strings
dstufft a356cc9
Refactor normalization to handle LegacyVersion
dstufft 4fc2f3e
Relax the syntax of versions to better parse more versions
dstufft 8de22d1
Allow the implicit post release syntax (e.g. 1.0-5)
dstufft 44aec39
Make the invoke tasks run on Python 2.x as well as Python 3.x
dstufft File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
[run] | ||
branch = True | ||
branch = True | ||
omit = packaging/_compat.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
Version Handling | ||
================ | ||
|
||
.. currentmodule:: packaging.version | ||
|
||
A core requirement of dealing with packages is the ability to work with | ||
versions. `PEP 440`_ defines the standard version scheme for Python packages | ||
which has been implemented by this module. | ||
|
||
Usage | ||
----- | ||
|
||
.. doctest:: | ||
|
||
>>> from packaging.version import Version, Specifier | ||
>>> v1 = Version("1.0a5") | ||
>>> v2 = Version("1.0") | ||
>>> v1 | ||
<Version('1.0a5')> | ||
>>> v2 | ||
<Version('1.0')> | ||
>>> v1 < v2 | ||
True | ||
>>> v1.is_prerelease | ||
True | ||
>>> v2.is_prerelease | ||
False | ||
>>> Version("french toast") | ||
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 | ||
>>> v1 in combined_spec | ||
False | ||
>>> v2 in combined_spec | ||
True | ||
>>> # We can even do the same with a string based version | ||
>>> "1.4" in combined_spec | ||
True | ||
|
||
|
||
Reference | ||
--------- | ||
|
||
.. class:: Version(version) | ||
|
||
This class abstracts handling of a project's versions. It implements the | ||
scheme defined in `PEP 440`_. A :class:`Version` instance is comparison | ||
aware and can be compared and sorted using the standard Python interfaces. | ||
|
||
:param str version: The string representation of a version which will be | ||
parsed and normalized before use. | ||
:raises InvalidVersion: If the ``version`` does not conform to PEP 440 in | ||
any way then this exception will be raised. | ||
|
||
.. attribute:: public | ||
|
||
A string representing the public version portion of this ``Version()``. | ||
|
||
.. attribute:: local | ||
|
||
A string representing the local version portion of this ``Version()`` | ||
if it has one, or ``None`` otherwise. | ||
|
||
.. attribute:: is_prerelease | ||
|
||
A boolean value indicating whether this :class:`Version` instance | ||
represents a prerelease or a final release. | ||
|
||
|
||
.. class:: LegacyVersion(version) | ||
|
||
This class abstracts handling of a project's versions if they are not | ||
compatible with the scheme defined in `PEP 440`_. It implements a similar | ||
interface to that of :class:`Version` however it is considered unorderable | ||
and many of the comparison types are not implemented. | ||
|
||
:param str version: The string representation of a version which will be | ||
used as is. | ||
|
||
.. attribute:: public | ||
|
||
A string representing the public version portion of this | ||
:class:`LegacyVersion`. This will always be the entire version string. | ||
|
||
.. attribute:: local | ||
|
||
This will always be ``None`` since without `PEP 440`_ we do not have | ||
the concept of a local version. It exists primarily to allow a | ||
:class:`LegacyVersion` to be used as a stand in for a :class:`Version`. | ||
|
||
.. attribute:: is_prerelease | ||
|
||
A boolean value indicating whether this :class:`LegacyVersion` | ||
represents a prerelease or a final release. Since without `PEP 440`_ | ||
there is no concept of pre or final releases this will always be | ||
`False` and exists for compatibility with :class:`Version`. | ||
|
||
|
||
.. class:: Specifier(specifier) | ||
|
||
This class abstracts handling of specifying the dependencies of a project. | ||
It implements the scheme defined in `PEP 440`_. You can test membership | ||
of a particular version within a set of specifiers in a :class:`Specifier` | ||
instance by using the standard ``in`` operator (e.g. | ||
``Version("2.0") in Specifier("==2.0")``). You may also 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. | ||
:raises InvalidSpecifier: If the ``specifier`` does not conform to PEP 440 | ||
in any way then this exception will be raised. | ||
|
||
|
||
.. class:: InvalidVersion | ||
|
||
Raised when attempting to create a :class:`Version` with a version string | ||
that does not conform to `PEP 440`_. | ||
|
||
|
||
.. class:: 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/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Copyright 2014 Donald Stufft | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
from __future__ import absolute_import, division, print_function | ||
|
||
import sys | ||
|
||
|
||
PY2 = sys.version_info[0] == 2 | ||
PY3 = sys.version_info[0] == 3 | ||
|
||
# flake8: noqa | ||
|
||
if PY3: | ||
string_types = str, | ||
else: | ||
string_types = basestring, |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
# Copyright 2014 Donald Stufft | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
from __future__ import absolute_import, division, print_function | ||
|
||
|
||
class Infinity(object): | ||
|
||
def __repr__(self): | ||
return "Infinity" | ||
|
||
def __hash__(self): | ||
return hash(repr(self)) | ||
|
||
def __lt__(self, other): | ||
return False | ||
|
||
def __le__(self, other): | ||
return False | ||
|
||
def __eq__(self, other): | ||
return isinstance(other, self.__class__) | ||
|
||
def __ne__(self, other): | ||
return not isinstance(other, self.__class__) | ||
|
||
def __gt__(self, other): | ||
return True | ||
|
||
def __ge__(self, other): | ||
return True | ||
|
||
def __neg__(self): | ||
return NegativeInfinity | ||
|
||
Infinity = Infinity() | ||
|
||
|
||
class NegativeInfinity(object): | ||
|
||
def __repr__(self): | ||
return "-Infinity" | ||
|
||
def __hash__(self): | ||
return hash(repr(self)) | ||
|
||
def __lt__(self, other): | ||
return True | ||
|
||
def __le__(self, other): | ||
return True | ||
|
||
def __eq__(self, other): | ||
return isinstance(other, self.__class__) | ||
|
||
def __ne__(self, other): | ||
return not isinstance(other, self.__class__) | ||
|
||
def __gt__(self, other): | ||
return False | ||
|
||
def __ge__(self, other): | ||
return False | ||
|
||
def __neg__(self): | ||
return Infinity | ||
|
||
NegativeInfinity = NegativeInfinity() |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC the things in parens in a Sphinx class definition should be base classes, not arguments for init.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
http://sphinx-doc.org/domains.html#directive-py:class seems to indicate otherwise!