Skip to content

Commit a75b702

Browse files
chore(deps): update dotnet monorepo (#606)
* chore(deps): update dotnet monorepo * Update binder for new commandline version --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Einar Omang <einar.omang@cognite.com>
1 parent 8023259 commit a75b702

File tree

8 files changed

+179
-28
lines changed

8 files changed

+179
-28
lines changed

Cognite.Common/Cognite.Common.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
<None Include="..\LICENSE" Pack="true" Visible="false" PackagePath="" />
2525
</ItemGroup>
2626
<ItemGroup>
27-
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.0" />
28-
<PackageReference Include="System.Text.Json" Version="10.0.0" />
27+
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.3" />
28+
<PackageReference Include="System.Text.Json" Version="10.0.3" />
2929
<PackageReference Include="NCrontab.Signed" Version="3.4.0" />
3030
</ItemGroup>
3131

Cognite.Config/Cognite.Configuration.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
<PackageReference Include="Azure.Identity" Version="1.17.1" />
2929
<PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.8.0" />
3030
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
31-
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
31+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.3" />
3232
<PackageReference Include="YamlDotNet" Version="16.3.0" />
3333
</ItemGroup>
3434

Cognite.Extensions/Cognite.Extensions.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@
2828
<ItemGroup>
2929
<PackageReference Include="Microsoft.Identity.Client" Version="4.79.2" />
3030
<PackageReference Include="CogniteSdk" Version="5.5.0" />
31-
<PackageReference Include="System.Text.Json" Version="10.0.0" />
31+
<PackageReference Include="System.Text.Json" Version="10.0.3" />
3232
<PackageReference Include="prometheus-net" Version="8.2.1" />
33-
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.0" />
34-
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="10.0.0" />
33+
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.3" />
34+
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="10.0.3" />
3535
<PackageReference Include="Polly.Extensions.Http" Version="3.0.0" />
36-
<PackageReference Include="FSharp.Core" Version="10.0.100" />
36+
<PackageReference Include="FSharp.Core" Version="10.0.103" />
3737
</ItemGroup>
3838
</Project>

Cognite.Logging/Cognite.Logging.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
</ItemGroup>
2626

2727
<ItemGroup>
28-
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
29-
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.0" />
28+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.3" />
29+
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.3" />
3030
<PackageReference Include="Serilog" Version="4.3.1" />
3131
<PackageReference Include="Serilog.Extensions.Logging" Version="10.0.0" />
3232
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />

Cognite.Metrics/Cognite.Metrics.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
</ItemGroup>
2626

2727
<ItemGroup>
28-
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.0" />
29-
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="10.0.0" />
28+
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.3" />
29+
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="10.0.3" />
3030
<PackageReference Include="Polly.Extensions.Http" Version="3.0.0" />
3131
<PackageReference Include="prometheus-net" Version="8.2.1" />
3232
</ItemGroup>

ExtractorUtils.Test/unit/CommandLineTest.cs

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using Cognite.Extractor.Testing;
22
using Cognite.Extractor.Utils.CommandLine;
33
using System.CommandLine;
4+
using System.Threading.Tasks;
45
using Xunit;
56
using Xunit.Abstractions;
67

@@ -17,6 +18,12 @@ internal class CliType
1718
public bool IgnoredOption { get; set; }
1819
}
1920

21+
internal class SubCommandType : CliType
22+
{
23+
[CommandLineOption("Some other flag", false, "-o")]
24+
public bool OtherFlag { get; set; }
25+
}
26+
2027

2128
public class CommandLineTest : ConsoleWrapper
2229
{
@@ -34,15 +41,72 @@ public void TestSimpleCliType()
3441
};
3542
binder.AddOptionsToCommand(command);
3643

37-
command.SetHandler<CliType>(result =>
44+
command.SetHandler(result =>
45+
{
46+
Assert.Equal("stringvalue", result.StringType);
47+
Assert.Equal(123, result.IntType);
48+
Assert.True(result.Flag);
49+
Assert.False(result.IgnoredOption);
50+
}, binder);
51+
52+
Assert.Equal(0, command.Invoke(new[] { "--string-type", "stringvalue", "-b", "-i", "123" }));
53+
}
54+
55+
[Fact]
56+
public void TestMultiCommandCli()
57+
{
58+
var binder = new AttributeBinder<CliType>();
59+
var subBinder = new AttributeBinder<SubCommandType>();
60+
61+
var command = new RootCommand()
62+
{
63+
Description = "My description"
64+
};
65+
binder.AddOptionsToCommand(command);
66+
command.SetHandler(result =>
67+
{
68+
Assert.Fail("Root command should not be invoked in this test.");
69+
}, binder);
70+
71+
var subCommand = new Command("subcommand")
72+
{
73+
Description = "Subcommand description"
74+
};
75+
subBinder.AddOptionsToCommand(subCommand);
76+
subCommand.SetHandler(result =>
77+
{
78+
Assert.Equal("stringvalue", result.StringType);
79+
Assert.Equal(123, result.IntType);
80+
Assert.True(result.Flag);
81+
Assert.False(result.IgnoredOption);
82+
Assert.True(result.OtherFlag);
83+
}, subBinder);
84+
command.Add(subCommand);
85+
86+
Assert.Equal(0, command.Invoke(new[] { "subcommand", "-o", "--string-type", "stringvalue", "-b", "-i", "123" }));
87+
}
88+
89+
[Fact]
90+
public async Task TestAsyncCli()
91+
{
92+
var binder = new AttributeBinder<CliType>();
93+
94+
var command = new RootCommand()
95+
{
96+
Description = "My description"
97+
};
98+
binder.AddOptionsToCommand(command);
99+
100+
command.SetHandler(async result =>
38101
{
102+
await Task.Delay(10);
39103
Assert.Equal("stringvalue", result.StringType);
40104
Assert.Equal(123, result.IntType);
41105
Assert.True(result.Flag);
42106
Assert.False(result.IgnoredOption);
43107
}, binder);
44108

45-
Assert.Equal(0, command.Invoke("--string-type stringvalue -b -i 123"));
109+
Assert.Equal(0, command.Invoke(new[] { "--string-type", "stringvalue", "-b", "-i", "123" }));
46110
}
47111
}
48112
}

ExtractorUtils/CommandLine/AttributeBinder.cs

Lines changed: 98 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@
44
using System.CommandLine;
55
using System.CommandLine.Binding;
66
using System.Linq;
7+
using System.Threading.Tasks;
78

89
namespace Cognite.Extractor.Utils.CommandLine
910
{
1011
/// <summary>
1112
/// Binder class for objects built with CommandLineOptionAttribute.
1213
/// </summary>
1314
/// <typeparam name="T">Type to create. Must have a parameterless constructor.</typeparam>
14-
public class AttributeBinder<T> : BinderBase<T>
15+
public class AttributeBinder<T>
1516
{
1617
/// <summary>
1718
/// Built options, options here can be modified.
@@ -35,11 +36,11 @@ public AttributeBinder()
3536
/// <param name="command">Command to add to</param>
3637
public void AddOptionsToCommand(Command command)
3738
{
38-
if (command == null) throw new ArgumentNullException(nameof(Command));
39+
if (command == null) throw new ArgumentNullException(nameof(command));
3940

4041
foreach (var kvp in Options)
4142
{
42-
command.AddOption(kvp.Value);
43+
command.Add(kvp.Value);
4344
}
4445
}
4546

@@ -64,7 +65,8 @@ private void BuildCommandOptions()
6465
}
6566
Option option;
6667
var optType = typeof(Option<>).MakeGenericType(prop.PropertyType);
67-
option = (Option)Activator.CreateInstance(optType, aliases.ToArray(), attr.Description)!;
68+
option = (Option)Activator.CreateInstance(optType, aliases.ToArray())!;
69+
option.Description = attr.Description;
6870

6971
Options[prop.Name] = option;
7072
}
@@ -74,26 +76,111 @@ private void BuildCommandOptions()
7476
/// Create an instance of <typeparamref name="T"/>, and bind to it using options constructed from
7577
/// CommandLineOptionAttributes.
7678
/// </summary>
77-
/// <param name="bindingContext">Context</param>
79+
/// <param name="result">Parse result</param>
7880
/// <returns>An instance of <typeparamref name="T"/> with fields filled from command line.</returns>
79-
protected override T GetBoundValue(BindingContext bindingContext)
81+
public T GetBoundValue(ParseResult result)
8082
{
81-
if (bindingContext == null) throw new ArgumentNullException(nameof(bindingContext));
83+
if (result == null) throw new ArgumentNullException(nameof(result));
8284

8385
var type = typeof(T);
84-
var result = Activator.CreateInstance(type);
86+
var instance = Activator.CreateInstance(type);
8587
var props = type.GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
8688

8789
foreach (var prop in props)
8890
{
8991
if (!prop.CanWrite) continue;
9092
if (!Options.TryGetValue(prop.Name, out var option)) continue;
9193

92-
var res = bindingContext.ParseResult.GetValueForOption(option);
93-
prop.SetValue(result, res);
94+
var getter = typeof(ParseResult).GetMethods().First(m =>
95+
m.Name == nameof(ParseResult.GetValue)
96+
&& m.IsGenericMethod
97+
&& m.GetParameters()[0].ParameterType.IsGenericType
98+
&& m.GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(Option<>)
99+
).MakeGenericMethod(prop.PropertyType);
100+
prop.SetValue(instance, getter.Invoke(result, new object[] { option }));
94101
}
95102

96-
return (T)result!;
103+
return (T)instance!;
97104
}
98105
}
106+
107+
/// <summary>
108+
/// Extensions for Command, to make our command line interface backwards compatible.
109+
/// </summary>
110+
public static class CommandExtensions
111+
{
112+
/// <summary>
113+
/// Set a typed handler for the command.
114+
/// </summary>
115+
/// <typeparam name="T">The type of the bound value.</typeparam>
116+
/// <param name="command">Command to set the handler for.</param>
117+
/// <param name="action">The action to execute when the command is invoked.</param>
118+
/// <param name="binder">The attribute binder to use for binding command line options.</param>
119+
/// <exception cref="ArgumentNullException"></exception>
120+
public static void SetHandler<T>(this Command command, Action<T> action, AttributeBinder<T> binder)
121+
{
122+
if (command == null) throw new ArgumentNullException(nameof(command));
123+
if (action == null) throw new ArgumentNullException(nameof(action));
124+
if (binder == null) throw new ArgumentNullException(nameof(binder));
125+
126+
command.SetAction(result =>
127+
{
128+
var boundValue = binder.GetBoundValue(result);
129+
action(boundValue);
130+
});
131+
}
132+
133+
/// <summary>
134+
/// Set a typed async handler for the command.
135+
/// </summary>
136+
/// <typeparam name="T">The type of the bound value.</typeparam>
137+
/// <param name="command">Command to set the handler for.</param>
138+
/// <param name="action">The action to execute when the command is invoked.</param>
139+
/// <param name="binder">The attribute binder to use for binding command line options.</param>
140+
/// <exception cref="ArgumentNullException"></exception>
141+
public static void SetHandler<T>(this Command command, Func<T, Task> action, AttributeBinder<T> binder)
142+
{
143+
if (command == null) throw new ArgumentNullException(nameof(command));
144+
if (action == null) throw new ArgumentNullException(nameof(action));
145+
if (binder == null) throw new ArgumentNullException(nameof(binder));
146+
147+
command.SetAction(async result =>
148+
{
149+
var boundValue = binder.GetBoundValue(result);
150+
await action(boundValue).ConfigureAwait(false);
151+
});
152+
}
153+
154+
155+
/// <summary>
156+
/// Invoke the command.
157+
/// </summary>
158+
/// <param name="command">Command to invoke.</param>
159+
/// <param name="args">Raw command line arguments</param>
160+
/// <returns>The command's exit code.</returns>
161+
/// <exception cref="ArgumentNullException"></exception>
162+
public static int Invoke(this Command command, string[] args)
163+
{
164+
if (command == null) throw new ArgumentNullException(nameof(command));
165+
if (args == null) throw new ArgumentNullException(nameof(args));
166+
167+
return command.Parse(args).Invoke();
168+
}
169+
170+
/// <summary>
171+
/// Invoke the command asynchronously.
172+
/// </summary>
173+
/// <param name="command">Command to invoke.</param>
174+
/// <param name="args">Raw command line arguments</param>
175+
/// <returns>A task representing the asynchronous operation, with the command's exit code as the result.</returns>
176+
/// <exception cref="ArgumentNullException"></exception>
177+
public static async Task<int> InvokeAsync(this Command command, string[] args)
178+
{
179+
if (command == null) throw new ArgumentNullException(nameof(command));
180+
if (args == null) throw new ArgumentNullException(nameof(args));
181+
182+
return await command.Parse(args).InvokeAsync().ConfigureAwait(false);
183+
}
184+
185+
}
99186
}

ExtractorUtils/ExtractorUtils.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@
2323
<None Include="..\LICENSE" Pack="true" Visible="false" PackagePath="" />
2424
</ItemGroup>
2525
<ItemGroup>
26-
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.0" />
27-
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
28-
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.0" />
26+
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.3" />
27+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.3" />
28+
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.3" />
2929
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
3030
<PackageReference Include="StackExchange.Redis" Version="2.11.0" />
31-
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
31+
<PackageReference Include="System.CommandLine" Version="2.0.3" />
3232
</ItemGroup>
3333
<ItemGroup>
3434
<ProjectReference Include="..\Cognite.Config\Cognite.Configuration.csproj" />

0 commit comments

Comments
 (0)