mirror of https://github.com/mamba-org/mamba.git
More specs bindings (#3080)
* Bind archive * Minor specs::Version improvements * Bind specs::Version * Bind VersionSpec * Use alias
This commit is contained in:
parent
32961e93c2
commit
2d85759c13
|
@ -32,13 +32,13 @@ namespace mamba::specs
|
|||
VersionPartAtom(std::size_t numeral, std::string_view literal);
|
||||
// The use of a template is only meant to prevent ambiguous conversions
|
||||
template <typename Char>
|
||||
VersionPartAtom(std::size_t numeral, std::basic_string<Char>&& literal);
|
||||
VersionPartAtom(std::size_t numeral, std::basic_string<Char> literal);
|
||||
|
||||
auto numeral() const noexcept -> std::size_t;
|
||||
auto literal() const& noexcept -> const std::string&;
|
||||
[[nodiscard]] auto numeral() const noexcept -> std::size_t;
|
||||
[[nodiscard]] auto literal() const& noexcept -> const std::string&;
|
||||
auto literal() && noexcept -> std::string;
|
||||
|
||||
auto str() const -> std::string;
|
||||
[[nodiscard]] auto str() const -> std::string;
|
||||
|
||||
auto operator==(const VersionPartAtom& other) const -> bool;
|
||||
auto operator!=(const VersionPartAtom& other) const -> bool;
|
||||
|
@ -54,7 +54,7 @@ namespace mamba::specs
|
|||
std::size_t m_numeral = 0;
|
||||
};
|
||||
|
||||
extern template VersionPartAtom::VersionPartAtom(std::size_t, std::string&&);
|
||||
extern template VersionPartAtom::VersionPartAtom(std::size_t, std::string);
|
||||
|
||||
/**
|
||||
* A sequence of VersionPartAtom meant to represent a part of a version (e.g. major, minor).
|
||||
|
@ -104,7 +104,7 @@ namespace mamba::specs
|
|||
|
||||
/** Construct version ``0.0``. */
|
||||
Version() noexcept = default;
|
||||
Version(std::size_t epoch, CommonVersion&& version, CommonVersion&& local = {}) noexcept;
|
||||
Version(std::size_t epoch, CommonVersion version, CommonVersion local = {}) noexcept;
|
||||
|
||||
[[nodiscard]] auto epoch() const noexcept -> std::size_t;
|
||||
[[nodiscard]] auto version() const noexcept -> const CommonVersion&;
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include <optional>
|
||||
#include <tuple>
|
||||
|
||||
#include "mamba/core/error_handling.hpp"
|
||||
#include "mamba/specs/version.hpp"
|
||||
#include "mamba/util/cast.hpp"
|
||||
#include "mamba/util/string.hpp"
|
||||
|
@ -65,13 +64,13 @@ namespace mamba::specs
|
|||
}
|
||||
|
||||
template <typename Char>
|
||||
VersionPartAtom::VersionPartAtom(std::size_t numeral, std::basic_string<Char>&& literal)
|
||||
VersionPartAtom::VersionPartAtom(std::size_t numeral, std::basic_string<Char> literal)
|
||||
: m_literal{ util::to_lower(std::move(literal)) }
|
||||
, m_numeral{ numeral }
|
||||
{
|
||||
}
|
||||
|
||||
template VersionPartAtom::VersionPartAtom(std::size_t, std::string&&);
|
||||
template VersionPartAtom::VersionPartAtom(std::size_t, std::string);
|
||||
|
||||
auto VersionPartAtom::numeral() const noexcept -> std::size_t
|
||||
{
|
||||
|
@ -180,7 +179,7 @@ namespace mamba::specs
|
|||
* Implementation of Version *
|
||||
*******************************/
|
||||
|
||||
Version::Version(std::size_t epoch, CommonVersion&& version, CommonVersion&& local) noexcept
|
||||
Version::Version(std::size_t epoch, CommonVersion version, CommonVersion local) noexcept
|
||||
: m_version{ std::move(version) }
|
||||
, m_local{ std::move(local) }
|
||||
, m_epoch{ epoch }
|
||||
|
|
|
@ -263,11 +263,6 @@ bind_submodule_impl(pybind11::module_ m)
|
|||
{
|
||||
using namespace mamba;
|
||||
|
||||
py::class_<specs::Version>(m, "Version")
|
||||
.def_static("parse", &specs::Version::parse)
|
||||
.def("__str__", &specs::Version::str);
|
||||
|
||||
|
||||
// declare earlier to avoid C++ types in docstrings
|
||||
auto pyPackageInfo = py::class_<PackageInfo>(m, "PackageInfo");
|
||||
auto pyPrefixData = py::class_<PrefixData>(m, "PrefixData");
|
||||
|
|
|
@ -8,17 +8,23 @@
|
|||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl_bind.h>
|
||||
|
||||
#include "mamba/specs/archive.hpp"
|
||||
#include "mamba/specs/authentication_info.hpp"
|
||||
#include "mamba/specs/channel.hpp"
|
||||
#include "mamba/specs/channel_spec.hpp"
|
||||
#include "mamba/specs/conda_url.hpp"
|
||||
#include "mamba/specs/platform.hpp"
|
||||
#include "mamba/specs/version.hpp"
|
||||
#include "mamba/specs/version_spec.hpp"
|
||||
|
||||
#include "bindings.hpp"
|
||||
#include "flat_set_caster.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "weakening_map_bind.hpp"
|
||||
|
||||
PYBIND11_MAKE_OPAQUE(mamba::specs::VersionPart);
|
||||
PYBIND11_MAKE_OPAQUE(mamba::specs::CommonVersion);
|
||||
|
||||
namespace mambapy
|
||||
{
|
||||
void bind_submodule_specs(pybind11::module_ m)
|
||||
|
@ -26,6 +32,26 @@ namespace mambapy
|
|||
namespace py = pybind11;
|
||||
using namespace mamba::specs;
|
||||
|
||||
m.def("archive_extensions", []() { return ARCHIVE_EXTENSIONS; });
|
||||
|
||||
m.def(
|
||||
"has_archive_extension",
|
||||
[](std::string_view str) { return has_archive_extension(str); }
|
||||
);
|
||||
m.def(
|
||||
"has_archive_extension",
|
||||
[](const mamba::fs::u8path& p) { return has_archive_extension(p); }
|
||||
);
|
||||
|
||||
m.def(
|
||||
"strip_archive_extension",
|
||||
[](std::string_view str) { return strip_archive_extension(str); }
|
||||
);
|
||||
m.def(
|
||||
"strip_archive_extension",
|
||||
[](const mamba::fs::u8path& p) { return strip_archive_extension(p); }
|
||||
);
|
||||
|
||||
py::enum_<Platform>(m, "Platform")
|
||||
.value("noarch", Platform::noarch)
|
||||
.value("linux_32", Platform::linux_32)
|
||||
|
@ -285,7 +311,7 @@ namespace mambapy
|
|||
py::arg("type") = ChannelSpec::Type::Unknown
|
||||
)
|
||||
.def("__copy__", ©<ChannelSpec>)
|
||||
.def("__deepcopy__", &deepcopy<ChannelSpec>, pybind11::arg("memo"))
|
||||
.def("__deepcopy__", &deepcopy<ChannelSpec>, py::arg("memo"))
|
||||
.def_property_readonly("type", &ChannelSpec::type)
|
||||
.def_property_readonly("location", &ChannelSpec::location)
|
||||
.def_property_readonly("platform_filters", &ChannelSpec::platform_filters);
|
||||
|
@ -309,7 +335,7 @@ namespace mambapy
|
|||
.def(py::self == py::self)
|
||||
.def(py::self != py::self)
|
||||
.def("__copy__", ©<BasicHTTPAuthentication>)
|
||||
.def("__deepcopy__", &deepcopy<BasicHTTPAuthentication>, pybind11::arg("memo"))
|
||||
.def("__deepcopy__", &deepcopy<BasicHTTPAuthentication>, py::arg("memo"))
|
||||
.def("__hash__", &hash<BasicHTTPAuthentication>);
|
||||
|
||||
py::class_<BearerToken>(m, "BearerToken")
|
||||
|
@ -321,7 +347,7 @@ namespace mambapy
|
|||
.def(py::self == py::self)
|
||||
.def(py::self != py::self)
|
||||
.def("__copy__", ©<BearerToken>)
|
||||
.def("__deepcopy__", &deepcopy<BearerToken>, pybind11::arg("memo"))
|
||||
.def("__deepcopy__", &deepcopy<BearerToken>, py::arg("memo"))
|
||||
.def("__hash__", &hash<BearerToken>);
|
||||
|
||||
py::class_<CondaToken>(m, "CondaToken")
|
||||
|
@ -333,7 +359,7 @@ namespace mambapy
|
|||
.def(py::self == py::self)
|
||||
.def(py::self != py::self)
|
||||
.def("__copy__", ©<CondaToken>)
|
||||
.def("__deepcopy__", &deepcopy<CondaToken>, pybind11::arg("memo"))
|
||||
.def("__deepcopy__", &deepcopy<CondaToken>, py::arg("memo"))
|
||||
.def("__hash__", &hash<CondaToken>);
|
||||
|
||||
bind_weakening_map<AuthenticationDataBase>(m, "AuthenticationDataBase");
|
||||
|
@ -384,7 +410,7 @@ namespace mambapy
|
|||
.def_readwrite("home_dir", &ChannelResolveParams::home_dir)
|
||||
.def_readwrite("current_working_dir", &ChannelResolveParams::current_working_dir)
|
||||
.def("__copy__", ©<BasicHTTPAuthentication>)
|
||||
.def("__deepcopy__", &deepcopy<BasicHTTPAuthentication>, pybind11::arg("memo"));
|
||||
.def("__deepcopy__", &deepcopy<BasicHTTPAuthentication>, py::arg("memo"));
|
||||
|
||||
py_channel //
|
||||
.def_property_readonly_static(
|
||||
|
@ -453,9 +479,83 @@ namespace mambapy
|
|||
.def("contains_equivalent", &Channel::contains_equivalent)
|
||||
.def(py::self == py::self)
|
||||
.def(py::self != py::self)
|
||||
.def(py::self != py::self)
|
||||
.def("__hash__", &hash<Channel>)
|
||||
.def("__copy__", ©<Channel>)
|
||||
.def("__deepcopy__", &deepcopy<Channel>, pybind11::arg("memo"));
|
||||
.def("__deepcopy__", &deepcopy<Channel>, py::arg("memo"));
|
||||
|
||||
py::class_<VersionPartAtom>(m, "VersionPartAtom")
|
||||
.def(py::init<>())
|
||||
.def(py::init<std::size_t, std::string_view>(), py::arg("numeral"), py::arg("literal") = "")
|
||||
.def_property_readonly("numeral", &VersionPartAtom::numeral)
|
||||
.def_property_readonly(
|
||||
"literal",
|
||||
[](const VersionPartAtom& atom) { return atom.literal(); }
|
||||
)
|
||||
.def("__str__", &VersionPartAtom::str)
|
||||
.def(py::self == py::self)
|
||||
.def(py::self != py::self)
|
||||
.def(py::self < py::self)
|
||||
.def(py::self <= py::self)
|
||||
.def(py::self > py::self)
|
||||
.def(py::self >= py::self)
|
||||
.def("__copy__", ©<VersionPartAtom>)
|
||||
.def("__deepcopy__", &deepcopy<VersionPartAtom>, py::arg("memo"));
|
||||
|
||||
// Type made opaque at the top of this file
|
||||
py::bind_vector<VersionPart>(m, "VersionPart");
|
||||
|
||||
// Type made opaque at the top of this file
|
||||
py::bind_vector<CommonVersion>(m, "CommonVersion");
|
||||
|
||||
py::class_<Version>(m, "Version")
|
||||
.def_readonly_static("epoch_delim", &Version::epoch_delim)
|
||||
.def_readonly_static("local_delim", &Version::local_delim)
|
||||
.def_readonly_static("part_delim", &Version::part_delim)
|
||||
.def_readonly_static("part_delim_alt", &Version::part_delim_alt)
|
||||
.def_readonly_static("part_delim_special", &Version::part_delim_special)
|
||||
.def_static("parse", &Version::parse, py::arg("str"))
|
||||
.def(
|
||||
py::init<std::size_t, CommonVersion, CommonVersion>(),
|
||||
py::arg("epoch") = 0,
|
||||
py::arg("version") = CommonVersion(),
|
||||
py::arg("local") = CommonVersion()
|
||||
)
|
||||
.def_property_readonly("epoch", &Version::epoch)
|
||||
.def_property_readonly("version", &Version::version)
|
||||
.def_property_readonly("local", &Version::local)
|
||||
.def("starts_with", &Version::starts_with, py::arg("prefix"))
|
||||
.def("compatible_with", &Version::compatible_with, py::arg("older"), py::arg("level"))
|
||||
.def("__str__", &Version::str)
|
||||
.def(py::self == py::self)
|
||||
.def(py::self != py::self)
|
||||
.def(py::self < py::self)
|
||||
.def(py::self <= py::self)
|
||||
.def(py::self > py::self)
|
||||
.def(py::self >= py::self)
|
||||
.def("__copy__", ©<Version>)
|
||||
.def("__deepcopy__", &deepcopy<Version>, py::arg("memo"));
|
||||
|
||||
// Bindings for VersionSpec currently ignores VersionPredicate and flat_bool_expr_tree
|
||||
// which would be tedious to bind, and even more to make extendable through Python
|
||||
|
||||
py::class_<VersionSpec>(m, "VersionSpec")
|
||||
.def_readonly_static("and_token", &VersionSpec::and_token)
|
||||
.def_readonly_static("or_token", &VersionSpec::or_token)
|
||||
.def_readonly_static("left_parenthesis_token", &VersionSpec::left_parenthesis_token)
|
||||
.def_readonly_static("right_parenthesis_token", &VersionSpec::right_parenthesis_token)
|
||||
.def_readonly_static("starts_with_str", &VersionSpec::starts_with_str)
|
||||
.def_readonly_static("equal_str", &VersionSpec::equal_str)
|
||||
.def_readonly_static("not_equal_str", &VersionSpec::not_equal_str)
|
||||
.def_readonly_static("greater_str", &VersionSpec::greater_str)
|
||||
.def_readonly_static("greater_equal_str", &VersionSpec::greater_equal_str)
|
||||
.def_readonly_static("less_str", &VersionSpec::less_str)
|
||||
.def_readonly_static("less_equal_str", &VersionSpec::less_equal_str)
|
||||
.def_readonly_static("compatible_str", &VersionSpec::compatible_str)
|
||||
.def_readonly_static("glob_suffix_str", &VersionSpec::glob_suffix_str)
|
||||
.def_readonly_static("glob_suffix_token", &VersionSpec::glob_suffix_token)
|
||||
.def_static("parse", &VersionSpec::parse, py::arg("str"))
|
||||
.def("contains", &VersionSpec::contains, py::arg("point"))
|
||||
.def("__copy__", ©<VersionSpec>)
|
||||
.def("__deepcopy__", &deepcopy<VersionSpec>, py::arg("memo"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,16 @@ def test_import_recursive():
|
|||
_p = mamba.specs.Platform.noarch
|
||||
|
||||
|
||||
def test_archive_extension():
|
||||
assert libmambapy.specs.archive_extensions() == [".tar.bz2", ".conda"]
|
||||
|
||||
assert libmambapy.specs.has_archive_extension("pkg.conda")
|
||||
assert not libmambapy.specs.has_archive_extension("conda.pkg")
|
||||
|
||||
assert libmambapy.specs.strip_archive_extension("pkg.conda") == "pkg"
|
||||
assert libmambapy.specs.strip_archive_extension("conda.pkg") == "conda.pkg"
|
||||
|
||||
|
||||
def test_Platform():
|
||||
Platform = libmambapy.specs.Platform
|
||||
|
||||
|
@ -515,3 +525,130 @@ def test_Channel_resolve():
|
|||
)
|
||||
assert len(chans) == 2
|
||||
assert {c.display_name for c in chans} == {"best-forge", "conda-forge"}
|
||||
|
||||
|
||||
def test_VersionPartAtom():
|
||||
VersionPartAtom = libmambapy.specs.VersionPartAtom
|
||||
|
||||
a = VersionPartAtom(numeral=1, literal="alpha")
|
||||
|
||||
# Getters
|
||||
assert a.numeral == 1
|
||||
assert a.literal == "alpha"
|
||||
assert str(a) == "1alpha"
|
||||
|
||||
# Comparison
|
||||
b = VersionPartAtom(2)
|
||||
assert a == a
|
||||
assert a != b
|
||||
assert a <= a
|
||||
assert a <= b
|
||||
assert a < b
|
||||
assert a >= a
|
||||
assert b >= a
|
||||
assert b > a
|
||||
|
||||
# Copy
|
||||
assert copy.deepcopy(a) == a
|
||||
|
||||
|
||||
def test_VersionPart():
|
||||
VersionPartAtom = libmambapy.specs.VersionPartAtom
|
||||
VersionPart = libmambapy.specs.VersionPart
|
||||
|
||||
p = VersionPart([VersionPartAtom(1, "a"), VersionPartAtom(3)])
|
||||
assert len(p) == 2
|
||||
|
||||
|
||||
def test_CommonVersion():
|
||||
VersionPartAtom = libmambapy.specs.VersionPartAtom
|
||||
VersionPart = libmambapy.specs.VersionPart
|
||||
CommonVersion = libmambapy.specs.CommonVersion
|
||||
|
||||
p = VersionPart([VersionPartAtom(1, "a"), VersionPartAtom(3)])
|
||||
v = CommonVersion([p, p])
|
||||
assert len(v) == 2
|
||||
|
||||
|
||||
def test_Version():
|
||||
VersionPartAtom = libmambapy.specs.VersionPartAtom
|
||||
VersionPart = libmambapy.specs.VersionPart
|
||||
CommonVersion = libmambapy.specs.CommonVersion
|
||||
Version = libmambapy.specs.Version
|
||||
|
||||
# Static data
|
||||
assert isinstance(Version.epoch_delim, str)
|
||||
assert isinstance(Version.local_delim, str)
|
||||
assert isinstance(Version.part_delim, str)
|
||||
assert isinstance(Version.part_delim_alt, str)
|
||||
assert isinstance(Version.part_delim_special, str)
|
||||
|
||||
# Parse
|
||||
v = Version.parse("3!1.3ab2.4+42.0alpha")
|
||||
|
||||
# Getters
|
||||
assert v.epoch == 3
|
||||
assert v.version == CommonVersion(
|
||||
[
|
||||
VersionPart([VersionPartAtom(1)]),
|
||||
VersionPart([VersionPartAtom(3, "ab"), VersionPartAtom(2)]),
|
||||
VersionPart([VersionPartAtom(4)]),
|
||||
]
|
||||
)
|
||||
assert v.local == CommonVersion(
|
||||
[
|
||||
VersionPart([VersionPartAtom(42)]),
|
||||
VersionPart([VersionPartAtom(0, "alpha")]),
|
||||
]
|
||||
)
|
||||
|
||||
# str
|
||||
assert str(v) == "3!1.3ab2.4+42.0alpha"
|
||||
|
||||
# Copy
|
||||
assert copy.deepcopy(v) == v
|
||||
|
||||
# Comparison
|
||||
v1 = Version.parse("1.0.1")
|
||||
v2 = Version.parse("1.2.3alpha2")
|
||||
assert v1 == v1
|
||||
assert v1 != v2
|
||||
assert v1 <= v1
|
||||
assert v1 <= v2
|
||||
assert v2 >= v1
|
||||
assert v2 >= v2
|
||||
assert v2 > v1
|
||||
assert v1.starts_with(Version.parse("1.0"))
|
||||
assert not v1.starts_with(v2)
|
||||
assert v2.compatible_with(older=v1, level=1)
|
||||
assert not v2.compatible_with(older=v1, level=2)
|
||||
assert not v1.compatible_with(older=v2, level=1)
|
||||
|
||||
|
||||
def test_VersionSpec():
|
||||
Version = libmambapy.specs.Version
|
||||
VersionSpec = libmambapy.specs.VersionSpec
|
||||
|
||||
# Static data
|
||||
assert isinstance(VersionSpec.and_token, str)
|
||||
assert isinstance(VersionSpec.or_token, str)
|
||||
assert isinstance(VersionSpec.left_parenthesis_token, str)
|
||||
assert isinstance(VersionSpec.right_parenthesis_token, str)
|
||||
assert isinstance(VersionSpec.starts_with_str, str)
|
||||
assert isinstance(VersionSpec.equal_str, str)
|
||||
assert isinstance(VersionSpec.not_equal_str, str)
|
||||
assert isinstance(VersionSpec.greater_str, str)
|
||||
assert isinstance(VersionSpec.greater_equal_str, str)
|
||||
assert isinstance(VersionSpec.less_str, str)
|
||||
assert isinstance(VersionSpec.less_equal_str, str)
|
||||
assert isinstance(VersionSpec.compatible_str, str)
|
||||
assert isinstance(VersionSpec.glob_suffix_str, str)
|
||||
assert isinstance(VersionSpec.glob_suffix_token, str)
|
||||
|
||||
vs = VersionSpec.parse(">2.0,<3.0")
|
||||
|
||||
assert not vs.contains(Version.parse("1.1"))
|
||||
assert vs.contains(Version.parse("2.1"))
|
||||
|
||||
# Copy
|
||||
copy.deepcopy(vs) # No easy comaprison
|
||||
|
|
|
@ -2,6 +2,5 @@ import libmambapy
|
|||
|
||||
|
||||
def test_version():
|
||||
ver_str = "1.0"
|
||||
ver = libmambapy.Version.parse(ver_str)
|
||||
assert str(ver) == ver_str
|
||||
assert isinstance(libmambapy.__version__, str)
|
||||
assert libmambapy.version.__version__ == libmambapy.__version__
|
||||
|
|
Loading…
Reference in New Issue