Merge branch 'dev' into claire/cnx-849

This commit is contained in:
Claire Kuang
2024-12-03 22:18:24 +00:00
committed by GitHub
23 changed files with 83 additions and 123 deletions
@@ -1,5 +1,3 @@
#nullable disable
using System.Reflection;
using GraphQL.Client.Abstractions.Utilities;
using Speckle.Newtonsoft.Json;
@@ -9,7 +7,7 @@ namespace Speckle.Sdk.Api.GraphQL.Serializer;
internal class ConstantCaseEnumConverter : StringEnumConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
if (value == null)
{
@@ -18,7 +16,7 @@ internal class ConstantCaseEnumConverter : StringEnumConverter
else
{
var enumString = ((Enum)value).ToString("G");
var memberName = value
string? memberName = value
.GetType()
.GetMember(enumString, BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public)
.FirstOrDefault()
@@ -34,7 +32,9 @@ internal class ConstantCaseEnumConverter : StringEnumConverter
}
else
{
#pragma warning disable CS8604 // Possible null reference argument. //never null?
writer.WriteValue(memberName.ToConstantCase());
#pragma warning restore CS8604 // Possible null reference argument.
}
}
}
@@ -1,4 +1,3 @@
#nullable disable
using System.Diagnostics.CodeAnalysis;
using GraphQL;
using Speckle.Newtonsoft.Json;
@@ -8,7 +7,7 @@ namespace Speckle.Sdk.Api.GraphQL.Serializer;
internal sealed class MapConverter : JsonConverter<Map>
{
public override void WriteJson(JsonWriter writer, Map value, JsonSerializer serializer)
public override void WriteJson(JsonWriter writer, Map? value, JsonSerializer serializer)
{
throw new NotImplementedException(
"This converter currently is only intended to be used to read a JSON object into a strongly-typed representation."
@@ -18,7 +17,7 @@ internal sealed class MapConverter : JsonConverter<Map>
public override Map ReadJson(
JsonReader reader,
Type objectType,
Map existingValue,
Map? existingValue,
bool hasExistingValue,
JsonSerializer serializer
)
@@ -39,16 +38,23 @@ internal sealed class MapConverter : JsonConverter<Map>
)]
private object ReadToken(JToken token)
{
return token switch
switch (token)
{
JObject jObject => ReadDictionary(jObject, new Dictionary<string, object>()),
JArray jArray => ReadArray(jArray).ToList(),
JValue jValue => jValue.Value,
JConstructor => throw new ArgumentOutOfRangeException(nameof(token), "cannot deserialize a JSON constructor"),
JProperty => throw new ArgumentOutOfRangeException(nameof(token), "cannot deserialize a JSON property"),
JContainer => throw new ArgumentOutOfRangeException(nameof(token), "cannot deserialize a JSON comment"),
_ => throw new ArgumentOutOfRangeException(nameof(token), $"Invalid token type {token?.Type}"),
};
case JObject jObject:
return ReadDictionary(jObject, new Dictionary<string, object>());
case JArray jArray:
return ReadArray(jArray).ToList();
case JValue jValue:
return jValue.Value ?? string.Empty;
case JConstructor:
throw new ArgumentOutOfRangeException(nameof(token), "cannot deserialize a JSON constructor");
case JProperty:
throw new ArgumentOutOfRangeException(nameof(token), "cannot deserialize a JSON property");
case JContainer:
throw new ArgumentOutOfRangeException(nameof(token), "cannot deserialize a JSON comment");
default:
throw new ArgumentOutOfRangeException(nameof(token), $"Invalid token type {token?.Type}");
}
}
private Dictionary<string, object> ReadDictionary(JToken element, Dictionary<string, object> to)
@@ -1,10 +1,10 @@
#nullable disable
using System.Text;
using GraphQL;
using GraphQL.Client.Abstractions;
using GraphQL.Client.Abstractions.Websocket;
using Speckle.Newtonsoft.Json;
using Speckle.Newtonsoft.Json.Serialization;
using Speckle.Sdk.Common;
using Speckle.Sdk.Serialisation;
namespace Speckle.Sdk.Api.GraphQL.Serializer;
@@ -51,10 +51,9 @@ internal sealed class NewtonsoftJsonSerializer : IGraphQLWebsocketJsonSerializer
public GraphQLWebSocketResponse<TResponse> DeserializeToWebsocketResponse<TResponse>(byte[] bytes)
{
return JsonConvert.DeserializeObject<GraphQLWebSocketResponse<TResponse>>(
Encoding.UTF8.GetString(bytes),
JsonSerializerSettings
);
return JsonConvert
.DeserializeObject<GraphQLWebSocketResponse<TResponse>>(Encoding.UTF8.GetString(bytes), JsonSerializerSettings)
.NotNull();
}
public Task<GraphQLResponse<TResponse>> DeserializeFromUtf8StreamAsync<TResponse>(
@@ -79,6 +78,6 @@ internal sealed class NewtonsoftJsonSerializer : IGraphQLWebsocketJsonSerializer
using var sr = new StreamReader(stream);
using JsonReader reader = SpeckleObjectSerializerPool.Instance.GetJsonTextReader(sr);
var serializer = JsonSerializer.Create(serializerSettings);
return Task.FromResult(serializer.Deserialize<T>(reader));
return Task.FromResult(serializer.Deserialize<T>(reader) ?? throw new ArgumentException("Serialized data is null"));
}
}
+3 -4
View File
@@ -1,4 +1,3 @@
#nullable disable
using System.Runtime.InteropServices;
using Speckle.Sdk.Api.GraphQL.Models;
using Speckle.Sdk.Helpers;
@@ -48,7 +47,7 @@ public class Account : IEquatable<Account>
private static string CleanURL(string server)
{
if (Uri.TryCreate(server, UriKind.Absolute, out Uri newUri))
if (Uri.TryCreate(server, UriKind.Absolute, out Uri? newUri))
{
server = newUri.Authority;
}
@@ -77,12 +76,12 @@ public class Account : IEquatable<Account>
return $"Account ({userInfo.email} | {serverInfo.url})";
}
public bool Equals(Account other)
public bool Equals(Account? other)
{
return other is not null && other.userInfo.email == userInfo.email && other.serverInfo.url == serverInfo.url;
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return obj is Account acc && Equals(acc);
}
@@ -248,7 +248,7 @@ public class AccountManager(
account.serverInfo.frontend2 = true;
// setting the id to null will force it to be recreated
account.id = null;
account.id = null!; //TODO this is gross so remove when id is nullable
RemoveAccount(id);
_accountStorage.SaveObject(account.id.NotNull(), JsonConvert.SerializeObject(account));
+3 -4
View File
@@ -1,4 +1,3 @@
#nullable disable
namespace Speckle.Sdk.Host;
[AttributeUsage(AttributeTargets.Constructor)]
@@ -7,7 +6,7 @@ public sealed class SchemaInfoAttribute : Attribute
public SchemaInfoAttribute(string name, string description)
: this(name, description, null, null) { }
public SchemaInfoAttribute(string name, string description, string category, string subcategory)
public SchemaInfoAttribute(string name, string description, string? category, string? subcategory)
{
Name = name;
Description = description;
@@ -15,9 +14,9 @@ public sealed class SchemaInfoAttribute : Attribute
Subcategory = subcategory;
}
public string Subcategory { get; }
public string? Subcategory { get; }
public string Category { get; }
public string? Category { get; }
public string Description { get; }
+2 -5
View File
@@ -1,4 +1,3 @@
#nullable disable
using System.Collections;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
@@ -24,15 +23,13 @@ namespace Speckle.Sdk.Models;
[SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Serialized property names are camelCase by design")]
public class Base : DynamicBase, ISpeckleObject
{
private string _type;
private string? _type;
/// <summary>
/// A speckle object's id is an unique hash based on its properties. <b>NOTE: this field will be null unless the object was deserialised from a source. Use the <see cref="GetId"/> function to get it.</b>
/// </summary>
[SchemaIgnore]
public virtual string id { get; set; }
#nullable enable //Starting nullability syntax here so that `id` null oblivious,
public virtual string? id { get; set; }
/// <summary>
/// Secondary, ideally host application driven, object identifier.
+5 -5
View File
@@ -1,5 +1,4 @@
#nullable disable
using System.Runtime.Serialization;
using System.Runtime.Serialization;
using Speckle.Newtonsoft.Json;
namespace Speckle.Sdk.Models;
@@ -38,13 +37,13 @@ public class Blob : Base
/// <summary>
/// For blobs, the id is the same as the file hash. Please note, when deserialising, the id will be set from the original hash generated on sending.
/// </summary>
public override string id
public override string? id
{
get => GetFileHash();
set => base.id = value;
}
public string GetFileHash()
public string? GetFileHash()
{
if ((_isHashExpired || _hash == null) && filePath != null)
{
@@ -63,6 +62,7 @@ public class Blob : Base
public string GetLocalDestinationPath(string blobStorageFolder)
{
var fileName = Path.GetFileName(filePath);
return Path.Combine(blobStorageFolder, $"{id[..10]}-{fileName}");
var x = id ?? throw new ArgumentException("id is empty");
return Path.Combine(blobStorageFolder, $"{x[..10]}-{fileName}");
}
}
@@ -1,5 +1,6 @@
using System.Collections;
using System.Diagnostics.Contracts;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models.Collections;
namespace Speckle.Sdk.Models.Extensions;
@@ -31,7 +32,7 @@ public static class BaseExtensions
root,
b =>
{
if (!cache.Add(b.id))
if (!cache.Add(b.id.NotNull()))
{
return true;
}
@@ -42,7 +43,7 @@ public static class BaseExtensions
foreach (var b in traversal)
{
if (!cache.Contains(b.id))
if (!cache.Contains(b.id.NotNull()))
{
yield return b;
}
+1 -4
View File
@@ -2,10 +2,7 @@
public interface ISpeckleObject
{
#nullable disable
public string id { get; }
#nullable enable //Starting nullability syntax here so that `id` null oblivious,
public string? id { get; }
public string? applicationId { get; }
@@ -362,7 +362,7 @@ public class SpeckleObjectSerializer
}
else
{
id = new Id(((Blob)baseObj).id);
id = new Id(((Blob)baseObj).id.NotNull());
}
writer.WritePropertyName("id");
writer.WriteValue(id.Value);
@@ -20,7 +20,6 @@ public class ObjectSerializer : IObjectSerializer
{
private HashSet<object> _parentObjects = new();
private readonly Dictionary<Id, int> _currentClosures = new();
private readonly IDictionary<Base, CacheInfo> _baseCache;
private readonly bool _trackDetachedChildren;
private readonly IBasePropertyGatherer _propertyGatherer;
@@ -41,12 +40,10 @@ public class ObjectSerializer : IObjectSerializer
/// <param name="cancellationToken"></param>
public ObjectSerializer(
IBasePropertyGatherer propertyGatherer,
IDictionary<Base, CacheInfo> baseCache,
bool trackDetachedChildren = false,
CancellationToken cancellationToken = default
)
{
_baseCache = baseCache;
_propertyGatherer = propertyGatherer;
_cancellationToken = cancellationToken;
_trackDetachedChildren = trackDetachedChildren;
@@ -69,7 +66,6 @@ public class ObjectSerializer : IObjectSerializer
{
throw new SpeckleSerializeException($"Failed to extract (pre-serialize) properties from the {baseObj}", ex);
}
_baseCache[baseObj] = new(item.Item2, _currentClosures);
yield return (item.Item1, item.Item2);
foreach (var chunk in _chunks)
{
@@ -232,26 +228,13 @@ public class ObjectSerializer : IObjectSerializer
return null;
}
Closures childClosures;
Id id;
Json json;
if (_baseCache.TryGetValue(baseObj, out var info))
{
id = new Id(baseObj.id);
childClosures = info.Closures;
json = info.Json;
MergeClosures(_currentClosures, childClosures);
}
else
{
childClosures = isRoot || inheritedDetachInfo.IsDetachable ? _currentClosures : [];
var sb = Pools.StringBuilders.Get();
using var writer = new StringWriter(sb);
using var jsonWriter = SpeckleObjectSerializerPool.Instance.GetJsonTextWriter(writer);
id = SerializeBaseObject(baseObj, jsonWriter, childClosures);
json = new Json(writer.ToString());
Pools.StringBuilders.Return(sb);
}
var childClosures = isRoot || inheritedDetachInfo.IsDetachable ? _currentClosures : [];
var sb = Pools.StringBuilders.Get();
using var writer = new StringWriter(sb);
using var jsonWriter = SpeckleObjectSerializerPool.Instance.GetJsonTextWriter(writer);
var id = SerializeBaseObject(baseObj, jsonWriter, childClosures);
var json = new Json(writer.ToString());
Pools.StringBuilders.Return(sb);
_parentObjects.Remove(baseObj);
@@ -311,7 +294,7 @@ public class ObjectSerializer : IObjectSerializer
}
else
{
id = new Id(((Blob)baseObj).id);
id = new Id(((Blob)baseObj).id.NotNull());
}
writer.WritePropertyName("id");
writer.WriteValue(id.Value);
@@ -1,11 +1,10 @@
using Speckle.InterfaceGenerator;
using Speckle.Sdk.Models;
namespace Speckle.Sdk.Serialisation.V2.Send;
[GenerateAutoInterface]
public class ObjectSerializerFactory(IBasePropertyGatherer propertyGatherer) : IObjectSerializerFactory
{
public IObjectSerializer Create(IDictionary<Base, CacheInfo> baseCache, CancellationToken cancellationToken) =>
new ObjectSerializer(propertyGatherer, baseCache, true, cancellationToken);
public IObjectSerializer Create(CancellationToken cancellationToken) =>
new ObjectSerializer(propertyGatherer, true, cancellationToken);
}
@@ -9,7 +9,7 @@ using Speckle.Sdk.Transports;
namespace Speckle.Sdk.Serialisation.V2.Send;
public record SerializeProcessOptions(bool SkipCacheRead, bool SkipCacheWrite, bool SkipServer, bool CacheBases);
public record SerializeProcessOptions(bool SkipCacheRead, bool SkipCacheWrite, bool SkipServer);
public readonly record struct SerializeProcessResults(
string RootId,
@@ -26,11 +26,8 @@ public class SerializeProcess(
SerializeProcessOptions? options = null
) : ChannelSaver, ISerializeProcess
{
private readonly SerializeProcessOptions _options = options ?? new(false, false, false, true);
private readonly SerializeProcessOptions _options = options ?? new(false, false, false);
private readonly ConcurrentDictionary<Id, Json> _jsonCache = new();
private readonly IDictionary<Base, CacheInfo> _baseCache =
options?.CacheBases ?? true ? new ConcurrentDictionary<Base, CacheInfo>() : new EmptyDictionary<Base, CacheInfo>();
private readonly ConcurrentDictionary<Id, ObjectReference> _objectReferences = new();
private long _totalFound;
@@ -44,7 +41,7 @@ public class SerializeProcess(
var channelTask = Start(cancellationToken);
await Traverse(root, true, cancellationToken).ConfigureAwait(false);
await channelTask.ConfigureAwait(false);
return new(root.id, _objectReferences.Freeze());
return new(root.id.NotNull(), _objectReferences.Freeze());
}
private async Task Traverse(Base obj, bool isEnd, CancellationToken cancellationToken)
@@ -110,7 +107,7 @@ public class SerializeProcess(
}
if (id is null || !_jsonCache.TryGetValue(id.Value, out var json))
{
var serializer2 = objectSerializerFactory.Create(_baseCache, cancellationToken);
var serializer2 = objectSerializerFactory.Create(cancellationToken);
var items = serializer2.Serialize(obj).ToList();
foreach (var kvp in serializer2.ObjectReferences)
{
@@ -61,7 +61,7 @@ var process2 = factory.CreateSerializeProcess(
streamId,
token,
progress,
new SerializeProcessOptions(skipCacheSendCheck, skipCacheSendSave, true, true)
new SerializeProcessOptions(skipCacheSendCheck, skipCacheSendSave, true)
);
await process2.Serialize(@base, default).ConfigureAwait(false);
Console.WriteLine("Detach");
@@ -26,9 +26,7 @@ public class DetachedTests
}
[Test(Description = "Checks that all typed properties (including obsolete ones) are returned")]
[TestCase(true)]
[TestCase(false)]
public async Task CanSerialize_New_Detached(bool cacheBases)
public async Task CanSerialize_New_Detached()
{
var expectedJson = """
{
@@ -76,7 +74,7 @@ public class DetachedTests
new DummyServerObjectManager(),
new BaseChildFinder(new BasePropertyGatherer()),
new ObjectSerializerFactory(new BasePropertyGatherer()),
new SerializeProcessOptions(false, false, true, cacheBases)
new SerializeProcessOptions(false, false, true)
);
await process2.Serialize(@base, default).ConfigureAwait(false);
@@ -193,9 +191,7 @@ public class DetachedTests
}
[Test(Description = "Checks that all typed properties (including obsolete ones) are returned")]
[TestCase(true)]
[TestCase(false)]
public async Task CanSerialize_New_Detached2(bool cacheBases)
public async Task CanSerialize_New_Detached2()
{
var root = """
@@ -270,7 +266,7 @@ public class DetachedTests
new DummyServerObjectManager(),
new BaseChildFinder(new BasePropertyGatherer()),
new ObjectSerializerFactory(new BasePropertyGatherer()),
new SerializeProcessOptions(false, false, true, cacheBases)
new SerializeProcessOptions(false, false, true)
);
var results = await process2.Serialize(@base, default).ConfigureAwait(false);
@@ -1,5 +1,4 @@
using System.Collections.Concurrent;
using NUnit.Framework;
using NUnit.Framework;
using Shouldly;
using Speckle.Newtonsoft.Json.Linq;
using Speckle.Objects.Geometry;
@@ -27,11 +26,7 @@ public class ExternalIdTests
public void ExternalIdTest_Detached(string lineId, string valueId)
{
var p = new Polyline() { units = "cm", value = [1, 2] };
var serializer = new ObjectSerializer(
new BasePropertyGatherer(),
new ConcurrentDictionary<Base, CacheInfo>(),
true
);
var serializer = new ObjectSerializer(new BasePropertyGatherer(), true);
var list = serializer.Serialize(p).ToDictionary(x => x.Item1, x => x.Item2);
list.ContainsKey(new Id(lineId)).ShouldBeTrue();
var json = list[new Id(lineId)];
@@ -58,11 +53,7 @@ public class ExternalIdTests
knots = [],
weights = [],
};
var serializer = new ObjectSerializer(
new BasePropertyGatherer(),
new ConcurrentDictionary<Base, CacheInfo>(),
true
);
var serializer = new ObjectSerializer(new BasePropertyGatherer(), true);
var list = serializer.Serialize(curve).ToDictionary(x => x.Item1, x => x.Item2);
list.ContainsKey(new Id(lineId)).ShouldBeTrue();
var json = list[new Id(lineId)];
@@ -90,11 +81,7 @@ public class ExternalIdTests
weights = [],
};
var polycurve = new Polycurve() { segments = [curve], units = "cm" };
var serializer = new ObjectSerializer(
new BasePropertyGatherer(),
new ConcurrentDictionary<Base, CacheInfo>(),
true
);
var serializer = new ObjectSerializer(new BasePropertyGatherer(), true);
var list = serializer.Serialize(polycurve).ToDictionary(x => x.Item1, x => x.Item2);
list.ContainsKey(new Id(lineId)).ShouldBeTrue();
var json = list[new Id(lineId)];
@@ -124,11 +111,7 @@ public class ExternalIdTests
var polycurve = new Polycurve() { segments = [curve], units = "cm" };
var @base = new Base();
@base.SetDetachedProp("profile", polycurve);
var serializer = new ObjectSerializer(
new BasePropertyGatherer(),
new ConcurrentDictionary<Base, CacheInfo>(),
true
);
var serializer = new ObjectSerializer(new BasePropertyGatherer(), true);
var list = serializer.Serialize(@base).ToDictionary(x => x.Item1, x => x.Item2);
list.ContainsKey(new Id(lineId)).ShouldBeTrue();
var json = list[new Id(lineId)];
@@ -228,7 +228,7 @@ public class SerializationTests
var j = serializer.Serialize(base1);
//j.ShouldBe(objJson);
JToken.DeepEquals(JObject.Parse(j), JObject.Parse(objJson));
newIds.Add(base1.id, j);
newIds.Add(base1.id.NotNull(), j);
oldIds.Add(id, j);
idToBase.Add(id, base1);
}
@@ -263,7 +263,7 @@ public class SerializationTests
new DummySendServerObjectManager(newIdToJson),
new BaseChildFinder(new BasePropertyGatherer()),
new ObjectSerializerFactory(new BasePropertyGatherer()),
new SerializeProcessOptions(true, true, false, true)
new SerializeProcessOptions(true, true, false)
);
var (rootId2, _) = await serializeProcess.Serialize(root, default);
@@ -2,6 +2,7 @@
using Speckle.Sdk.Api.GraphQL.Inputs;
using Speckle.Sdk.Api.GraphQL.Models;
using Speckle.Sdk.Api.GraphQL.Resources;
using Speckle.Sdk.Common;
namespace Speckle.Sdk.Tests.Integration.API.GraphQL.Resources;
@@ -76,7 +77,7 @@ public class CommentResourceTests
public async Task Edit()
{
var blobs = await Fixtures.SendBlobData(_testUser.Account, _project.id);
var blobIds = blobs.Select(b => b.id).ToList();
var blobIds = blobs.Select(b => b.id.NotNull()).ToList();
EditCommentInput input = new(new(blobIds, null), _comment.id, _project.id);
var editedComment = await Sut.Edit(input);
@@ -92,7 +93,7 @@ public class CommentResourceTests
public async Task Reply()
{
var blobs = await Fixtures.SendBlobData(_testUser.Account, _project.id);
var blobIds = blobs.Select(b => b.id).ToList();
var blobIds = blobs.Select(b => b.id.NotNull()).ToList();
CreateCommentReplyInput input = new(new(blobIds, null), _comment.id, _project.id);
var editedComment = await Sut.Reply(input);
@@ -4,6 +4,7 @@ using Speckle.Sdk.Api.GraphQL.Enums;
using Speckle.Sdk.Api.GraphQL.Inputs;
using Speckle.Sdk.Api.GraphQL.Models;
using Speckle.Sdk.Api.GraphQL.Resources;
using Speckle.Sdk.Common;
namespace Speckle.Sdk.Tests.Integration.API.GraphQL.Resources;
@@ -88,7 +89,7 @@ public class ProjectResourceExceptionalTests
[TestCase(StreamRoles.REVOKE)]
public void ProjectUpdateRole_NonExistentProject(string newRole)
{
ProjectUpdateRoleInput input = new(_secondUser.Account.id, "NonExistentProject", newRole);
ProjectUpdateRoleInput input = new(_secondUser.Account.id.NotNull(), "NonExistentProject", newRole);
var ex = Assert.ThrowsAsync<AggregateException>(async () => _ = await Sut.UpdateRole(input));
Assert.That(ex?.InnerExceptions, Has.One.Items.And.All.TypeOf<SpeckleGraphQLForbiddenException>());
@@ -101,7 +102,7 @@ public class ProjectResourceExceptionalTests
[TestCase(StreamRoles.REVOKE)]
public void ProjectUpdateRole_NonAuth(string newRole)
{
ProjectUpdateRoleInput input = new(_secondUser.Account.id, "NonExistentProject", newRole);
ProjectUpdateRoleInput input = new(_secondUser.Account.id.NotNull(), "NonExistentProject", newRole);
var ex = Assert.ThrowsAsync<AggregateException>(async () => _ = await _unauthedUser.Project.UpdateRole(input));
Assert.That(ex?.InnerExceptions, Has.One.Items.And.All.TypeOf<SpeckleGraphQLForbiddenException>());
@@ -159,7 +159,7 @@ public static class Fixtures
internal static async Task<Comment> CreateComment(Client client, string projectId, string modelId, string versionId)
{
var blobs = await SendBlobData(client.Account, projectId);
var blobIds = blobs.Select(b => b.id).ToList();
var blobIds = blobs.Select(b => b.id.NotNull()).ToList();
CreateCommentInput input = new(new(blobIds, null), projectId, $"{projectId},{modelId},{versionId}", null, null);
return await client.Comment.Create(input);
}
+2 -1
View File
@@ -1,4 +1,5 @@
using Newtonsoft.Json;
using Speckle.Sdk.Common;
using Speckle.Sdk.Credentials;
using Speckle.Sdk.Logging;
using Speckle.Sdk.Transports;
@@ -16,7 +17,7 @@ public abstract class Fixtures
public static void UpdateOrSaveAccount(Account account)
{
DeleteLocalAccount(account.id);
DeleteLocalAccount(account.id.NotNull());
string serializedObject = JsonConvert.SerializeObject(account);
s_accountStorage.SaveObjectSync(account.id, serializedObject);
}
@@ -1,4 +1,5 @@
using NUnit.Framework;
using Speckle.Sdk.Common;
using Speckle.Sdk.Models;
using Speckle.Sdk.Models.Extensions;
@@ -25,7 +26,7 @@ public class TraversalTests
},
};
static bool BreakRule(Base b) => b.id.Contains("break on me");
static bool BreakRule(Base b) => b.id.NotNull().Contains("break on me");
//Flatten
var ret = root.Flatten(BreakRule).ToList();