You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
87 lines
2.4 KiB
87 lines
2.4 KiB
using System.Diagnostics; |
|
using System.Diagnostics.CodeAnalysis; |
|
using System.Text.RegularExpressions; |
|
using StabilityMatrix.Core.Processes; |
|
|
|
namespace StabilityMatrix.Core.Python; |
|
|
|
public partial record PipPackageSpecifier |
|
{ |
|
public required string Name { get; init; } |
|
|
|
public string? Constraint { get; init; } |
|
|
|
public string? Version { get; init; } |
|
|
|
public string? VersionConstraint => Constraint is null || Version is null ? null : Constraint + Name; |
|
|
|
public static PipPackageSpecifier Parse(string value) |
|
{ |
|
var result = TryParse(value, true, out var packageSpecifier); |
|
|
|
Debug.Assert(result); |
|
|
|
return packageSpecifier!; |
|
} |
|
|
|
public static bool TryParse(string value, [NotNullWhen(true)] out PipPackageSpecifier? packageSpecifier) |
|
{ |
|
return TryParse(value, false, out packageSpecifier); |
|
} |
|
|
|
private static bool TryParse( |
|
string value, |
|
bool throwOnFailure, |
|
[NotNullWhen(true)] out PipPackageSpecifier? packageSpecifier |
|
) |
|
{ |
|
var match = PackageSpecifierRegex().Match(value); |
|
if (!match.Success) |
|
{ |
|
if (throwOnFailure) |
|
{ |
|
throw new ArgumentException($"Invalid package specifier: {value}"); |
|
} |
|
|
|
packageSpecifier = null; |
|
return false; |
|
} |
|
|
|
packageSpecifier = new PipPackageSpecifier |
|
{ |
|
Name = match.Groups["package_name"].Value, |
|
Constraint = match.Groups["version_constraint"].Value, |
|
Version = match.Groups["version"].Value |
|
}; |
|
|
|
return true; |
|
} |
|
|
|
/// <inheritdoc /> |
|
public override string ToString() |
|
{ |
|
return Name + VersionConstraint; |
|
} |
|
|
|
public static implicit operator Argument(PipPackageSpecifier specifier) |
|
{ |
|
return specifier.VersionConstraint is null |
|
? new Argument(specifier.Name) |
|
: new Argument((specifier.Name, specifier.VersionConstraint)); |
|
} |
|
|
|
public static implicit operator PipPackageSpecifier(string specifier) |
|
{ |
|
return Parse(specifier); |
|
} |
|
|
|
/// <summary> |
|
/// Regex to match a pip package specifier. |
|
/// </summary> |
|
[GeneratedRegex( |
|
"(?<package_name>[a-zA-Z0-9_]+)(?<version_specifier>(?<version_constraint>==|>=|<=|>|<|~=|!=)(<version>[a-zA-Z0-9_.]+))?", |
|
RegexOptions.CultureInvariant, |
|
1000 |
|
)] |
|
private static partial Regex PackageSpecifierRegex(); |
|
}
|
|
|