Revamped parsing part 1

This commit is contained in:
Samuele Lorefice
2023-12-18 04:01:46 +01:00
parent a14301bfe6
commit 5e036a6a8b
4 changed files with 214 additions and 68 deletions

View File

@@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/Environment/Hierarchy/NuGetOptions/DefaultPackageManagementFormat/@EntryValue">PackageReference</s:String></wpf:ResourceDictionary>

View File

@@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Dynamic;
using System.Net; using System.Net;
using System.Net.Http.Json; using System.Net.Http.Json;
using System.Text.Json; using System.Text.Json;
@@ -8,7 +9,7 @@ namespace ComfySharp;
public class ComfyClient { public class ComfyClient {
private HttpClient client; private HttpClient client;
private List<Node> nodes; private List<ExpandoObject> nodes;
public string BaseUrl { get; set; } public string BaseUrl { get; set; }
@@ -18,7 +19,7 @@ public class ComfyClient {
BaseAddress = new Uri(baseUrl), BaseAddress = new Uri(baseUrl),
DefaultRequestHeaders = { { "User-Agent", "ComfySharp" } } DefaultRequestHeaders = { { "User-Agent", "ComfySharp" } }
}; };
nodes= new List<Node>(); nodes= new();
} }
public async Task<string[]?> GetEmbeddings() { public async Task<string[]?> GetEmbeddings() {
@@ -49,10 +50,10 @@ public class ComfyClient {
if (req is { IsSuccessStatusCode: true, Content: not null }) { if (req is { IsSuccessStatusCode: true, Content: not null }) {
var doc = await req.Content.ReadFromJsonAsync<JsonDocument>(); var doc = await req.Content.ReadFromJsonAsync<JsonDocument>();
ObjectInfoParser.Parse(doc, out nodes); ObjectInfoParser.Parse(doc, out nodes);
} }
throw new NotImplementedException(); return null;
//throw new NotImplementedException();
} }
public async Task<byte[]?> GetImage(string filename) { public async Task<byte[]?> GetImage(string filename) {

View File

@@ -1,75 +1,21 @@
using System.Text.Json; using System.Dynamic;
using System.Text.Json;
using ComfySharp.Types; using ComfySharp.Types;
namespace ComfySharp; namespace ComfySharp;
public static class ObjectInfoParser { public static class ObjectInfoParser {
public static void Parse(JsonDocument document, out List<Node> nodes) {
nodes = new List<Node>(); public static void Parse(JsonDocument document, out List<ExpandoObject> nodes) {
foreach (var node in document.RootElement.EnumerateObject()) { NodeDBGenerator dbGenerator = new();
Node n = new(); dbGenerator.GenerateNodes(document);
n.Name = node.Name; nodes = dbGenerator.GetNodes();
dbGenerator.GenerateClasses(document);
foreach (var prop in node.Value.EnumerateObject()) {
switch (prop.Name) {
case "input":
n.Input = new();
foreach (var input in prop.Value.EnumerateObject()) {
switch (input.Name) {
case "required":
foreach (var field in input.Value.EnumerateObject()) {
InputField f = new();
f.Name = field.Name;
f.Type = Enum.Parse<PrimitiveType>(field.Value.GetString() ?? "");
n.Input.Required.Add(f);
}
break;
case "optional":
foreach (var field in input.Value.EnumerateObject()) {
InputField f = new();
f.Name = field.Name;
f.Type = Enum.Parse<PrimitiveType>(field.Value.GetString() ?? "");
n.Input.Optional.Add(f);
}
break;
case "hidden":
foreach (var field in input.Value.EnumerateObject()) {
InputField f = new();
f.Name = field.Name;
f.Type = Enum.Parse<PrimitiveType>(field.Value.GetString() ?? "");
n.Input.Hidden.Add(f);
}
break;
}
}
break;
case "output":
foreach (var output in prop.Value.EnumerateObject()) {
n.Outputs.Add(Enum.Parse<PrimitiveType>(output.Value.GetString() ?? ""));
n.OutputIsList.Add(output.Value.GetBoolean());
n.OutputNames.Add(output.Name);
}
break;
case "display_name":
n.DisplayName = prop.Value.GetString() ?? "";
break;
case "description":
n.Description = prop.Value.GetString() ?? "";
break;
case "category":
n.Category = prop.Value.GetString() ?? "";
break;
case "output_node":
n.IsOutputNode = prop.Value.GetBoolean();
break;
}
}
}
} }
private static void ParseNode(JsonElement node, out Node n) { private static void ParseNode(JsonElement node, out Node n) {
n = new(); n = new();
n.Name = node.GetProperty("name").GetString() ?? ""; n.Name = node.GetProperty("name").GetString() ?? "";
n.Input = ParseInput(node.GetProperty("input")); n.Input = ParseInput(node.GetProperty("input"));
n.Outputs = ParseOutputs(node.GetProperty("output")); n.Outputs = ParseOutputs(node.GetProperty("output"));
@@ -80,4 +26,20 @@ public static class ObjectInfoParser {
n.Category = node.GetProperty("category").GetString() ?? ""; n.Category = node.GetProperty("category").GetString() ?? "";
n.IsOutputNode = node.GetProperty("output_node").GetBoolean(); n.IsOutputNode = node.GetProperty("output_node").GetBoolean();
} }
static private List<string> ParseOutputNames(JsonElement getProperty) {
List<string> outputNames = new();
foreach (var output in getProperty.EnumerateArray()) {
outputNames.Add(output.GetProperty("name").GetString() ?? "");
}
return outputNames;
}
static private List<bool> ParseOutputIsList(JsonElement getProperty) {
throw new NotImplementedException();
}
static private List<PrimitiveType> ParseOutputs(JsonElement getProperty) {
throw new NotImplementedException();
}
static private Input ParseInput(JsonElement getProperty) {
throw new NotImplementedException();
}
} }

View File

@@ -0,0 +1,181 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Dynamic;
using System.Runtime.CompilerServices;
namespace ComfySharp.Types;
public class NodeDBGenerator {
private List<ExpandoObject> nodes;
private List<string> knownTypes = new();
public List<string> GetKnownTypes() => knownTypes;
private Dictionary<string, List<string>> knownEnums = new();
public Dictionary<string, List<string>> GetKnownEnums() => knownEnums;
public int Count => nodes.Count;
private int typeFields = 0;
private int enumFields = 0;
public NodeDBGenerator() {
nodes = new();
}
public void ResetDb() => nodes.Clear();
/// <summary>
/// Adds a new type to the list of known types, avoids duplicates
/// </summary>
/// <param name="type">type name as string</param>
private void AddKnownType(string type) {
if (!knownTypes.Contains(type)) {
knownTypes.Add(type);
Console.WriteLine("Added new known type: {0}", type);
} else {
Console.WriteLine("Type {0} already known, skipped.", type);
}
typeFields++;
}
/// <summary>
/// Adds or updates a known enum, avoids duplicates.
/// </summary>
/// <param name="type">enum type name as string</param>
/// <param name="values">Collection of valid string values for this enum</param>
private void AddKnownEnum(string type, ICollection<string> values) {
if (!knownEnums.ContainsKey(type)) {
knownEnums.Add(type, values.ToList());
Console.WriteLine("Added new known enum: {0}", type);
}
else {
values.ToList().ForEach(value => {
if (!knownEnums[type].Contains(value)) {
knownEnums[type].Add(value);
Console.WriteLine("Added new value to known enum: {0}", value);
}
});
}
enumFields++;
}
public void GenerateClasses(JsonDocument document) {
foreach (var node in document.RootElement.EnumerateObject()) ScanNode(node);
Console.WriteLine("List of recognized Types:");
foreach (var knownType in knownTypes) {
Console.WriteLine(knownType);
}
Console.WriteLine("\nTotal amount of types iterated: {0}\n", typeFields);
Console.WriteLine("List of recognized Enums:");
foreach (var knownEnum in knownEnums) {
Console.WriteLine(knownEnum.Key);
foreach (var value in knownEnum.Value) {
Console.Write("\t{0}", value);
}
Console.WriteLine();
}
Console.WriteLine("\nTotal amount of enums iterated: {0}\n", enumFields);
}
/// <summary>
/// executed for a single node, progresses through the properties of the node
/// </summary>
private void ScanNode(JsonProperty node) {
// each of this are top level properties of the node
foreach (var property in node.Value.EnumerateObject()) {
//if this is a list of input properties:
if (property.Name == "input" && property.Value.ValueKind == JsonValueKind.Object) ScanInputs(property);
else if (property.Name == "output" && property.Value.ValueKind == JsonValueKind.Array) ScanOutputs(property);
}
}
/// <summary>
/// Executed on the input property inside a node
/// </summary>
private void ScanInputs(JsonProperty input) {
foreach (var inputType in input.Value.EnumerateObject()) {
//these are related to the nodes themselves and useless for us
if (inputType.Name == "hidden") continue;
// required and optionals have the same structure, so we can parse them the same way
if (inputType.Name == "required" || inputType.Name == "optional")
foreach (var inputProperty in inputType.Value.EnumerateObject()) ScanInputField(inputProperty);
}
}
/// <summary>
/// Executed for each of the elements inside a required or optional input
/// </summary>
private void ScanInputField(JsonProperty inputProperty) {
// if element 0 is a string, this is a type
if (inputProperty.Value[0].ValueKind == JsonValueKind.String)
AddKnownType(inputProperty.Value[0].ToString());
// else, if element 0 is an array, this is an enum
else if (inputProperty.Value[0].ValueKind == JsonValueKind.Array) {
List<string> enumValues = new();
inputProperty.Value[0].EnumerateArray().ToList().ForEach(value => enumValues.Add(value.ToString()));
AddKnownEnum(inputProperty.Name, enumValues);
}
}
private void ScanOutputs(JsonProperty output) { }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void GenerateNode(JsonElement data) {
var node = new ExpandoObject();
Console.WriteLine("Generating node: {0}", data.GetProperty("name").GetString() ?? "");
foreach (var property in data.EnumerateObject()) {
Console.WriteLine("Adding new property: {0}\nType: {2}\nValue: {1}\n", property.Name, property.Value, property.Value.GetType());
node.TryAdd(property.Name, property.Value);
}
nodes.Add(node);
}
public void GenerateNode(JsonProperty node) {
GenerateNode(node.Value);
}
public void GenerateNodes(JsonDocument document) {
foreach (var node in document.RootElement.EnumerateObject()) {
GenerateNode(node.Value);
}
}
public void GenerateNodes(string json) {
var document = JsonDocument.Parse(json);
GenerateNodes(document);
}
public void GenerateNodes(ICollection<JsonElement> elements) {
foreach (var element in elements) {
GenerateNode(element);
}
}
public void GenerateNodes(ICollection<JsonProperty> elements) {
foreach (var element in elements) {
GenerateNode(element);
}
}
public List<ExpandoObject> GetNodes() => nodes;
}