Skip to content

Commit

Permalink
Enable explicitly specifying pre-releases without enabling pre-releases
Browse files Browse the repository at this point in the history
  • Loading branch information
MHendricks committed Nov 6, 2024
1 parent f0cb3ba commit 311554a
Show file tree
Hide file tree
Showing 8 changed files with 287 additions and 3 deletions.
15 changes: 12 additions & 3 deletions hab/parsers/distro.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,25 @@ def matching_versions(self, specification):
"""Returns a list of versions available matching the version specification.
See `packaging.requirements` for details on valid requirements, but it
should be the same as pip requirements.
This respects `self.resolver.prereleases`, so pre-releases will only be
returned if that is set to True or if this specification uses an
"Inclusive ordered comparison"(`<=`, `>=`) and the specification
contains any of the pre-release specifiers (`.dev1`). You will need
to enable prereleases to use "Exclusive ordered comparison"(`<`, `>`)s.
This is consistent with how pip handles these options.
"""
if isinstance(specification, Requirement):
specifier = specification.specifier
elif isinstance(specification, SpecifierSet):
specifier = specification
else:
specifier = Requirement(specification).specifier
return specifier.filter(
self.versions.keys(), prereleases=self.resolver.prereleases
)
# If a pre-release specifier was provided, it should enable pre-releases
# even if the site doesn't. This replicates explicitly passing a pre-release
# version to pip even if you don't pass `--pre`.
prereleases = self.resolver.prereleases or specifier.prereleases
return specifier.filter(self.versions.keys(), prereleases=prereleases)

@property
def versions(self):
Expand Down
19 changes: 19 additions & 0 deletions tests/distros/pre-release/1.0.dev1/.hab.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "pre-release",
"aliases": {
"windows": [
[
"pre", {
"cmd": "python"
}
]
],
"linux": [
[
"pre", {
"cmd": "python"
}
]
]
}
}
19 changes: 19 additions & 0 deletions tests/distros/pre-release/1.0/.hab.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "pre-release",
"aliases": {
"windows": [
[
"pre", {
"cmd": "python"
}
]
],
"linux": [
[
"pre", {
"cmd": "python"
}
]
]
}
}
19 changes: 19 additions & 0 deletions tests/distros/pre-release/1.1.dev2/.hab.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "pre-release",
"aliases": {
"windows": [
[
"pre", {
"cmd": "python"
}
]
],
"linux": [
[
"pre", {
"cmd": "python"
}
]
]
}
}
19 changes: 19 additions & 0 deletions tests/distros/pre-release2/1.0/.hab.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "pre-release2",
"aliases": {
"windows": [
[
"pre2", {
"cmd": "python"
}
]
],
"linux": [
[
"pre2", {
"cmd": "python"
}
]
]
}
}
19 changes: 19 additions & 0 deletions tests/distros/pre-release2/1.1.dev2/.hab.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "pre-release2",
"aliases": {
"windows": [
[
"pre2", {
"cmd": "python"
}
]
],
"linux": [
[
"pre2", {
"cmd": "python"
}
]
]
}
}
110 changes: 110 additions & 0 deletions tests/site_main_check.habcache
Original file line number Diff line number Diff line change
Expand Up @@ -1404,6 +1404,116 @@
},
"version": "2024.0"
},
"{config-root}/distros/pre-release2/1.0/.hab.json": {
"name": "pre-release2",
"aliases": {
"windows": [
[
"pre2",
{
"cmd": "python"
}
]
],
"linux": [
[
"pre2",
{
"cmd": "python"
}
]
]
},
"version": "1.0"
},
"{config-root}/distros/pre-release2/1.1.dev2/.hab.json": {
"name": "pre-release2",
"aliases": {
"windows": [
[
"pre2",
{
"cmd": "python"
}
]
],
"linux": [
[
"pre2",
{
"cmd": "python"
}
]
]
},
"version": "1.1.dev2"
},
"{config-root}/distros/pre-release/1.0.dev1/.hab.json": {
"name": "pre-release",
"aliases": {
"windows": [
[
"pre",
{
"cmd": "python"
}
]
],
"linux": [
[
"pre",
{
"cmd": "python"
}
]
]
},
"version": "1.0.dev1"
},
"{config-root}/distros/pre-release/1.0/.hab.json": {
"name": "pre-release",
"aliases": {
"windows": [
[
"pre",
{
"cmd": "python"
}
]
],
"linux": [
[
"pre",
{
"cmd": "python"
}
]
]
},
"version": "1.0"
},
"{config-root}/distros/pre-release/1.1.dev2/.hab.json": {
"name": "pre-release",
"aliases": {
"windows": [
[
"pre",
{
"cmd": "python"
}
]
],
"linux": [
[
"pre",
{
"cmd": "python"
}
]
]
},
"version": "1.1.dev2"
},
"{config-root}/distros/the_dcc/1.0/.hab.json": {
"name": "the_dcc",
"environment": {},
Expand Down
70 changes: 70 additions & 0 deletions tests/test_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from packaging.requirements import Requirement

from hab import NotSet, Resolver, Site, utils
from hab.errors import InvalidRequirementError
from hab.solvers import Solver


Expand Down Expand Up @@ -245,6 +246,13 @@ def test_distros(self, resolver):
" maya2020==2020.1",
"maya2024",
" maya2024==2024.0",
"pre-release",
" pre-release==1.0",
" pre-release==1.0.dev1",
" pre-release==1.1.dev2",
"pre-release2",
" pre-release2==1.0",
" pre-release2==1.1.dev2",
"the_dcc",
" the_dcc==1.0",
" the_dcc==1.1",
Expand Down Expand Up @@ -293,6 +301,13 @@ def test_distros_truncate(self, resolver):
" maya2020==2020.1",
"maya2024",
" maya2024==2024.0",
"pre-release",
" pre-release==1.0",
" ...",
" pre-release==1.1.dev2",
"pre-release2",
" pre-release2==1.0",
" pre-release2==1.1.dev2",
"the_dcc",
" the_dcc==1.0",
" ...",
Expand Down Expand Up @@ -563,6 +578,61 @@ def test_forced_requirements(
for i, v in enumerate(versions):
assert v.name == check_versions[i]

@pytest.mark.parametrize(
"requirements,prereleases,check",
(
# Full release requirements respect `--pre` flag
(["pre-release"], False, ["pre-release==1.0"]),
(["pre-release"], True, ["pre-release==1.1.dev2"]),
(["pre-release==1.0"], True, ["pre-release==1.0"]),
(["pre-release==1.0"], False, ["pre-release==1.0"]),
(["pre-release<=2.0"], True, ["pre-release==1.1.dev2"]),
(["pre-release<=2.0"], False, ["pre-release==1.0"]),
(["pre-release>=1.0"], True, ["pre-release==1.1.dev2"]),
(["pre-release>=1.0"], False, ["pre-release==1.0"]),
# Forced pre-release requirements will find pre-release distros
# regardless of the `--pre` flag.
(["pre-release==1.0rc99"], True, False),
(["pre-release==1.0rc99"], False, False),
(["pre-release==1.0.dev1"], True, ["pre-release==1.0.dev1"]),
(["pre-release==1.0.dev1"], False, ["pre-release==1.0.dev1"]),
(["pre-release<=1.0rc99"], True, ["pre-release==1.0.dev1"]),
(["pre-release<=1.0rc99"], False, ["pre-release==1.0.dev1"]),
# Forced pre-release requirements don't affect other requirements
# regardless of the `--pre` flag.
(
["pre-release<=1.0rc99", "pre-release2"],
False,
["pre-release==1.0.dev1", "pre-release2==1.0"],
),
(
["pre-release<=1.0rc99", "pre-release2"],
True,
["pre-release==1.0.dev1", "pre-release2==1.1.dev2"],
),
),
)
def test_pre_releases(self, habcached_resolver, requirements, prereleases, check):
"""Check how prereleases and specifying a version with prereleases works.
If the global prereleases is False, ignore any pre-release versions
unless the version specifier itself specifies a pre-release. See
`hab.parsers.distro.Distro.matching_versions` for details.
"""
habcached_resolver.prereleases = prereleases
uri = "not_set/no_distros"

if check is False:
with pytest.raises(InvalidRequirementError):
habcached_resolver.resolve(uri, forced_requirements=requirements)
else:
cfg = habcached_resolver.resolve(uri, forced_requirements=requirements)
versions = cfg.versions

assert len(versions) == len(check)
for i, v in enumerate(versions):
assert v.name == check[i]

def test_forced_requirements_uri(self, resolver, helpers):
resolver_forced = Resolver(
site=resolver.site,
Expand Down

0 comments on commit 311554a

Please sign in to comment.