-
Notifications
You must be signed in to change notification settings - Fork 1
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 "provides" package metadata. #194
Changes from 6 commits
6d02c2f
e6b0dda
2d94753
56b8166
34a6d7d
c262432
f639e0f
552fb35
b109360
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
class ConstraintKinds(enum.Enum): | ||
install_requires = 'install_requires' | ||
conflicts = 'conflicts' | ||
provides = 'provides' | ||
|
||
|
||
class IRepositoryInfo(six.with_metaclass(abc.ABCMeta)): | ||
|
@@ -62,7 +63,8 @@ def _from_pretty_string(cls, s): | |
parser = PrettyPackageStringParser(EnpkgVersion.from_string) | ||
return parser.parse_to_package(s) | ||
|
||
def __init__(self, name, version, install_requires=None, conflicts=None): | ||
def __init__(self, name, version, install_requires=None, conflicts=None, | ||
provides=None): | ||
""" Return a new PackageMetdata object. | ||
|
||
Parameters | ||
|
@@ -85,15 +87,24 @@ def __init__(self, name, version, install_requires=None, conflicts=None): | |
(("MKL", ((">= 10.1", "< 11"),)), | ||
("nose", (("*",),)), | ||
("six", (("> 1.2", "<= 1.2.3"), (">= 1.2.5-2",))) | ||
|
||
conflicts : tuple(tuple(str, tuple(tuple(str)))) | ||
A tuple of tuples mapping distribution names to disjunctions of | ||
conjunctions of version constraints. | ||
|
||
This works the same way as install_requires, but instead denotes | ||
packages that must *not* be installed with this package. | ||
provides : iterable of package names | ||
The packages that are provided by this distribution. Useful when | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This makes it sounds like only the names of actual packages can be specified. From the examples, it looks like this could be an arbitrary label listed as a requirement. Is this purely a semantic difference? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed a package can There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In fact, this docstring is out of date, since the provides are also in the "constraint tuple" format. |
||
this does not match the package name. | ||
|
||
For example, a package ``foo`` is abandoned by its maintainer and a | ||
fork ``bar`` is created to continue development. If ``bar`` is | ||
intended to be a transparent replacement for ``foo``, then ``bar`` | ||
`provides` ``foo``. | ||
|
||
""" | ||
self._name = name | ||
self._provides = tuple(provides or ()) | ||
self._version = version | ||
self._install_requires = install_requires or () | ||
self._conflicts = conflicts or () | ||
|
@@ -104,6 +115,12 @@ def __init__(self, name, version, install_requires=None, conflicts=None): | |
def name(self): | ||
return self._name | ||
|
||
@property | ||
def provides(self): | ||
constraint_str = "*" | ||
this_pkg = ((self._name, ((constraint_str,),)),) | ||
return this_pkg + self._provides | ||
|
||
@property | ||
def version(self): | ||
return self._version | ||
|
@@ -124,10 +141,16 @@ def __hash__(self): | |
return self._hash | ||
|
||
def __eq__(self, other): | ||
return self._key == other._key | ||
try: | ||
return self._key == other._key | ||
except AttributeError: | ||
return NotImplemented | ||
|
||
def __ne__(self, other): | ||
return self._key != other._key | ||
try: | ||
return self._key != other._key | ||
except AttributeError: | ||
return NotImplemented | ||
|
||
|
||
class RepositoryPackageMetadata(object): | ||
|
@@ -147,6 +170,10 @@ def __init__(self, package, repository_info): | |
def name(self): | ||
return self._package.name | ||
|
||
@property | ||
def provides(self): | ||
return self._package.provides | ||
|
||
@property | ||
def version(self): | ||
return self._package.version | ||
|
@@ -173,7 +200,13 @@ def __hash__(self): | |
return self._hash | ||
|
||
def __eq__(self, other): | ||
return self._key == other._key | ||
try: | ||
return self._key == other._key | ||
except AttributeError: | ||
return NotImplemented | ||
|
||
def __ne__(self, other): | ||
return self._key != other._key | ||
try: | ||
return self._key != other._key | ||
except AttributeError: | ||
return NotImplemented |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
from __future__ import absolute_import | ||
|
||
from .utils import DefaultOrderedDict | ||
from simplesat.constraints import modify_requirement | ||
from simplesat.constraints import ( | ||
ConstraintModifiers, Requirement, modify_requirement | ||
) | ||
|
||
|
||
class Pool(object): | ||
|
@@ -47,7 +49,10 @@ def add_repository(self, repository): | |
self._id += 1 | ||
self._id_to_package_[current_id] = package | ||
self._package_to_id_[package] = current_id | ||
self._packages_by_name_[package.name].append(package) | ||
for constraints in package.provides: | ||
req = Requirement.from_constraints(constraints) | ||
assert not req.has_any_version_constraint | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you explain this assertion? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah yes, I forgot to write about it. Really we need to move the entire package metadata spec into the docs here. The long and short of it is that right now we don't have a good way to handle provides with version numbers. We might someday, but there aren't any good use-cases that I know of. This assertion is there to make sure package metadata authors haven't done that. It should probably be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This does sound like an |
||
self._packages_by_name_[req.name].append(package) | ||
|
||
def what_provides(self, requirement, use_modifiers=True): | ||
""" Computes the list of packages fulfilling the given | ||
|
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.
How is this different from "provides with version numbers"?
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.
This is only testing our ability to parse, which separates the clauses and builds constraint tuples, but doesn't validate. In general we don't validate things up front due to the overhead of parsing version objects and the sheer number of packages. Also, we will not be parsing pretty strings during a normal work flow. IThe program which is using
simplesat
as a library will construct package metadata directly (which is why we guard against it below this level).