MatchSpec small improvements (#3043)

* Small CQA

* Add ChannelSpec::str

* Add ChannelContext::make_channel for ChannelSpec

* Split MatchSpec tests
This commit is contained in:
Antoine Prouvost 2023-12-07 09:20:58 +01:00 committed by GitHub
parent df4aeaca4c
commit dfcb8c249e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 362 additions and 279 deletions

View File

@ -51,7 +51,8 @@ namespace mamba
*/
ChannelContext(ChannelResolveParams params, std::vector<Channel> has_zst);
auto make_channel(std::string_view name) -> const channel_list&;
[[nodiscard]] auto make_channel(specs::ChannelSpec spec) -> const channel_list&;
[[nodiscard]] auto make_channel(std::string_view name) -> const channel_list&;
[[nodiscard]] auto params() const -> const specs::ChannelResolveParams&;

View File

@ -31,7 +31,7 @@ namespace mamba
bool is_simple() const;
static std::tuple<std::string, std::string> parse_version_and_build(const std::string& s);
static std::tuple<std::string, std::string> parse_version_and_build(std::string_view s);
std::string spec;
std::string name;

View File

@ -11,6 +11,9 @@
#include <string>
#include <string_view>
#include <fmt/core.h>
#include <fmt/format.h>
#include "mamba/util/flat_set.hpp"
namespace mamba::specs
@ -98,6 +101,8 @@ namespace mamba::specs
[[nodiscard]] auto platform_filters() && -> dynamic_platform_set;
auto clear_platform_filters() -> dynamic_platform_set;
[[nodiscard]] auto str() const -> std::string;
private:
std::string m_location = std::string(unknown_channel);
@ -105,4 +110,23 @@ namespace mamba::specs
Type m_type = Type::Unknown;
};
}
template <>
struct fmt::formatter<mamba::specs::ChannelSpec>
{
using ChannelSpec = ::mamba::specs::ChannelSpec;
constexpr auto parse(format_parse_context& ctx) -> format_parse_context::iterator
{
// make sure that range is empty
if (ctx.begin() != ctx.end() && *ctx.begin() != '}')
{
throw fmt::format_error("Invalid format");
}
return ctx.begin();
}
auto format(const ChannelSpec& spec, format_context& ctx) const -> format_context::iterator;
};
#endif

View File

@ -214,6 +214,22 @@ namespace mamba
return { std::move(params), has_zst };
}
auto ChannelContext::make_channel(specs::ChannelSpec spec) -> const channel_list&
{
auto str = spec.str();
if (const auto it = m_channel_cache.find(str); it != m_channel_cache.end())
{
return it->second;
}
auto [it, inserted] = m_channel_cache.emplace(
std::move(str),
Channel::resolve(std::move(spec), params())
);
assert(inserted);
return it->second;
}
auto ChannelContext::make_channel(std::string_view name) -> const channel_list&
{
if (const auto it = m_channel_cache.find(std::string(name)); it != m_channel_cache.end())

View File

@ -41,14 +41,14 @@ namespace mamba
parse(ctx, channel_context);
}
std::tuple<std::string, std::string> MatchSpec::parse_version_and_build(const std::string& s)
std::tuple<std::string, std::string> MatchSpec::parse_version_and_build(std::string_view s)
{
std::size_t pos = s.find_last_of(" =");
std::size_t const pos = s.find_last_of(" =");
if (pos == s.npos || pos == 0)
{
std::string tmp = s;
std::string tmp = std::string(s);
util::replace_all(tmp, " ", "");
return { tmp, "" };
return { std::move(tmp), "" };
}
else
{
@ -59,17 +59,18 @@ namespace mamba
char d = s[pm1];
if (d == '=' || d == '!' || d == '|' || d == ',' || d == '<' || d == '>' || d == '~')
{
std::string tmp = s;
auto tmp = std::string(s);
util::replace_all(tmp, " ", "");
return { tmp, "" };
}
}
// c is either ' ' or pm1 is none of the forbidden chars
std::string v = s.substr(0, pos), b = s.substr(pos + 1);
auto v = std::string(s.substr(0, pos));
auto b = std::string(s.substr(pos + 1));
util::replace_all(v, " ", "");
util::replace_all(b, " ", "");
return { v, b };
return { std::move(v), std::move(b) };
}
}
@ -124,7 +125,7 @@ namespace mamba
auto extract_kv = [&spec_str](const std::string& kv_string, auto& map)
{
static std::regex kv_re("([a-zA-Z0-9_-]+?)=([\"\']?)([^\'\"]*?)(\\2)(?:[\'\", ]|$)");
static const std::regex kv_re("([a-zA-Z0-9_-]+?)=([\"\']?)([^\'\"]*?)(\\2)(?:[\'\", ]|$)");
std::cmatch kv_match;
const char* text_iter = kv_string.c_str();

View File

@ -163,7 +163,7 @@ namespace mamba::specs
if (m_type == Type::Unknown)
{
m_location = unknown_channel;
m_platform_filters = {};
// Allowing in any platform filters for unkown type can be useful in MatchSpec
}
if (m_location.empty())
{
@ -208,4 +208,21 @@ namespace mamba::specs
{
return std::exchange(m_platform_filters, {});
}
auto ChannelSpec::str() const -> std::string
{
return fmt::format("{}", *this);
}
}
auto
fmt::formatter<mamba::specs::ChannelSpec>::format(const ChannelSpec& spec, format_context& ctx) const
-> format_context::iterator
{
auto out = fmt::format_to(ctx.out(), "{}", spec.location());
if (!spec.platform_filters().empty())
{
out = fmt::format_to(ctx.out(), "[{}]", fmt::join(spec.platform_filters(), ","));
}
return out;
}

View File

@ -58,6 +58,7 @@ set(
src/core/test_activation.cpp
src/core/test_channel_context.cpp
src/core/test_configuration.cpp
src/core/test_match_spec.cpp
src/core/test_cpp.cpp
src/core/test_downloader.cpp
src/core/test_env_file_reading.cpp

View File

@ -15,7 +15,6 @@
#include "mamba/core/fsutil.hpp"
#include "mamba/core/history.hpp"
#include "mamba/core/link.hpp"
#include "mamba/core/match_spec.hpp"
#include "mamba/core/output.hpp"
#include "mamba/core/subdirdata.hpp"
#include "mamba/util/build.hpp"
@ -47,268 +46,6 @@ namespace mamba
// lp.execute();
// }
TEST_SUITE("match_spec")
{
TEST_CASE("parse_version_build")
{
std::string v, b;
// >>> _parse_version_plus_build("=1.2.3 0")
// ('=1.2.3', '0')
// >>> _parse_version_plus_build("1.2.3=0")
// ('1.2.3', '0')
// >>> _parse_version_plus_build(">=1.0 , < 2.0 py34_0")
// ('>=1.0,<2.0', 'py34_0')
// >>> _parse_version_plus_build(">=1.0 , < 2.0 =py34_0")
// ('>=1.0,<2.0', 'py34_0')
// >>> _parse_version_plus_build("=1.2.3 ")
// ('=1.2.3', None)
// >>> _parse_version_plus_build(">1.8,<2|==1.7")
// ('>1.8,<2|==1.7', None)
// >>> _parse_version_plus_build("* openblas_0")
// ('*', 'openblas_0')
// >>> _parse_version_plus_build("* *")
// ('*', '*')
std::tie(v, b) = MatchSpec::parse_version_and_build("=1.2.3 0");
CHECK_EQ(v, "=1.2.3");
CHECK_EQ(b, "0");
std::tie(v, b) = MatchSpec::parse_version_and_build("=1.2.3=0");
CHECK_EQ(v, "=1.2.3");
CHECK_EQ(b, "0");
std::tie(v, b) = MatchSpec::parse_version_and_build(">=1.0 , < 2.0 py34_0");
CHECK_EQ(v, ">=1.0,<2.0");
CHECK_EQ(b, "py34_0");
std::tie(v, b) = MatchSpec::parse_version_and_build(">=1.0 , < 2.0 =py34_0");
CHECK_EQ(v, ">=1.0,<2.0");
CHECK_EQ(b, "py34_0");
std::tie(v, b) = MatchSpec::parse_version_and_build("=1.2.3 ");
CHECK_EQ(v, "=1.2.3");
CHECK_EQ(b, "");
std::tie(v, b) = MatchSpec::parse_version_and_build(">1.8,<2|==1.7");
CHECK_EQ(v, ">1.8,<2|==1.7");
CHECK_EQ(b, "");
std::tie(v, b) = MatchSpec::parse_version_and_build("* openblas_0");
CHECK_EQ(v, "*");
CHECK_EQ(b, "openblas_0");
std::tie(v, b) = MatchSpec::parse_version_and_build("* *");
CHECK_EQ(v, "*");
CHECK_EQ(b, "*");
}
TEST_CASE("parse")
{
auto& ctx = mambatests::context();
auto channel_context = ChannelContext::make_conda_compatible(ctx);
{
MatchSpec ms("xtensor==0.12.3", ctx, channel_context);
CHECK_EQ(ms.version, "0.12.3");
CHECK_EQ(ms.name, "xtensor");
}
{
MatchSpec ms("", ctx, channel_context);
CHECK_EQ(ms.version, "");
CHECK_EQ(ms.name, "");
}
{
MatchSpec ms("ipykernel", ctx, channel_context);
CHECK_EQ(ms.version, "");
CHECK_EQ(ms.name, "ipykernel");
}
{
MatchSpec ms("ipykernel ", ctx, channel_context);
CHECK_EQ(ms.version, "");
CHECK_EQ(ms.name, "ipykernel");
}
{
MatchSpec ms("numpy 1.7*", ctx, channel_context);
CHECK_EQ(ms.version, "1.7*");
CHECK_EQ(ms.name, "numpy");
CHECK_EQ(ms.conda_build_form(), "numpy 1.7*");
CHECK_EQ(ms.str(), "numpy=1.7");
}
{
MatchSpec ms("numpy[version='1.7|1.8']", ctx, channel_context);
// TODO!
// CHECK_EQ(ms.version, "1.7|1.8");
CHECK_EQ(ms.name, "numpy");
CHECK_EQ(ms.brackets["version"], "1.7|1.8");
CHECK_EQ(ms.str(), "numpy[version='1.7|1.8']");
}
{
MatchSpec ms("conda-forge/linux64::xtensor==0.12.3", ctx, channel_context);
CHECK_EQ(ms.version, "0.12.3");
CHECK_EQ(ms.name, "xtensor");
CHECK_EQ(ms.channel, "conda-forge/linux64");
CHECK_EQ(ms.optional, false);
}
{
MatchSpec ms("conda-forge::foo[build=3](target=blarg,optional)", ctx, channel_context);
CHECK_EQ(ms.version, "");
CHECK_EQ(ms.name, "foo");
CHECK_EQ(ms.channel, "conda-forge");
CHECK_EQ(ms.brackets["build"], "3");
CHECK_EQ(ms.parens["target"], "blarg");
CHECK_EQ(ms.optional, true);
}
{
MatchSpec ms("python[build_number=3]", ctx, channel_context);
CHECK_EQ(ms.name, "python");
CHECK_EQ(ms.brackets["build_number"], "3");
CHECK_EQ(ms.build_number, "3");
}
{
MatchSpec ms("python[build_number='<=3']", ctx, channel_context);
CHECK_EQ(ms.name, "python");
CHECK_EQ(ms.brackets["build_number"], "<=3");
CHECK_EQ(ms.build_number, "<=3");
}
{
MatchSpec ms(
"https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2",
ctx,
channel_context
);
CHECK_EQ(ms.name, "_libgcc_mutex");
CHECK_EQ(ms.version, "0.1");
CHECK_EQ(ms.build_string, "conda_forge");
CHECK_EQ(
ms.url,
"https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2"
);
CHECK_EQ(ms.fn, "_libgcc_mutex-0.1-conda_forge.tar.bz2");
}
{
MatchSpec ms(
"/home/randomguy/Downloads/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2",
ctx,
channel_context
);
CHECK_EQ(ms.name, "_libgcc_mutex");
CHECK_EQ(ms.version, "0.1");
CHECK_EQ(ms.build_string, "conda_forge");
#ifdef _WIN32
std::string driveletter = fs::absolute(fs::u8path("/")).string().substr(0, 1);
CHECK_EQ(
ms.url,
std::string("file://") + driveletter
+ ":/home/randomguy/Downloads/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2"
);
#else
CHECK_EQ(
ms.url,
"file:///home/randomguy/Downloads/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2"
);
#endif
CHECK_EQ(ms.fn, "_libgcc_mutex-0.1-conda_forge.tar.bz2");
}
{
MatchSpec ms(
"xtensor[url=file:///home/wolfv/Downloads/"
"xtensor-0.21.4-hc9558a2_0.tar.bz2]",
ctx,
channel_context
);
CHECK_EQ(ms.name, "xtensor");
CHECK_EQ(
ms.brackets["url"],
"file:///home/wolfv/Downloads/xtensor-0.21.4-hc9558a2_0.tar.bz2"
);
CHECK_EQ(ms.url, "file:///home/wolfv/Downloads/xtensor-0.21.4-hc9558a2_0.tar.bz2");
}
{
MatchSpec ms("foo=1.0=2", ctx, channel_context);
CHECK_EQ(ms.conda_build_form(), "foo 1.0 2");
CHECK_EQ(ms.str(), "foo==1.0=2");
}
{
MatchSpec ms(
"foo=1.0=2[md5=123123123, license=BSD-3, fn='test 123.tar.bz2']",
ctx,
channel_context
);
CHECK_EQ(ms.conda_build_form(), "foo 1.0 2");
CHECK_EQ(ms.str(), "foo==1.0=2[md5=123123123,license=BSD-3,fn='test 123.tar.bz2']");
}
{
MatchSpec ms(
"foo=1.0=2[md5=123123123, license=BSD-3, fn='test 123.tar.bz2', url='abcdef']",
ctx,
channel_context
);
CHECK_EQ(ms.conda_build_form(), "foo 1.0 2");
CHECK_EQ(ms.str(), "foo==1.0=2[url=abcdef,md5=123123123,license=BSD-3]");
}
{
MatchSpec ms("libblas=*=*mkl", ctx, channel_context);
CHECK_EQ(ms.conda_build_form(), "libblas * *mkl");
// CHECK_EQ(ms.str(), "foo==1.0=2");
}
{
MatchSpec ms("libblas=0.15*", ctx, channel_context);
CHECK_EQ(ms.conda_build_form(), "libblas 0.15*");
}
{
MatchSpec ms("xtensor =0.15*", ctx, channel_context);
CHECK_EQ(ms.conda_build_form(), "xtensor 0.15*");
CHECK_EQ(ms.str(), "xtensor=0.15");
}
{
MatchSpec ms("numpy=1.20", ctx, channel_context);
CHECK_EQ(ms.str(), "numpy=1.20");
}
{
MatchSpec ms("conda-forge::tzdata", ctx, channel_context);
CHECK_EQ(ms.str(), "conda-forge::tzdata");
}
{
MatchSpec ms("conda-forge::noarch/tzdata", ctx, channel_context);
CHECK_EQ(ms.str(), "conda-forge::noarch/tzdata");
}
{
MatchSpec ms("pkgs/main::tzdata", ctx, channel_context);
CHECK_EQ(ms.str(), "pkgs/main::tzdata");
}
{
MatchSpec ms("pkgs/main/noarch::tzdata", ctx, channel_context);
CHECK_EQ(ms.str(), "pkgs/main/noarch::tzdata");
}
{
MatchSpec ms("conda-forge/noarch::tzdata[subdir=linux64]", ctx, channel_context);
CHECK_EQ(ms.str(), "conda-forge/noarch::tzdata");
}
{
MatchSpec ms("conda-forge::tzdata[subdir=linux64]", ctx, channel_context);
CHECK_EQ(ms.str(), "conda-forge/linux64::tzdata");
}
}
TEST_CASE("is_simple")
{
auto& ctx = mambatests::context();
auto channel_context = ChannelContext::make_conda_compatible(ctx);
{
MatchSpec ms("libblas", ctx, channel_context);
CHECK(ms.is_simple());
}
{
MatchSpec ms("libblas=12.9=abcdef", ctx, channel_context);
CHECK_FALSE(ms.is_simple());
}
{
MatchSpec ms("libblas=0.15*", ctx, channel_context);
CHECK_FALSE(ms.is_simple());
}
{
MatchSpec ms("libblas[version=12.2]", ctx, channel_context);
CHECK_FALSE(ms.is_simple());
}
{
MatchSpec ms("xtensor =0.15*", ctx, channel_context);
CHECK_FALSE(ms.is_simple());
}
}
}
TEST_SUITE("history")
{
TEST_CASE("user_request")

View File

@ -0,0 +1,276 @@
// Copyright (c) 2023, QuantStack and Mamba Contributors
//
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include "mamba/core/channel_context.hpp"
#include "mamba/core/match_spec.hpp"
#include "mambatests.hpp"
using namespace mamba;
TEST_SUITE("MatchSpec")
{
TEST_CASE("parse_version_build")
{
std::string v, b;
// >>> _parse_version_plus_build("=1.2.3 0")
// ('=1.2.3', '0')
// >>> _parse_version_plus_build("1.2.3=0")
// ('1.2.3', '0')
// >>> _parse_version_plus_build(">=1.0 , < 2.0 py34_0")
// ('>=1.0,<2.0', 'py34_0')
// >>> _parse_version_plus_build(">=1.0 , < 2.0 =py34_0")
// ('>=1.0,<2.0', 'py34_0')
// >>> _parse_version_plus_build("=1.2.3 ")
// ('=1.2.3', None)
// >>> _parse_version_plus_build(">1.8,<2|==1.7")
// ('>1.8,<2|==1.7', None)
// >>> _parse_version_plus_build("* openblas_0")
// ('*', 'openblas_0')
// >>> _parse_version_plus_build("* *")
// ('*', '*')
std::tie(v, b) = MatchSpec::parse_version_and_build("=1.2.3 0");
CHECK_EQ(v, "=1.2.3");
CHECK_EQ(b, "0");
std::tie(v, b) = MatchSpec::parse_version_and_build("=1.2.3=0");
CHECK_EQ(v, "=1.2.3");
CHECK_EQ(b, "0");
std::tie(v, b) = MatchSpec::parse_version_and_build(">=1.0 , < 2.0 py34_0");
CHECK_EQ(v, ">=1.0,<2.0");
CHECK_EQ(b, "py34_0");
std::tie(v, b) = MatchSpec::parse_version_and_build(">=1.0 , < 2.0 =py34_0");
CHECK_EQ(v, ">=1.0,<2.0");
CHECK_EQ(b, "py34_0");
std::tie(v, b) = MatchSpec::parse_version_and_build("=1.2.3 ");
CHECK_EQ(v, "=1.2.3");
CHECK_EQ(b, "");
std::tie(v, b) = MatchSpec::parse_version_and_build(">1.8,<2|==1.7");
CHECK_EQ(v, ">1.8,<2|==1.7");
CHECK_EQ(b, "");
std::tie(v, b) = MatchSpec::parse_version_and_build("* openblas_0");
CHECK_EQ(v, "*");
CHECK_EQ(b, "openblas_0");
std::tie(v, b) = MatchSpec::parse_version_and_build("* *");
CHECK_EQ(v, "*");
CHECK_EQ(b, "*");
}
TEST_CASE("parse")
{
auto& ctx = mambatests::context();
auto channel_context = ChannelContext::make_conda_compatible(ctx);
{
MatchSpec ms("xtensor==0.12.3", ctx, channel_context);
CHECK_EQ(ms.version, "0.12.3");
CHECK_EQ(ms.name, "xtensor");
}
{
MatchSpec ms("", ctx, channel_context);
CHECK_EQ(ms.version, "");
CHECK_EQ(ms.name, "");
}
{
MatchSpec ms("ipykernel", ctx, channel_context);
CHECK_EQ(ms.version, "");
CHECK_EQ(ms.name, "ipykernel");
}
{
MatchSpec ms("ipykernel ", ctx, channel_context);
CHECK_EQ(ms.version, "");
CHECK_EQ(ms.name, "ipykernel");
}
{
MatchSpec ms("numpy 1.7*", ctx, channel_context);
CHECK_EQ(ms.version, "1.7*");
CHECK_EQ(ms.name, "numpy");
CHECK_EQ(ms.conda_build_form(), "numpy 1.7*");
CHECK_EQ(ms.str(), "numpy=1.7");
}
{
MatchSpec ms("numpy[version='1.7|1.8']", ctx, channel_context);
// TODO!
// CHECK_EQ(ms.version, "1.7|1.8");
CHECK_EQ(ms.name, "numpy");
CHECK_EQ(ms.brackets["version"], "1.7|1.8");
CHECK_EQ(ms.str(), "numpy[version='1.7|1.8']");
}
{
MatchSpec ms("conda-forge/linux64::xtensor==0.12.3", ctx, channel_context);
CHECK_EQ(ms.version, "0.12.3");
CHECK_EQ(ms.name, "xtensor");
CHECK_EQ(ms.channel, "conda-forge/linux64");
CHECK_EQ(ms.optional, false);
}
{
MatchSpec ms("conda-forge::foo[build=3](target=blarg,optional)", ctx, channel_context);
CHECK_EQ(ms.version, "");
CHECK_EQ(ms.name, "foo");
CHECK_EQ(ms.channel, "conda-forge");
CHECK_EQ(ms.brackets["build"], "3");
CHECK_EQ(ms.parens["target"], "blarg");
CHECK_EQ(ms.optional, true);
}
{
MatchSpec ms("python[build_number=3]", ctx, channel_context);
CHECK_EQ(ms.name, "python");
CHECK_EQ(ms.brackets["build_number"], "3");
CHECK_EQ(ms.build_number, "3");
}
{
MatchSpec ms("python[build_number='<=3']", ctx, channel_context);
CHECK_EQ(ms.name, "python");
CHECK_EQ(ms.brackets["build_number"], "<=3");
CHECK_EQ(ms.build_number, "<=3");
}
{
MatchSpec ms(
"https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2",
ctx,
channel_context
);
CHECK_EQ(ms.name, "_libgcc_mutex");
CHECK_EQ(ms.version, "0.1");
CHECK_EQ(ms.build_string, "conda_forge");
CHECK_EQ(
ms.url,
"https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2"
);
CHECK_EQ(ms.fn, "_libgcc_mutex-0.1-conda_forge.tar.bz2");
}
{
MatchSpec ms(
"/home/randomguy/Downloads/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2",
ctx,
channel_context
);
CHECK_EQ(ms.name, "_libgcc_mutex");
CHECK_EQ(ms.version, "0.1");
CHECK_EQ(ms.build_string, "conda_forge");
#ifdef _WIN32
std::string driveletter = fs::absolute(fs::u8path("/")).string().substr(0, 1);
CHECK_EQ(
ms.url,
std::string("file://") + driveletter
+ ":/home/randomguy/Downloads/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2"
);
#else
CHECK_EQ(
ms.url,
"file:///home/randomguy/Downloads/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2"
);
#endif
CHECK_EQ(ms.fn, "_libgcc_mutex-0.1-conda_forge.tar.bz2");
}
{
MatchSpec ms(
"xtensor[url=file:///home/wolfv/Downloads/"
"xtensor-0.21.4-hc9558a2_0.tar.bz2]",
ctx,
channel_context
);
CHECK_EQ(ms.name, "xtensor");
CHECK_EQ(
ms.brackets["url"],
"file:///home/wolfv/Downloads/xtensor-0.21.4-hc9558a2_0.tar.bz2"
);
CHECK_EQ(ms.url, "file:///home/wolfv/Downloads/xtensor-0.21.4-hc9558a2_0.tar.bz2");
}
{
MatchSpec ms("foo=1.0=2", ctx, channel_context);
CHECK_EQ(ms.conda_build_form(), "foo 1.0 2");
CHECK_EQ(ms.str(), "foo==1.0=2");
}
{
MatchSpec ms(
"foo=1.0=2[md5=123123123, license=BSD-3, fn='test 123.tar.bz2']",
ctx,
channel_context
);
CHECK_EQ(ms.conda_build_form(), "foo 1.0 2");
CHECK_EQ(ms.str(), "foo==1.0=2[md5=123123123,license=BSD-3,fn='test 123.tar.bz2']");
}
{
MatchSpec ms(
"foo=1.0=2[md5=123123123, license=BSD-3, fn='test 123.tar.bz2', url='abcdef']",
ctx,
channel_context
);
CHECK_EQ(ms.conda_build_form(), "foo 1.0 2");
CHECK_EQ(ms.str(), "foo==1.0=2[url=abcdef,md5=123123123,license=BSD-3]");
}
{
MatchSpec ms("libblas=*=*mkl", ctx, channel_context);
CHECK_EQ(ms.conda_build_form(), "libblas * *mkl");
// CHECK_EQ(ms.str(), "foo==1.0=2");
}
{
MatchSpec ms("libblas=0.15*", ctx, channel_context);
CHECK_EQ(ms.conda_build_form(), "libblas 0.15*");
}
{
MatchSpec ms("xtensor =0.15*", ctx, channel_context);
CHECK_EQ(ms.conda_build_form(), "xtensor 0.15*");
CHECK_EQ(ms.str(), "xtensor=0.15");
}
{
MatchSpec ms("numpy=1.20", ctx, channel_context);
CHECK_EQ(ms.str(), "numpy=1.20");
}
{
MatchSpec ms("conda-forge::tzdata", ctx, channel_context);
CHECK_EQ(ms.str(), "conda-forge::tzdata");
}
{
MatchSpec ms("conda-forge::noarch/tzdata", ctx, channel_context);
CHECK_EQ(ms.str(), "conda-forge::noarch/tzdata");
}
{
MatchSpec ms("pkgs/main::tzdata", ctx, channel_context);
CHECK_EQ(ms.str(), "pkgs/main::tzdata");
}
{
MatchSpec ms("pkgs/main/noarch::tzdata", ctx, channel_context);
CHECK_EQ(ms.str(), "pkgs/main/noarch::tzdata");
}
{
MatchSpec ms("conda-forge/noarch::tzdata[subdir=linux64]", ctx, channel_context);
CHECK_EQ(ms.str(), "conda-forge/noarch::tzdata");
}
{
MatchSpec ms("conda-forge::tzdata[subdir=linux64]", ctx, channel_context);
CHECK_EQ(ms.str(), "conda-forge/linux64::tzdata");
}
}
TEST_CASE("is_simple")
{
auto& ctx = mambatests::context();
auto channel_context = ChannelContext::make_conda_compatible(ctx);
{
MatchSpec ms("libblas", ctx, channel_context);
CHECK(ms.is_simple());
}
{
MatchSpec ms("libblas=12.9=abcdef", ctx, channel_context);
CHECK_FALSE(ms.is_simple());
}
{
MatchSpec ms("libblas=0.15*", ctx, channel_context);
CHECK_FALSE(ms.is_simple());
}
{
MatchSpec ms("libblas[version=12.2]", ctx, channel_context);
CHECK_FALSE(ms.is_simple());
}
{
MatchSpec ms("xtensor =0.15*", ctx, channel_context);
CHECK_FALSE(ms.is_simple());
}
}
}

View File

@ -14,6 +14,9 @@ using namespace mamba::specs;
TEST_SUITE("specs::channel_spec")
{
using PlatformSet = typename util::flat_set<std::string>;
using Type = typename ChannelSpec::Type;
TEST_CASE("Constructor")
{
SUBCASE("Default")
@ -29,15 +32,12 @@ TEST_SUITE("specs::channel_spec")
const auto spec = ChannelSpec("hello", { "linux-78" }, ChannelSpec::Type::Unknown);
CHECK_EQ(spec.type(), ChannelSpec::Type::Unknown);
CHECK_EQ(spec.location(), "<unknown>");
CHECK(spec.platform_filters().empty());
CHECK_EQ(spec.platform_filters(), PlatformSet{ "linux-78" });
}
}
TEST_CASE("Parsing")
{
using Type = typename ChannelSpec::Type;
using PlatformSet = typename util::flat_set<std::string>;
SUBCASE("Invalid channels")
{
for (std::string_view str : { "", "<unknown>", ":///<unknown>", "none" })
@ -220,4 +220,13 @@ TEST_SUITE("specs::channel_spec")
CHECK_EQ(spec.platform_filters(), PlatformSet{ "linux-64" });
}
}
TEST_CASE("str")
{
CHECK_EQ(ChannelSpec("location", {}, Type::Name).str(), "location");
CHECK_EQ(
ChannelSpec("location", { "linux-64", "noarch" }, Type::Name).str(),
"location[linux-64,noarch]"
);
}
}

View File

@ -714,7 +714,8 @@ bind_submodule_impl(pybind11::module_ m)
py::arg("params"),
py::arg("has_zst")
)
.def("make_channel", &ChannelContext::make_channel)
.def("make_channel", py::overload_cast<std::string_view>(&ChannelContext::make_channel))
.def("make_channel", py::overload_cast<specs::ChannelSpec>(&ChannelContext::make_channel))
.def("params", &ChannelContext::params)
.def("has_zst", &ChannelContext::has_zst);