Skip to content

Commit 099e0ab

Browse files
awoll-bdaiexploy-bot
authored andcommitted
Fix version check (#75)
# Pull Request ### What change is being made Fix the version check in C++ and Python ### Why this change is being made Fix. ### Tested Tests are passing. GitOrigin-RevId: 3ee94d15ab67a130e45d724fea1a770c19858187
1 parent cfc9d1f commit 099e0ab

4 files changed

Lines changed: 76 additions & 81 deletions

File tree

control/context.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,7 @@ bool OnnxContext::createContext(OnnxRuntime& onnx_model, bool strict) {
6565
return false;
6666
}
6767

68-
// TODO: enable strict mode to ensure version compatibility.
69-
if (!metadata::checkExployVersion(onnx_model.getCustomMetadata("exploy_version"),
70-
/*strict*/ false))
71-
return false;
68+
if (!metadata::checkExployVersion(onnx_model.getCustomMetadata("exploy_version"))) return false;
7269

7370
std::optional<int> maybe_update_rate = parseUpdateRate(onnx_model);
7471
if (!maybe_update_rate.has_value()) return false;
@@ -123,7 +120,6 @@ bool OnnxContext::createContext(OnnxRuntime& onnx_model, bool strict) {
123120
});
124121
}
125122

126-
// TODO: simplify
127123
for (auto& matcher : matchers_) {
128124
auto inputs = matcher->createInputs();
129125
inputs_.insert(inputs_.end(), std::make_move_iterator(inputs.begin()),

control/metadata.hpp

Lines changed: 34 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -251,89 +251,79 @@ inline void from_json(const json& j, JointMetadata& jm) {
251251
}
252252

253253
/**
254-
* @brief Parsed semantic version (MAJOR.MINOR.PATCH).
254+
* @brief Parsed version (MAJOR.MINOR).
255255
*/
256256
struct Version {
257257
int major{0};
258258
int minor{0};
259-
int patch{0};
260259

261-
std::string toString() const { return fmt::format("{}.{}.{}", major, minor, patch); }
260+
std::string toString() const { return fmt::format("{}.{}", major, minor); }
262261

263262
bool operator<=(const Version& other) const {
264263
if (major != other.major) return major < other.major;
265-
if (minor != other.minor) return minor < other.minor;
266-
return patch <= other.patch;
264+
return minor <= other.minor;
267265
}
268266
};
269267

270-
constexpr Version kMinSupportedExployVersion{0, 1, 0};
271-
constexpr Version kMaxSupportedExployVersion{0, 1, 0};
268+
constexpr Version kMinSupportedExployVersion{0, 0};
272269

273270
/**
274-
* @brief Parse a "MAJOR.MINOR.PATCH" version string.
271+
* @brief Parse a version string into MAJOR.MINOR.
275272
*
276-
* @param s Version string to parse.
277-
* @return Parsed Version, or std::nullopt if the string is not a valid semver.
273+
* Only the leading MAJOR.MINOR digits are extracted; any trailing content
274+
* (e.g. ".PATCH", ".postN", ".devN", "+local") is ignored.
275+
*
276+
* @param s Version string to parse (e.g. "1.2.3", "0.0.post1.dev96+gabcdef").
277+
* @return Parsed Version, or std::nullopt if the string does not start with MAJOR.MINOR.
278278
*/
279279
inline std::optional<Version> parseVersion(const std::string& s) {
280-
static const std::regex kVersionRegex(R"(^(\d+)\.(\d+)\.(\d+)$)");
280+
static const std::regex kVersionRegex(R"(^(\d+)\.(\d+))");
281281
std::smatch match;
282-
if (!std::regex_match(s, match, kVersionRegex)) return std::nullopt;
283-
return Version{std::stoi(match[1]), std::stoi(match[2]), std::stoi(match[3])};
282+
if (!std::regex_search(s, match, kVersionRegex)) return std::nullopt;
283+
return Version{std::stoi(match[1]), std::stoi(match[2])};
284284
}
285285

286286
/**
287-
* @brief Check that the ONNX model's exploy_version metadata is present and within the supported
288-
* range [kMinSupportedExployVersion, kMaxSupportedExployVersion]. Logs an error if not.
287+
* @brief Check that the ONNX model's exploy_version metadata is present and at least
288+
* @p min_version. Logs an error if not.
289289
*
290290
* @param maybe_version_str The value of the "exploy_version" metadata key, or std::nullopt if
291291
* absent.
292-
* @param strict If true, treat mismatch as a failure. If false, only log a warning and return true.
293-
* @return true if the version is present and within the supported range, false otherwise.
292+
* @param min_version Minimum accepted version. Defaults to kMinSupportedExployVersion.
293+
* @return true if the version is present and >= @p min_version, false otherwise.
294294
*/
295295
inline bool checkExployVersion(const std::optional<std::string>& maybe_version_str,
296-
bool strict = true) {
297-
const auto log = [&](const std::string& msg) {
298-
if (strict) {
299-
LOG_STREAM(ERROR, msg);
300-
} else {
301-
LOG_STREAM(WARN, msg);
302-
}
303-
};
304-
296+
const Version& min_version = kMinSupportedExployVersion) {
305297
if (!maybe_version_str.has_value()) {
306-
log("ONNX model does not contain 'exploy_version' metadata. "
307-
"The ONNX file might not be compatible with this controller.");
308-
return !strict;
298+
LOG_STREAM(ERROR,
299+
"ONNX model does not contain 'exploy_version' metadata. "
300+
"The ONNX file might not be compatible with this controller.");
301+
return false;
309302
}
310303

311304
std::string version_str;
312305
try {
313306
version_str = json::parse(maybe_version_str.value()).get<std::string>();
314307
} catch (const json::exception&) {
315-
log(
316-
fmt::format("Failed to JSON parse exploy_version: '{}'. "
317-
"The ONNX file might not be compatible with this controller.",
318-
maybe_version_str.value()));
319-
return !strict;
308+
LOG_STREAM(ERROR, fmt::format("Failed to JSON parse exploy_version: '{}'. "
309+
"The ONNX file might not be compatible with this controller.",
310+
maybe_version_str.value()));
311+
return false;
320312
}
321313

322314
auto maybe_version = parseVersion(version_str);
323315
if (!maybe_version.has_value()) {
324-
log(
325-
fmt::format("Failed to parse exploy_version: '{}'. "
326-
"The ONNX file might not be compatible with this controller.",
327-
version_str));
328-
return !strict;
316+
LOG_STREAM(ERROR, fmt::format("Failed to parse exploy_version: '{}'. "
317+
"The ONNX file might not be compatible with this controller.",
318+
version_str));
319+
return false;
329320
}
330321

331322
const auto& v = maybe_version.value();
332-
const bool in_range = kMinSupportedExployVersion <= v && v <= kMaxSupportedExployVersion;
333-
if (!in_range) {
334-
log(fmt::format("exploy_version '{}' is outside the supported range [{}, {}].", version_str,
335-
kMinSupportedExployVersion.toString(), kMaxSupportedExployVersion.toString()));
336-
return !strict;
323+
if (!(min_version <= v)) {
324+
LOG_STREAM(ERROR, fmt::format("exploy_version '{}' is below the minimum supported version {}.",
325+
version_str, min_version.toString()));
326+
return false;
337327
}
338328
return true;
339329
}

control/test/metadata_test.cpp

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,26 @@ namespace exploy::control::metadata {
99
// ========== Version::toString ==========
1010

1111
TEST(VersionTest, ToString) {
12-
EXPECT_EQ((Version{1, 2, 3}.toString()), "1.2.3");
13-
EXPECT_EQ((Version{0, 0, 0}.toString()), "0.0.0");
14-
EXPECT_EQ((Version{10, 20, 30}.toString()), "10.20.30");
12+
EXPECT_EQ((Version{1, 2}.toString()), "1.2");
13+
EXPECT_EQ((Version{0, 0}.toString()), "0.0");
14+
EXPECT_EQ((Version{10, 20}.toString()), "10.20");
1515
}
1616

1717
// ========== Version::operator<= ==========
1818

1919
TEST(VersionTest, ComparisonEqualVersions) {
20-
EXPECT_TRUE((Version{1, 2, 3} <= Version{1, 2, 3}));
21-
EXPECT_TRUE((Version{0, 0, 0} <= Version{0, 0, 0}));
20+
EXPECT_TRUE((Version{1, 2} <= Version{1, 2}));
21+
EXPECT_TRUE((Version{0, 0} <= Version{0, 0}));
2222
}
2323

2424
TEST(VersionTest, ComparisonMajorDiffers) {
25-
EXPECT_TRUE((Version{0, 9, 9} <= Version{1, 0, 0}));
26-
EXPECT_FALSE((Version{2, 0, 0} <= Version{1, 9, 9}));
25+
EXPECT_TRUE((Version{0, 9} <= Version{1, 0}));
26+
EXPECT_FALSE((Version{2, 0} <= Version{1, 9}));
2727
}
2828

2929
TEST(VersionTest, ComparisonMinorDiffers) {
30-
EXPECT_TRUE((Version{1, 1, 9} <= Version{1, 2, 0}));
31-
EXPECT_FALSE((Version{1, 3, 0} <= Version{1, 2, 9}));
32-
}
33-
34-
TEST(VersionTest, ComparisonPatchDiffers) {
35-
EXPECT_TRUE((Version{1, 2, 2} <= Version{1, 2, 3}));
36-
EXPECT_FALSE((Version{1, 2, 4} <= Version{1, 2, 3}));
30+
EXPECT_TRUE((Version{1, 1} <= Version{1, 2}));
31+
EXPECT_FALSE((Version{1, 3} <= Version{1, 2}));
3732
}
3833

3934
// ========== parseVersion ==========
@@ -43,43 +38,57 @@ TEST(ParseVersionTest, ValidVersion) {
4338
ASSERT_TRUE(v.has_value());
4439
EXPECT_EQ(v->major, 1);
4540
EXPECT_EQ(v->minor, 2);
46-
EXPECT_EQ(v->patch, 3);
4741
}
4842

4943
TEST(ParseVersionTest, ZeroVersion) {
5044
auto v = parseVersion("0.0.0");
5145
ASSERT_TRUE(v.has_value());
5246
EXPECT_EQ(v->major, 0);
5347
EXPECT_EQ(v->minor, 0);
54-
EXPECT_EQ(v->patch, 0);
5548
}
5649

5750
TEST(ParseVersionTest, LargeNumbers) {
5851
auto v = parseVersion("10.20.30");
5952
ASSERT_TRUE(v.has_value());
6053
EXPECT_EQ(v->major, 10);
6154
EXPECT_EQ(v->minor, 20);
62-
EXPECT_EQ(v->patch, 30);
6355
}
6456

6557
TEST(ParseVersionTest, EmptyString) {
6658
EXPECT_FALSE(parseVersion("").has_value());
6759
}
6860

6961
TEST(ParseVersionTest, MissingPatch) {
70-
EXPECT_FALSE(parseVersion("1.2").has_value());
62+
auto v = parseVersion("1.2");
63+
ASSERT_TRUE(v.has_value());
64+
EXPECT_EQ(v->major, 1);
65+
EXPECT_EQ(v->minor, 2);
7166
}
7267

7368
TEST(ParseVersionTest, ExtraComponent) {
74-
EXPECT_FALSE(parseVersion("1.2.3.4").has_value());
69+
auto v = parseVersion("1.2.3.4");
70+
ASSERT_TRUE(v.has_value());
71+
EXPECT_EQ(v->major, 1);
72+
EXPECT_EQ(v->minor, 2);
73+
}
74+
75+
TEST(ParseVersionTest, PythonDevVersion) {
76+
auto v = parseVersion("0.0.post1.dev96+g1cdbae3db");
77+
ASSERT_TRUE(v.has_value());
78+
EXPECT_EQ(v->major, 0);
79+
EXPECT_EQ(v->minor, 0);
7580
}
7681

7782
TEST(ParseVersionTest, NonNumericComponents) {
7883
EXPECT_FALSE(parseVersion("a.b.c").has_value());
7984
}
8085

8186
TEST(ParseVersionTest, NegativeComponent) {
82-
EXPECT_FALSE(parseVersion("1.2.-3").has_value());
87+
// "1.2.-3" — trailing content after MAJOR.MINOR is ignored
88+
auto v = parseVersion("1.2.-3");
89+
ASSERT_TRUE(v.has_value());
90+
EXPECT_EQ(v->major, 1);
91+
EXPECT_EQ(v->minor, 2);
8392
}
8493

8594
TEST(ParseVersionTest, WithVPrefix) {
@@ -107,18 +116,18 @@ TEST(CheckExployVersionTest, InvalidSemver) {
107116
}
108117

109118
TEST(CheckExployVersionTest, VersionBelowMinimum) {
110-
// kMinSupportedExployVersion is 0.1.0, so 0.0.9 is below the minimum
111-
EXPECT_FALSE(checkExployVersion("\"0.0.9\""));
119+
constexpr Version min{1, 2};
120+
EXPECT_FALSE(checkExployVersion("\"1.1.9\"", min));
112121
}
113122

114-
TEST(CheckExployVersionTest, VersionAboveMaximum) {
115-
// kMaxSupportedExployVersion is 0.1.0, so 0.2.0 is above the maximum
116-
EXPECT_FALSE(checkExployVersion("\"0.2.0\""));
123+
TEST(CheckExployVersionTest, SupportedVersion) {
124+
constexpr Version min{1, 2};
125+
EXPECT_TRUE(checkExployVersion("\"1.2.0\"", min));
117126
}
118127

119-
TEST(CheckExployVersionTest, SupportedVersion) {
120-
// kMinSupportedExployVersion == kMaxSupportedExployVersion == 0.1.0
121-
EXPECT_TRUE(checkExployVersion("\"0.1.0\""));
128+
TEST(CheckExployVersionTest, VersionAboveMinimum) {
129+
constexpr Version min{1, 2};
130+
EXPECT_TRUE(checkExployVersion("\"1.3.0\"", min));
122131
}
123132

124133
} // namespace exploy::control::metadata

python/exploy/exporter/core/utils/paths.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@
1818

1919

2020
def get_exploy_version() -> str:
21-
"""Get the installed exploy-exporter-core package version.
21+
"""Get the installed exploy package version.
2222
2323
Returns:
24-
Version string, or "unknown" if the package metadata is not available.
24+
Version string, or "0.0.0" if the package metadata is not available.
2525
"""
2626
try:
27-
return importlib.metadata.version("exploy-exporter-core")
27+
return importlib.metadata.version("exploy")
2828
except importlib.metadata.PackageNotFoundError:
29-
return "unknown"
29+
return "0.0.0"
3030

3131

3232
def _ensure_onnx_extension(filename: str) -> pathlib.Path:

0 commit comments

Comments
 (0)