Skip to content

Commit 421f31e

Browse files
feat: add property "kind" to resources and infer it from "paths" (#177)
* feat: add property "kind" to resources --------- Co-authored-by: codefactor-io <support@codefactor.io>
1 parent 7d63cf1 commit 421f31e

26 files changed

+358
-136
lines changed

src/Packata.Core.Testing/Serialization/ExtensionSerializerTests.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,21 @@ public void Deserialize_Package_Success((Stream Stream, IDataPackageSerializer S
5353
});
5454
}
5555

56+
57+
[TestCaseSource(nameof(GetData))]
58+
public void Deserialize_ResourceKind_Success((Stream Stream, IDataPackageSerializer Serializer) value)
59+
{
60+
using var streamReader = new StreamReader(value.Stream);
61+
var dataPackage = value.Serializer.Deserialize(streamReader, new LocalDirectoryDataPackageContainer(), new StorageProvider());
62+
Assert.That(dataPackage.Resources, Is.Not.Null);
63+
Assert.That(dataPackage.Resources, Has.Count.EqualTo(1));
64+
Assert.Multiple(() =>
65+
{
66+
Assert.That(dataPackage.Resources[0].Kind, Is.EqualTo("local"));
67+
});
68+
}
69+
70+
5671
[TestCaseSource(nameof(GetData))]
5772
public void Deserialize_Metrics_Success((Stream Stream, IDataPackageSerializer Serializer) value)
5873
{

src/Packata.Core.Testing/Serialization/Json/Resources/extension.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"name": "measures",
1414
"path": "sensor_measures.csv",
1515
"type": "table",
16+
"kind": "local",
1617
"$schema": "https://packata.dev/profiles/1.0/dataresource.json",
1718
"title": "Sensors' temperatures & hygrometry",
1819
"format": "csv",

src/Packata.Core.Testing/Serialization/Yaml/Resources/extension.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ resources:
1010
- name: measures
1111
path: sensor_measures.csv
1212
type: table
13+
kind: local
1314
"$schema": https://packata.dev/profiles/1.0/dataresource.json
1415
title: "Sensors' temperatures & hygrometry"
1516
format: csv

src/Packata.Core/Resource.Props.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ public partial class Resource
4747
/// <example>"table"</example>
4848
public string? Type { get; set; }
4949

50+
/// <summary>
51+
/// The type of the resource.
52+
/// </summary>
53+
/// <remarks>Specifies the nature of the resource, such as "table".</remarks>
54+
/// <example>"virtual", "local", "service", "remote"</example>
55+
public string? Kind { get; set; }
56+
5057
/// <summary>
5158
/// The file format of the resource.
5259
/// </summary>

src/Packata.ResourceReaders.Testing/Inference/FormatBasedDialectInferenceTests.cs

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@ public void TryInfer_ShouldReturnFalse_WhenFormatIsNullOrEmpty()
1515

1616
var result = inference.TryInfer(resource, out var dialect);
1717

18-
Assert.That(result, Is.False);
19-
Assert.That(dialect, Is.Null);
18+
using (Assert.EnterMultipleScope())
19+
{
20+
Assert.That(result, Is.False);
21+
Assert.That(dialect, Is.Null);
22+
}
2023
}
2124

2225
[Test]
@@ -33,11 +36,16 @@ public void TryInfer_ShouldReturnTrueAndSetDialect_WhenFormatIsKnown(
3336

3437
Assert.That(result, Is.True);
3538
Assert.That(dialect, Is.Not.Null);
36-
Assert.That(dialect!.Delimiter, Is.EqualTo(delimiter));
37-
Assert.That(dialect.QuoteChar, Is.EqualTo(quoteChar));
38-
Assert.That(dialect.EscapeChar, Is.EqualTo(escapeChar));
39-
Assert.That(dialect.DoubleQuote, Is.EqualTo(doubleQuote));
40-
Assert.That(dialect.LineTerminator, Is.EqualTo(lineTerminator));
39+
Assert.That(dialect, Is.TypeOf<TableDelimitedDialect>());
40+
var tdDialect = (TableDelimitedDialect)dialect;
41+
using (Assert.EnterMultipleScope())
42+
{
43+
Assert.That(tdDialect.Delimiter, Is.EqualTo(delimiter));
44+
Assert.That(tdDialect.QuoteChar, Is.EqualTo(quoteChar));
45+
Assert.That(tdDialect.EscapeChar, Is.EqualTo(escapeChar));
46+
Assert.That(tdDialect.DoubleQuote, Is.EqualTo(doubleQuote));
47+
Assert.That(tdDialect.LineTerminator, Is.EqualTo(lineTerminator));
48+
}
4149
}
4250

4351
[Test]
@@ -48,8 +56,11 @@ public void TryInfer_ShouldReturnFalse_WhenFormatIsUnknown()
4856

4957
var result = inference.TryInfer(resource, out var dialect);
5058

51-
Assert.That(result, Is.False);
52-
Assert.That(dialect, Is.Null);
59+
using (Assert.EnterMultipleScope())
60+
{
61+
Assert.That(result, Is.False);
62+
Assert.That(dialect, Is.Null);
63+
}
5364
}
5465
}
5566
}

src/Packata.ResourceReaders.Testing/Inference/MediaTypeBasedDialectInferenceTests.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ public void TryInfer_ShouldReturnTrueAndSetDialect_WhenMediaTypeIsKnown(string m
4545

4646
Assert.That(result, Is.True);
4747
Assert.That(dialect, Is.Not.Null);
48-
Assert.That(dialect!.Delimiter, Is.EqualTo(delimiter));
48+
Assert.That(dialect, Is.TypeOf<TableDelimitedDialect>());
49+
var tdDialect = (TableDelimitedDialect)dialect;
50+
Assert.That(tdDialect.Delimiter, Is.EqualTo(delimiter));
4951
}
5052

5153
[Test]

src/Packata.ResourceReaders.Testing/Inference/ResourceInferenceServiceTests.cs

Lines changed: 49 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,9 @@ public void Enrich_ShouldSetCompression_WhenCompressionIsNull()
2020
return true;
2121
});
2222

23-
var service = new ResourceInferenceService(
24-
Array.Empty<IDialectInference>(),
25-
Array.Empty<IFormatInference>(),
26-
new[] { mockCompression.Object }
27-
);
23+
var builder = new ResourceInferenceServiceBuilder();
24+
builder.AddStrategy(mockCompression.Object);
25+
var service = builder.Build();
2826

2927
var resource = new Resource { Compression = null };
3028
service.Enrich(resource);
@@ -35,11 +33,7 @@ public void Enrich_ShouldSetCompression_WhenCompressionIsNull()
3533
[Test]
3634
public void Enrich_ShouldNotSetCompression_WhenCompressionIsAlreadySet()
3735
{
38-
var service = new ResourceInferenceService(
39-
Array.Empty<IDialectInference>(),
40-
Array.Empty<IFormatInference>(),
41-
Array.Empty<ICompressionInference>()
42-
);
36+
var service = ResourceInferenceServiceBuilder.None;
4337

4438
var resource = new Resource { Compression = "gzip" };
4539
service.Enrich(resource);
@@ -52,18 +46,16 @@ public void Enrich_ShouldSetDialect_WhenDialectIsNull()
5246
{
5347
var mockDialect = new Mock<IDialectInference>();
5448
mockDialect
55-
.Setup(m => m.TryInfer(It.IsAny<Resource>(), out It.Ref<TableDelimitedDialect?>.IsAny))
56-
.Returns((Resource resource, out TableDelimitedDialect? dialect) =>
49+
.Setup(m => m.TryInfer(It.IsAny<Resource>(), out It.Ref<TableDialect?>.IsAny))
50+
.Returns((Resource resource, out TableDialect? dialect) =>
5751
{
5852
dialect = new TableDelimitedDialect { Delimiter = ',', QuoteChar = '"', DoubleQuote = true };
5953
return true;
6054
});
6155

62-
var service = new ResourceInferenceService(
63-
new[] { mockDialect.Object },
64-
Array.Empty<IFormatInference>(),
65-
Array.Empty<ICompressionInference>()
66-
);
56+
var builder = new ResourceInferenceServiceBuilder();
57+
builder.AddStrategy(mockDialect.Object);
58+
var service = builder.Build();
6759

6860
var resource = new Resource { Dialect = null };
6961
service.Enrich(resource);
@@ -88,11 +80,9 @@ public void Enrich_ShouldSetFormat_WhenFormatIsNull()
8880
return true;
8981
});
9082

91-
var service = new ResourceInferenceService(
92-
Array.Empty<IDialectInference>(),
93-
new[] { mockFormat.Object },
94-
Array.Empty<ICompressionInference>()
95-
);
83+
var builder = new ResourceInferenceServiceBuilder();
84+
builder.AddStrategy(mockFormat.Object);
85+
var service = builder.Build();
9686

9787
var resource = new Resource { Format = null };
9888
service.Enrich(resource);
@@ -113,11 +103,9 @@ public void Enrich_ShouldNotSetFormat_WhenFormatIsNotNull()
113103
return true;
114104
});
115105

116-
var service = new ResourceInferenceService(
117-
Array.Empty<IDialectInference>(),
118-
new[] { mockFormat.Object },
119-
Array.Empty<ICompressionInference>()
120-
);
106+
var builder = new ResourceInferenceServiceBuilder();
107+
builder.AddStrategy(mockFormat.Object);
108+
var service = builder.Build();
121109

122110
var resource = new Resource { Format = "bar" };
123111
service.Enrich(resource);
@@ -128,11 +116,7 @@ public void Enrich_ShouldNotSetFormat_WhenFormatIsNotNull()
128116
[Test]
129117
public void Enrich_ShouldNotSetDialect_WhenDialectIsAlreadySet()
130118
{
131-
var service = new ResourceInferenceService(
132-
Array.Empty<IDialectInference>(),
133-
Array.Empty<IFormatInference>(),
134-
Array.Empty<ICompressionInference>()
135-
);
119+
var service = ResourceInferenceServiceBuilder.None;
136120

137121
var resource = new Resource
138122
{
@@ -147,6 +131,39 @@ public void Enrich_ShouldNotSetDialect_WhenDialectIsAlreadySet()
147131
Assert.That(dialect.QuoteChar, Is.EqualTo('"'));
148132
Assert.That(dialect.DoubleQuote, Is.True);
149133
}
134+
135+
[Test]
136+
public void Enrich_ShouldSetKind_WhenKindIsNull()
137+
{
138+
var mockKind = new Mock<IKindInference>();
139+
mockKind
140+
.Setup(m => m.TryInfer(It.IsAny<Resource>(), out It.Ref<string?>.IsAny))
141+
.Returns((Resource resource, out string value) =>
142+
{
143+
value = "mssql";
144+
return true;
145+
});
146+
147+
var builder = new ResourceInferenceServiceBuilder();
148+
builder.AddStrategy(mockKind.Object);
149+
var service = builder.Build();
150+
151+
var resource = new Resource { Kind = null };
152+
service.Enrich(resource);
153+
154+
Assert.That(resource.Kind, Is.EqualTo("mssql"));
155+
}
156+
157+
[Test]
158+
public void Enrich_ShouldNotSetKind_WhenKindIsAlreadySet()
159+
{
160+
var service = ResourceInferenceServiceBuilder.None;
161+
162+
var resource = new Resource { Kind = "service" };
163+
service.Enrich(resource);
164+
165+
Assert.That(resource.Kind, Is.EqualTo("service"));
166+
}
150167
}
151168
}
152169

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using NUnit.Framework;
7+
using Packata.Core;
8+
using Packata.ResourceReaders.Inference;
9+
using Packata.Core.Storage;
10+
using Moq;
11+
12+
namespace Packata.ResourceReaders.Testing.Inference;
13+
public class SchemeBasedKindInferenceTests
14+
{
15+
private static readonly string[] _remoteArray = ["http", "https"];
16+
private static readonly string[] _serviceArray = ["mssql", "pgsql"];
17+
18+
[Test]
19+
[TestCase("data/file.csv", "local")]
20+
[TestCase("file.csv", "local")]
21+
[TestCase("http://www.data.org/file.csv", "remote")]
22+
[TestCase("mssql://192.168.16.45/db", "service")]
23+
[TestCase(null, "virtual")]
24+
public void TryInfer_Path_Success(string? path, string expected)
25+
{
26+
bool remote(string value) => (_remoteArray).Any(x => x.Equals(value, StringComparison.OrdinalIgnoreCase));
27+
bool service(string value) => (_serviceArray).Any(x => x.Equals(value, StringComparison.OrdinalIgnoreCase));
28+
var inference = new SchemeBasedKindInference(remote, service);
29+
30+
var factory = new PathFactory(Mock.Of<IDataPackageContainer>(), Mock.Of<IStorageProvider>());
31+
var resource = path is null
32+
? new Resource()
33+
: new Resource() { Paths = [factory.Create(path)] };
34+
35+
Assert.That(inference.TryInfer(resource, out var result), Is.True);
36+
Assert.That(result, Is.EqualTo(expected));
37+
}
38+
}

src/Packata.ResourceReaders.Testing/ResourceReaderFactoryTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public void Create_ShouldEnrichDialect_WhenDialectIsNull()
6565
};
6666
});
6767

68-
var factory = new ResourceReaderFactory(ResourceInferenceService.None);
68+
var factory = new ResourceReaderFactory(ResourceInferenceServiceBuilder.None);
6969
var reader = factory.Create(resource);
7070
Assert.That(resource.Dialect, Is.Null);
7171

src/Packata.ResourceReaders/Inference/BaseCompressionInference.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Diagnostics.CodeAnalysis;
34
using System.Linq;
45
using System.Text;
56
using System.Threading.Tasks;
@@ -13,7 +14,7 @@ public abstract class BaseCompressionInference : ICompressionInference
1314
protected BaseCompressionInference(IDictionary<string, string> compressionMappings)
1415
=> CompressionMappings = compressionMappings;
1516

16-
public abstract bool TryInfer(Resource resource, out string? compression);
17+
public abstract bool TryInfer(Resource resource, [NotNullWhen(true)] out string? compression);
1718

1819
protected bool TryInferFromExtension(string? extension, out string? compression)
1920
{

0 commit comments

Comments
 (0)