Browse Source

Fixed python packages crash & show parent folder name for ipadapter/controlnets that have same name

also added sdxl turbo & svd
pull/365/head
JT 11 months ago
parent
commit
2475241492
  1. 9
      CHANGELOG.md
  2. 20
      StabilityMatrix.Avalonia/Assets/hf-packages.json
  3. 38
      StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj
  4. 16
      StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/HuggingFacePageViewModel.cs
  5. 19
      StabilityMatrix.Avalonia/ViewModels/Inference/Modules/ControlNetModule.cs
  6. 21
      StabilityMatrix.Avalonia/ViewModels/Inference/SelectImageCardViewModel.cs
  7. 72
      StabilityMatrix.Avalonia/Views/MainWindow.axaml.cs
  8. 29
      StabilityMatrix.Core/Models/HybridModelFile.cs
  9. 1
      StabilityMatrix.Core/Python/PipPackageInfo.cs

9
CHANGELOG.md

@ -5,6 +5,15 @@ All notable changes to Stability Matrix will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html).
## v2.7.6
### Added
- Added SDXL Turbo and Stable Video Diffusion to the Hugging Face tab
### Changed
- ControlNet model selector will now show the parent directory of a model when relevant
### Fixed
- Fixed Python Packages dialog crash
- Fixed Base Model downloads from the Hugging Face tab downloading to the wrong folder
## v2.7.5 ## v2.7.5
### Fixed ### Fixed
- Fixed Python Packages manager crash when pip list returns warnings in json - Fixed Python Packages manager crash when pip list returns warnings in json

20
StabilityMatrix.Avalonia/Assets/hf-packages.json

@ -38,6 +38,26 @@
"LicenseType": "Open RAIL++", "LicenseType": "Open RAIL++",
"LicensePath": "LICENSE.md" "LicensePath": "LICENSE.md"
}, },
{
"ModelCategory": "BaseModel",
"ModelName": "SDXL Turbo",
"RepositoryPath": "stabilityai/sdxl-turbo",
"Files": [
"sd_xl_turbo_1.0_fp16.safetensors"
],
"LicenseType": "SAI-NC-Community",
"LicensePath": "LICENSE.TXT"
},
{
"ModelCategory": "BaseModel",
"ModelName": "Stable Video Diffusion",
"RepositoryPath": "stabilityai/stable-video-diffusion-img2vid",
"Files": [
"svd.safetensors"
],
"LicenseType": "Stable-Video-Diffusion-NC-Community",
"LicensePath": "LICENSE"
},
{ {
"ModelCategory": "ControlNet", "ModelCategory": "ControlNet",
"ModelName": "Canny", "ModelName": "Canny",

38
StabilityMatrix.Avalonia/StabilityMatrix.Avalonia.csproj

@ -23,29 +23,29 @@
<PackageReference Include="AsyncImageLoader.Avalonia" Version="3.2.1" /> <PackageReference Include="AsyncImageLoader.Avalonia" Version="3.2.1" />
<PackageReference Include="AutoComplete.Net" Version="1.2211.2014.42"/> <PackageReference Include="AutoComplete.Net" Version="1.2211.2014.42"/>
<PackageReference Include="Avalonia.AvaloniaEdit" Version="11.0.5" /> <PackageReference Include="Avalonia.AvaloniaEdit" Version="11.0.5" />
<PackageReference Include="Avalonia.Controls.PanAndZoom" Version="11.0.0" /> <PackageReference Include="Avalonia.Controls.PanAndZoom" Version="11.0.0.2" />
<PackageReference Include="Avalonia" Version="11.0.5" /> <PackageReference Include="Avalonia" Version="11.0.6" />
<PackageReference Include="Avalonia.Desktop" Version="11.0.5" /> <PackageReference Include="Avalonia.Desktop" Version="11.0.6" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.0.5" /> <PackageReference Include="Avalonia.Fonts.Inter" Version="11.0.6" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.--> <!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.5" /> <PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.6" />
<PackageReference Include="Avalonia.HtmlRenderer" Version="11.0.0" /> <PackageReference Include="Avalonia.HtmlRenderer" Version="11.0.0" />
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.0.5" /> <PackageReference Include="Avalonia.Xaml.Behaviors" Version="11.0.6" />
<PackageReference Include="AvaloniaEdit.TextMate" Version="11.0.5" /> <PackageReference Include="AvaloniaEdit.TextMate" Version="11.0.5" />
<PackageReference Include="bodong.Avalonia.PropertyGrid" Version="11.0.5.1" /> <PackageReference Include="bodong.Avalonia.PropertyGrid" Version="11.0.6.1" />
<PackageReference Include="bodong.PropertyModels" Version="11.0.5.1" /> <PackageReference Include="bodong.PropertyModels" Version="11.0.6.1" />
<PackageReference Include="CommandLineParser" Version="2.9.1" /> <PackageReference Include="CommandLineParser" Version="2.9.1" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" /> <PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="DiscordRichPresence" Version="1.2.1.24" /> <PackageReference Include="DiscordRichPresence" Version="1.2.1.24" />
<PackageReference Include="Dock.Avalonia" Version="11.0.0.3" /> <PackageReference Include="Dock.Avalonia" Version="11.0.0.5" />
<PackageReference Include="Dock.Model.Avalonia" Version="11.0.0.3" /> <PackageReference Include="Dock.Model.Avalonia" Version="11.0.0.5" />
<PackageReference Include="Dock.Serializer" Version="11.0.0.3" /> <PackageReference Include="Dock.Serializer" Version="11.0.0.5" />
<PackageReference Include="DynamicData" Version="8.1.1" /> <PackageReference Include="DynamicData" Version="8.3.27" />
<PackageReference Include="Exceptionless.DateTimeExtensions" Version="3.4.3" /> <PackageReference Include="Exceptionless.DateTimeExtensions" Version="3.4.3" />
<PackageReference Include="FluentAvalonia.BreadcrumbBar" Version="2.0.2" /> <PackageReference Include="FluentAvalonia.BreadcrumbBar" Version="2.0.2" />
<PackageReference Include="FluentAvaloniaUI" Version="2.0.4" /> <PackageReference Include="FluentAvaloniaUI" Version="2.0.4" />
<PackageReference Include="FluentIcons.Avalonia" Version="1.1.222" /> <PackageReference Include="FluentIcons.Avalonia" Version="1.1.224" />
<PackageReference Include="FluentIcons.FluentAvalonia" Version="1.1.222" /> <PackageReference Include="FluentIcons.FluentAvalonia" Version="1.1.224" />
<PackageReference Include="FuzzySharp" Version="2.0.2" /> <PackageReference Include="FuzzySharp" Version="2.0.2" />
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" /> <PackageReference Include="JetBrains.Annotations" Version="2023.3.0" />
<PackageReference Include="Markdown.Avalonia" Version="11.0.2" /> <PackageReference Include="Markdown.Avalonia" Version="11.0.2" />
@ -59,16 +59,16 @@
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Http.Polly" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
<PackageReference Include="Nito.AsyncEx" Version="5.1.2" /> <PackageReference Include="Nito.AsyncEx" Version="5.1.2" />
<PackageReference Include="NLog" Version="5.2.5" /> <PackageReference Include="NLog" Version="5.2.7" />
<PackageReference Include="NLog.Extensions.Logging" Version="5.3.5" /> <PackageReference Include="NLog.Extensions.Logging" Version="5.3.7" />
<PackageReference Include="NSubstitute" Version="5.1.0" /> <PackageReference Include="NSubstitute" Version="5.1.0" />
<PackageReference Include="Polly" Version="8.2.0" /> <PackageReference Include="Polly" Version="8.2.0" />
<PackageReference Include="Polly.Contrib.WaitAndRetry" Version="1.1.1" /> <PackageReference Include="Polly.Contrib.WaitAndRetry" Version="1.1.1" />
<PackageReference Include="Polly.Extensions.Http" Version="3.0.0" /> <PackageReference Include="Polly.Extensions.Http" Version="3.0.0" />
<PackageReference Include="Projektanker.Icons.Avalonia.FontAwesome" Version="8.3.0" /> <PackageReference Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.0.1" />
<PackageReference Include="RockLib.Reflection.Optimized" Version="2.0.0" /> <PackageReference Include="RockLib.Reflection.Optimized" Version="2.0.0" />
<PackageReference Include="Sentry" Version="3.41.0" /> <PackageReference Include="Sentry" Version="3.41.3" />
<PackageReference Include="Sentry.NLog" Version="3.41.0" /> <PackageReference Include="Sentry.NLog" Version="3.41.3" />
<PackageReference Include="SpacedGrid-Avalonia" Version="11.0.0" /> <PackageReference Include="SpacedGrid-Avalonia" Version="11.0.0" />
<PackageReference Include="Sylvan.Common" Version="0.4.3" /> <PackageReference Include="Sylvan.Common" Version="0.4.3" />
<PackageReference Include="Sylvan.Data" Version="0.2.12" /> <PackageReference Include="Sylvan.Data" Version="0.2.12" />

16
StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/HuggingFacePageViewModel.cs

@ -41,7 +41,8 @@ public partial class HuggingFacePageViewModel : TabViewModelBase
private readonly ISettingsManager settingsManager; private readonly ISettingsManager settingsManager;
private readonly INotificationService notificationService; private readonly INotificationService notificationService;
public SourceCache<HuggingfaceItem, string> ItemsCache { get; } = new(i => i.RepositoryPath + i.ModelName); public SourceCache<HuggingfaceItem, string> ItemsCache { get; } =
new(i => i.RepositoryPath + i.ModelName);
public IObservableCollection<CategoryViewModel> Categories { get; set; } = public IObservableCollection<CategoryViewModel> Categories { get; set; } =
new ObservableCollectionExtended<CategoryViewModel>(); new ObservableCollectionExtended<CategoryViewModel>();
@ -76,7 +77,13 @@ public partial class HuggingFacePageViewModel : TabViewModelBase
.Connect() .Connect()
.DeferUntilLoaded() .DeferUntilLoaded()
.Group(i => i.ModelCategory) .Group(i => i.ModelCategory)
.Transform(g => new CategoryViewModel(g.Cache.Items) { Title = g.Key.GetDescription() ?? g.Key.ToString() }) .Transform(
g =>
new CategoryViewModel(g.Cache.Items)
{
Title = g.Key.GetDescription() ?? g.Key.ToString()
}
)
.SortBy(vm => vm.Title) .SortBy(vm => vm.Title)
.Bind(Categories) .Bind(Categories)
.WhenAnyPropertyChanged() .WhenAnyPropertyChanged()
@ -137,12 +144,13 @@ public partial class HuggingFacePageViewModel : TabViewModelBase
{ {
foreach (var file in viewModel.Item.Files) foreach (var file in viewModel.Item.Files)
{ {
var url = $"https://huggingface.co/{viewModel.Item.RepositoryPath}/resolve/main/{file}?download=true"; var url =
$"https://huggingface.co/{viewModel.Item.RepositoryPath}/resolve/main/{file}?download=true";
var sharedFolderType = viewModel.Item.ModelCategory.ConvertTo<SharedFolderType>(); var sharedFolderType = viewModel.Item.ModelCategory.ConvertTo<SharedFolderType>();
var downloadPath = new FilePath( var downloadPath = new FilePath(
Path.Combine( Path.Combine(
settingsManager.ModelsDirectory, settingsManager.ModelsDirectory,
sharedFolderType.GetDescription() ?? sharedFolderType.ToString(), sharedFolderType.ToString(),
viewModel.Item.Subfolder ?? string.Empty, viewModel.Item.Subfolder ?? string.Empty,
file file
) )

19
StabilityMatrix.Avalonia/ViewModels/Inference/Modules/ControlNetModule.cs

@ -42,9 +42,8 @@ public class ControlNetModule : ModuleBase
{ {
Name = e.Nodes.GetUniqueName("ControlNet_LoadImage"), Name = e.Nodes.GetUniqueName("ControlNet_LoadImage"),
Image = Image =
card.SelectImageCardViewModel.ImageSource?.GetHashGuidFileNameCached( card.SelectImageCardViewModel.ImageSource?.GetHashGuidFileNameCached("Inference")
"Inference" ?? throw new ValidationException("No ImageSource")
) ?? throw new ValidationException("No ImageSource")
} }
); );
@ -53,8 +52,7 @@ public class ControlNetModule : ModuleBase
{ {
Name = e.Nodes.GetUniqueName("ControlNetLoader"), Name = e.Nodes.GetUniqueName("ControlNetLoader"),
ControlNetName = ControlNetName =
card.SelectedModel?.FileName card.SelectedModel?.RelativePath ?? throw new ValidationException("No SelectedModel"),
?? throw new ValidationException("No SelectedModel"),
} }
); );
@ -64,10 +62,8 @@ public class ControlNetModule : ModuleBase
Name = e.Nodes.GetUniqueName("ControlNetApply"), Name = e.Nodes.GetUniqueName("ControlNetApply"),
Image = imageLoad.Output1, Image = imageLoad.Output1,
ControlNet = controlNetLoader.Output, ControlNet = controlNetLoader.Output,
Positive = Positive = e.Temp.Conditioning?.Positive ?? throw new ArgumentException("No Conditioning"),
e.Temp.Conditioning?.Positive ?? throw new ArgumentException("No Conditioning"), Negative = e.Temp.Conditioning?.Negative ?? throw new ArgumentException("No Conditioning"),
Negative =
e.Temp.Conditioning?.Negative ?? throw new ArgumentException("No Conditioning"),
Strength = card.Strength, Strength = card.Strength,
StartPercent = card.StartPercent, StartPercent = card.StartPercent,
EndPercent = card.EndPercent, EndPercent = card.EndPercent,
@ -93,10 +89,7 @@ public class ControlNetModule : ModuleBase
} }
); );
e.Temp.RefinerConditioning = ( e.Temp.RefinerConditioning = (controlNetRefinerApply.Output1, controlNetRefinerApply.Output2);
controlNetRefinerApply.Output1,
controlNetRefinerApply.Output2
);
} }
} }
} }

21
StabilityMatrix.Avalonia/ViewModels/Inference/SelectImageCardViewModel.cs

@ -71,7 +71,9 @@ public partial class SelectImageCardViewModel(INotificationService notificationS
{ {
e.Builder.SetupImagePrimarySource( e.Builder.SetupImagePrimarySource(
ImageSource ?? throw new ValidationException("Input Image is required"), ImageSource ?? throw new ValidationException("Input Image is required"),
!CurrentBitmapSize.IsEmpty ? CurrentBitmapSize : throw new ValidationException("CurrentBitmapSize is null"), !CurrentBitmapSize.IsEmpty
? CurrentBitmapSize
: throw new ValidationException("CurrentBitmapSize is null"),
e.Builder.Connections.BatchIndex e.Builder.Connections.BatchIndex
); );
} }
@ -98,7 +100,10 @@ public partial class SelectImageCardViewModel(INotificationService notificationS
private async Task SelectImageFromFilePickerAsync() private async Task SelectImageFromFilePickerAsync()
{ {
var files = await App.StorageProvider.OpenFilePickerAsync( var files = await App.StorageProvider.OpenFilePickerAsync(
new FilePickerOpenOptions { FileTypeFilter = [FilePickerFileTypes.ImagePng, FilePickerFileTypes.ImageJpg] } new FilePickerOpenOptions
{
FileTypeFilter = [FilePickerFileTypes.ImagePng, FilePickerFileTypes.ImageJpg]
}
); );
if (files.FirstOrDefault()?.TryGetLocalPath() is { } path) if (files.FirstOrDefault()?.TryGetLocalPath() is { } path)
@ -112,7 +117,10 @@ public partial class SelectImageCardViewModel(INotificationService notificationS
/// </summary> /// </summary>
public void DragOver(object? sender, DragEventArgs e) public void DragOver(object? sender, DragEventArgs e)
{ {
if (e.Data.GetDataFormats().Contains(DataFormats.Files) || e.Data.GetContext<LocalImageFile>() is not null) if (
e.Data.GetDataFormats().Contains(DataFormats.Files)
|| e.Data.GetContext<LocalImageFile>() is not null
)
{ {
e.Handled = true; e.Handled = true;
return; return;
@ -134,7 +142,10 @@ public partial class SelectImageCardViewModel(INotificationService notificationS
return; return;
} }
// 2. OS Files // 2. OS Files
if (e.Data.GetFiles() is { } files && files.Select(f => f.TryGetLocalPath()).FirstOrDefault() is { } path) if (
e.Data.GetFiles() is { } files
&& files.Select(f => f.TryGetLocalPath()).FirstOrDefault() is { } path
)
{ {
e.Handled = true; e.Handled = true;
@ -154,7 +165,7 @@ public partial class SelectImageCardViewModel(INotificationService notificationS
catch (Exception e) catch (Exception e)
{ {
Logger.Warn(e, "Error loading image"); Logger.Warn(e, "Error loading image");
notificationService.ShowPersistent("Error loading image", e.Message); notificationService.Show("Error loading image", e.Message);
} }
} }

72
StabilityMatrix.Avalonia/Views/MainWindow.axaml.cs

@ -132,15 +132,16 @@ public partial class MainWindow : AppWindowBase
return; return;
// Navigate to first page // Navigate to first page
Dispatcher Dispatcher.UIThread.Post(
.UIThread () =>
.Post( navigationService.NavigateTo(
() => vm.Pages[0],
navigationService.NavigateTo( new BetterSlideNavigationTransition
vm.Pages[0], {
new BetterSlideNavigationTransition { Effect = SlideNavigationTransitionEffect.FromBottom } Effect = SlideNavigationTransitionEffect.FromBottom
) }
); )
);
// Check show update teaching tip // Check show update teaching tip
if (vm.UpdateViewModel.IsUpdateAvailable) if (vm.UpdateViewModel.IsUpdateAvailable)
@ -165,27 +166,24 @@ public partial class MainWindow : AppWindowBase
var mainViewModel = (MainWindowViewModel)DataContext!; var mainViewModel = (MainWindowViewModel)DataContext!;
mainViewModel.SelectedCategory = mainViewModel mainViewModel.SelectedCategory = mainViewModel
.Pages .Pages.Concat(mainViewModel.FooterPages)
.Concat(mainViewModel.FooterPages)
.FirstOrDefault(x => x.GetType() == e.ViewModelType); .FirstOrDefault(x => x.GetType() == e.ViewModelType);
} }
private void OnUpdateAvailable(object? sender, UpdateInfo? updateInfo) private void OnUpdateAvailable(object? sender, UpdateInfo? updateInfo)
{ {
Dispatcher Dispatcher.UIThread.Post(() =>
.UIThread {
.Post(() => if (DataContext is MainWindowViewModel vm && vm.ShouldShowUpdateAvailableTeachingTip(updateInfo))
{ {
if (DataContext is MainWindowViewModel vm && vm.ShouldShowUpdateAvailableTeachingTip(updateInfo)) var target = this.FindControl<NavigationViewItem>("FooterUpdateItem")!;
{ var tip = this.FindControl<TeachingTip>("UpdateAvailableTeachingTip")!;
var target = this.FindControl<NavigationViewItem>("FooterUpdateItem")!;
var tip = this.FindControl<TeachingTip>("UpdateAvailableTeachingTip")!;
tip.Target = target; tip.Target = target;
tip.Subtitle = $"{Compat.AppVersion.ToDisplayString()} -> {updateInfo.Version}"; tip.Subtitle = $"{Compat.AppVersion.ToDisplayString()} -> {updateInfo.Version}";
tip.IsOpen = true; tip.IsOpen = true;
} }
}); });
} }
public void SetDefaultFonts() public void SetDefaultFonts()
@ -282,18 +280,16 @@ public partial class MainWindow : AppWindowBase
private void OnImageLoadFailed(object? sender, ImageLoadFailedEventArgs e) private void OnImageLoadFailed(object? sender, ImageLoadFailedEventArgs e)
{ {
Dispatcher Dispatcher.UIThread.Post(() =>
.UIThread {
.Post(() => var fileName = Path.GetFileName(e.Url);
{ var displayName = string.IsNullOrEmpty(fileName) ? e.Url : fileName;
var fileName = Path.GetFileName(e.Url); notificationService.Show(
var displayName = string.IsNullOrEmpty(fileName) ? e.Url : fileName; "Failed to load image",
notificationService.ShowPersistent( $"Could not load '{displayName}'\n({e.Exception.Message})",
"Failed to load image", NotificationType.Warning
$"Could not load '{displayName}'\n({e.Exception.Message})", );
NotificationType.Warning });
);
});
} }
private void TryEnableMicaEffect() private void TryEnableMicaEffect()
@ -319,7 +315,11 @@ public partial class MainWindow : AppWindowBase
else if (ActualThemeVariant == ThemeVariant.Light) else if (ActualThemeVariant == ThemeVariant.Light)
{ {
// Similar effect here // Similar effect here
var color = this.TryFindResource("SolidBackgroundFillColorBase", ThemeVariant.Light, out var value) var color = this.TryFindResource(
"SolidBackgroundFillColorBase",
ThemeVariant.Light,
out var value
)
? (Color2)(Color)value! ? (Color2)(Color)value!
: new Color2(243, 243, 243); : new Color2(243, 243, 243);

29
StabilityMatrix.Core/Models/HybridModelFile.cs

@ -1,6 +1,7 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using StabilityMatrix.Core.Models.Database; using StabilityMatrix.Core.Models.Database;
using StabilityMatrix.Core.Models.FileInterfaces;
namespace StabilityMatrix.Core.Models; namespace StabilityMatrix.Core.Models;
@ -67,7 +68,27 @@ public record HybridModelFile
return "Default"; return "Default";
} }
return Path.GetFileNameWithoutExtension(RelativePath); var fileName = Path.GetFileNameWithoutExtension(RelativePath);
if (
!fileName.Equals("diffusion_pytorch_model", StringComparison.OrdinalIgnoreCase)
&& !fileName.Equals("ip_adapter", StringComparison.OrdinalIgnoreCase)
)
{
return Path.GetFileNameWithoutExtension(RelativePath);
}
// show a friendlier name when models have the same name like ip_adapter or diffusion_pytorch_model
var directoryName = Path.GetDirectoryName(RelativePath);
if (directoryName is null)
return Path.GetFileNameWithoutExtension(RelativePath);
var lastIndex = directoryName.LastIndexOf(Path.DirectorySeparatorChar);
if (lastIndex < 0)
return $"{fileName} ({directoryName})";
var parentDirectoryName = directoryName.Substring(lastIndex + 1);
return $"{fileName} ({parentDirectoryName})";
} }
} }
@ -83,11 +104,7 @@ public record HybridModelFile
public static HybridModelFile FromDownloadable(RemoteResource resource) public static HybridModelFile FromDownloadable(RemoteResource resource)
{ {
return new HybridModelFile return new HybridModelFile { DownloadableResource = resource, Type = HybridModelType.Downloadable };
{
DownloadableResource = resource,
Type = HybridModelType.Downloadable
};
} }
public string GetId() public string GetId()

1
StabilityMatrix.Core/Python/PipPackageInfo.cs

@ -10,4 +10,5 @@ public readonly record struct PipPackageInfo(
[JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.SnakeCaseLower)] [JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.SnakeCaseLower)]
[JsonSerializable(typeof(PipPackageInfo))] [JsonSerializable(typeof(PipPackageInfo))]
[JsonSerializable(typeof(List<PipPackageInfo>))]
internal partial class PipPackageInfoSerializerContext : JsonSerializerContext; internal partial class PipPackageInfoSerializerContext : JsonSerializerContext;

Loading…
Cancel
Save