-
Notifications
You must be signed in to change notification settings - Fork 65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cli parser fixups #116
Merged
Merged
Cli parser fixups #116
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
54b7cd5
tweaks to default debugger setup - don't require optimizer
bpkroth c289504
tweak a notebook link to use the github pages rendered link
bpkroth 4d93c8c
Revert "tweak a notebook link to use the github pages rendered link"
bpkroth 01f497d
look for extra args and output more useful help text
bpkroth cfefca2
a few more usage help tweaks
bpkroth 4c980b4
reformat the strings in the code, and make it work for non "Errors" a…
bpkroth 82aea30
addressing comments
bpkroth 2ec178a
add a simple test target to check for proper parsing of bad arguments
bpkroth 57a0914
Revert "add a simple test target to check for proper parsing of bad a…
bpkroth File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
// ----------------------------------------------------------------------- | ||
// <copyright file="CliOptionsParser.cs" company="Microsoft Corporation"> | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. See LICENSE in the project root | ||
// for license information. | ||
// </copyright> | ||
// ----------------------------------------------------------------------- | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
|
||
using CommandLine; | ||
using CommandLine.Text; | ||
|
||
namespace Mlos.Agent.Server | ||
{ | ||
/// <summary> | ||
/// A helper class for parsing the command line arguments fed to <see cref="MlosAgentServer.Main" /> and displaying help usage | ||
/// output if necessary. | ||
/// </summary> | ||
public static class CliOptionsParser | ||
{ | ||
/// <summary> | ||
/// Parses the command line arguments fed to <see cref="MlosAgentServer.Main" />. | ||
/// Displays help output and forces a program exit upon errors. | ||
/// </summary> | ||
/// <param name="args">The input arguments to parse.</param> | ||
/// <param name="executablePath">The path to the executable found in the cli args.</param> | ||
/// <param name="optimizerUri">The optimizer uri found in the cli args.</param> | ||
public static void ParseArgs(string[] args, out string executablePath, out Uri optimizerUri) | ||
{ | ||
string executableFilePath = null; | ||
Uri optimizerAddressUri = null; | ||
|
||
IEnumerable<string> extraArgs = null; | ||
|
||
var cliOptsParser = new Parser(with => with.HelpWriter = null); | ||
var cliOptsParseResult = cliOptsParser.ParseArguments<CliOptions>(args) | ||
.WithParsed(parsedOptions => | ||
{ | ||
executableFilePath = parsedOptions.Executable; | ||
optimizerAddressUri = parsedOptions.OptimizerUri; | ||
extraArgs = parsedOptions.ExtraArgs; | ||
}); | ||
if (cliOptsParseResult.Tag == ParserResultType.NotParsed) | ||
{ | ||
cliOptsParseResult.WithNotParsed(errs => ShowUsageHelp( | ||
cliOptsParseResult, | ||
errors: errs, | ||
msg: "Failed to parse command line options.")); | ||
} | ||
else if (extraArgs != null && extraArgs.Any()) | ||
{ | ||
ShowUsageHelp(cliOptsParseResult, msg: "ERROR: Unknown arguments: " + string.Join(" ", extraArgs)); | ||
} | ||
|
||
cliOptsParser.Dispose(); | ||
|
||
// Populate the output variables | ||
// | ||
executablePath = executableFilePath; | ||
optimizerUri = optimizerAddressUri; | ||
} | ||
|
||
/// <summary> | ||
/// Displays the help usage, possibly with some error messages, and then exits (non-zero). | ||
/// </summary> | ||
/// <param name="parserResult">The results from a CommandLine.Parser.ParseArguments() operation.</param> | ||
/// <param name="errors">An errors reported by the parserResult.</param> | ||
/// <param name="msg">An optional error message to accompany the output.</param> | ||
private static void ShowUsageHelp<T>(ParserResult<T> parserResult, IEnumerable<Error> errors = null, string msg = null) | ||
{ | ||
if (msg != null) | ||
{ | ||
Console.Error.WriteLine(msg); | ||
Console.Error.WriteLine(); | ||
} | ||
|
||
if (errors == null) | ||
{ | ||
errors = new List<Error>(); | ||
} | ||
|
||
HelpText helpText = null; | ||
if (errors.IsVersion()) | ||
{ | ||
helpText = HelpText.AutoBuild(parserResult); | ||
} | ||
else | ||
{ | ||
helpText = HelpText.AutoBuild( | ||
parserResult, | ||
onError: ht => | ||
{ | ||
return HelpText.DefaultParsingErrorsHandler(parserResult, ht); | ||
}, | ||
e => e); | ||
helpText.AddNewLineBetweenHelpSections = true; | ||
helpText.AddPreOptionsLines(new[] | ||
{ | ||
string.Empty, | ||
|
||
// Use a single long line of text to let the help output get wrapped automatically for us. | ||
"The Mlos.Agent.Server acts as an external agent for MLOS integrated components, allowing them to " | ||
+ "send it messages over shared memory, which it can process and use to interface with an optimizer " | ||
+ "service to tune the components over their shared memory communication channels.", | ||
string.Empty, | ||
|
||
// Indent the actual commands to make them stand out a bit more. | ||
// Note: The help out preserves the indent across wrapping. | ||
"usage mode 1: Wait for an application to register over global shared memory, without an optimizer.", | ||
" dotnet Mlos.Agent.Server.dll", | ||
string.Empty, | ||
|
||
"usage mode 2: Wait for an application to register over global shared memory, and prepare to " | ||
+ "communicate with an MLOS optimizer listening at the given Grpc URI.", | ||
" dotnet Mlos.Agent.Server.dll --optimizer-uri http://localhost:50051", | ||
string.Empty, | ||
|
||
"usage mode 3: Start an executable to communicate over freshly prepared global shared memory.", | ||
" dotnet Mlos.Agent.Server.dll --executable path/to/executable", | ||
string.Empty, | ||
|
||
"usage mode 4: Start an executable to communicate over freshly prepared global shared memory and " | ||
+ "prepare to communicate with an MLOS optimizer listening at the given Grpc URI.", | ||
" dotnet Mlos.Agent.Server.dll --executable path/to/executable --optimizer-uri http://localhost:50051", | ||
string.Empty, | ||
|
||
"Note: the optimizer service used in these examples can be started using the 'start_optimizer_microservice " | ||
+ "launch --port 50051' command from the mlos Python module.", | ||
}); | ||
} | ||
|
||
Console.WriteLine(helpText); | ||
Environment.Exit(1); | ||
} | ||
|
||
/// <summary> | ||
/// The command line options for this application. | ||
/// </summary> | ||
private class CliOptions | ||
{ | ||
[Option("executable", Required = false, Default = null, HelpText = "A path to an executable to start (e.g. 'target/bin/Release/SmartCache').")] | ||
public string Executable { get; set; } | ||
|
||
[Option("optimizer-uri", Required = false, Default = null, HelpText = "A URI to connect to the MLOS Optimizer service over GRPC (e.g. 'http://localhost:50051').")] | ||
public Uri OptimizerUri { get; set; } | ||
|
||
/// <remarks> | ||
/// Just used to detect any extra arguments so we can throw a warning. | ||
/// See Also: https://github.com/microsoft/MLOS/issues/112. | ||
/// </remarks> | ||
[CommandLine.Value(0)] | ||
public IEnumerable<string> ExtraArgs { get; set; } | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixup for the default debugger experience.
If this options are enabled by default, the command will fail.
In the future we can consider to add a
preLaunchTask
that starts the optimizer service.