Skip to content

add string normalize method #1461

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

Merged
merged 5 commits into from
Apr 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ __Bug Fixes__:
#1426 Sequential.eval() does not put model into eval mode<br/>
`torch.optim.lr_scheduler.LinearLR` `end_factor` default has been corrected, is now 1.0.<br/>
Update package version of SixLabors.ImageSharp to avoid security vulnerability<br/>
Updated dll dependencies loading to avoid using hardcoded version strings<br/>

__API Changes__:

Expand Down
28 changes: 24 additions & 4 deletions src/TorchSharp/Torch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,26 @@ public static partial class torch
static bool nativeBackendCudaLoaded = false;

public static string __version__ => libtorchPackageVersion;
public static string NormalizeNuGetVersion(string versionString)
{
if (string.IsNullOrWhiteSpace(versionString))
throw new ArgumentException($"Invalid NuGet version: {versionString}. Version string is null, empty or only contains whitespaces");

string[] parts = versionString.Split('-', '+');
string[] versionParts = parts[0].Split('.');

if (versionParts.Length < 2 || versionParts.Length > 4 || !versionParts.All(v => int.TryParse(v, out _)))
throw new ArgumentException($"Invalid NuGet version: {versionString}. Please check: https://learn.microsoft.com/en-us/nuget/concepts/package-versioning");

string normalizedVersion = versionParts[0] + "." + versionParts[1];
if (versionParts.Length > 2) normalizedVersion += "." + versionParts[2];
if (versionParts.Length > 3 && int.Parse(versionParts[3]) != 0) normalizedVersion += "." + versionParts[3];

if (parts.Length > 1)
normalizedVersion += "-" + parts[1];

return normalizedVersion;
}

internal static bool TryLoadNativeLibraryFromFile(string path, StringBuilder trace) {
bool ok;
Expand Down Expand Up @@ -168,14 +188,14 @@ private static void LoadNativeBackend(bool useCudaBackend, out StringBuilder? tr

if (torchsharpLoc!.Contains("torchsharp") && torchsharpLoc.Contains("lib") && Directory.Exists(packagesDir) && Directory.Exists(torchsharpHome)) {

var torchSharpVersion = Path.GetFileName(torchsharpHome); // really GetDirectoryName

var torchSharpVersion = NormalizeNuGetVersion(Path.GetFileName(torchsharpHome));
var normalizedLibtorchPackageVersion = NormalizeNuGetVersion(libtorchPackageVersion);
if (useCudaBackend) {
var consolidatedDir = Path.Combine(torchsharpLoc, $"cuda-{cudaVersion}");

trace.AppendLine($" Trying dynamic load for .NET/F# Interactive by consolidating native {cudaRootPackage}-* binaries to {consolidatedDir}...");

var cudaOk = CopyNativeComponentsIntoSingleDirectory(packagesDir, $"{cudaRootPackage}-*", libtorchPackageVersion, consolidatedDir, trace);
var cudaOk = CopyNativeComponentsIntoSingleDirectory(packagesDir, $"{cudaRootPackage}-*", normalizedLibtorchPackageVersion, consolidatedDir, trace);
if (cudaOk) {
cudaOk = CopyNativeComponentsIntoSingleDirectory(packagesDir, "torchsharp", torchSharpVersion, consolidatedDir, trace);
if (cudaOk) {
Expand All @@ -193,7 +213,7 @@ private static void LoadNativeBackend(bool useCudaBackend, out StringBuilder? tr

trace.AppendLine($" Trying dynamic load for .NET/F# Interactive by consolidating native {cpuRootPackage}-* binaries to {consolidatedDir}...");

var cpuOk = CopyNativeComponentsIntoSingleDirectory(packagesDir, cpuRootPackage, libtorchPackageVersion, consolidatedDir, trace);
var cpuOk = CopyNativeComponentsIntoSingleDirectory(packagesDir, cpuRootPackage, normalizedLibtorchPackageVersion, consolidatedDir, trace);
if (cpuOk) {
cpuOk = CopyNativeComponentsIntoSingleDirectory(packagesDir, "torchsharp", torchSharpVersion, consolidatedDir, trace);
if (cpuOk) {
Expand Down
13 changes: 13 additions & 0 deletions test/TorchSharpTest/TestTorchSharp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using System.Security.Cryptography;
using Tensorboard;
using Xunit;

using static TorchSharp.torch;
Expand Down Expand Up @@ -450,6 +452,17 @@ public void AllowFP16ReductionCuBLAS()
Assert.False(torch.backends.cuda.matmul.allow_fp16_reduced_precision_reduction);
}

[Fact]
public void CheckVersionStrings()
{
Assert.Equal("2.5.1", torch.NormalizeNuGetVersion("2.5.1.0"));
Assert.Equal("0.105.0", torch.NormalizeNuGetVersion("0.105.0.0"));
Assert.Equal("0.1.0-alpha", torch.NormalizeNuGetVersion("0.1.0-alpha"));
Assert.Equal("0.1.0", torch.NormalizeNuGetVersion("0.1.0"));
Assert.Throws<ArgumentException>(() => NormalizeNuGetVersion(""));
Assert.Throws<ArgumentException>(() => NormalizeNuGetVersion("1.2.3.4.5"));
}

// Because some of the tests mess with global state, and are run in parallel, we need to
// acquire a lock before testing setting the default RNG see.
private static object _lock = new object();
Expand Down