This repository was archived by the owner on Jan 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 55
Expand file tree
/
Copy pathProgram.cs
More file actions
219 lines (203 loc) · 9.85 KB
/
Program.cs
File metadata and controls
219 lines (203 loc) · 9.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#nullable enable
using McMaster.Extensions.CommandLineUtils;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Jupyter.Core;
using Microsoft.Quantum.IQSharp.Kernel;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.Quantum.IQSharp
{
/// <summary>
/// The iqsharp program.
/// On top of the default commands for a Jupyter Kernel, this program also
/// exposes a "server" command that starts this Kernel in HTTP mode,
/// so the operations can be accessed and simulated using REST methods.
/// </summary>
public class Program
{
public static IConfiguration? Configuration;
public class LoggingOptions
{
public string? LogPath { get; set; }
public LogLevel? FileLogLevel { get; set; }
}
public static bool TelemetryOptOut
#if TELEMETRY
=> !string.IsNullOrEmpty(Configuration?[nameof(TelemetryOptOut)]);
#else
=> true;
#endif
/// <summary>
/// Creates dictionary of kernelspec file names to the embedded resource path
/// of all embedded resources found in <c>Kernel.csproj</c>.
/// Note: <c>WithKernelSpecResources</c> cannot handle keys that include directories
/// so we treat all path names as period-separated file names.
/// </summary>
private static Dictionary<string, string> GetEmbeddedKernelResources() =>
AppDomain.CurrentDomain.GetAssemblies()
.Single(asm => asm.GetName().Name == "Microsoft.Quantum.IQSharp.Kernel")
.GetManifestResourceNames()
// Take file name as substring after "Microsoft.Quantum.IQSharp.Kernel.res"
.ToDictionary(resName => string.Join(".", resName.Split(".").Skip(5)));
public static int Main(string[] args)
{
try
{
Configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddCommandLine(
args,
// We provide explicit aliases for those command line
// options that specify client information, matching
// the placeholder options that we define below.
new Dictionary<string, string>()
{
["--user-agent"] = "UserAgent",
["--user-agent-extra"] = "UserAgentExtra",
["--hosting-env"] = "HostingEnvironment"
}
)
.Add(new NormalizedEnvironmentVariableConfigurationSource
{
Prefix = "IQSHARP_",
Aliases = new Dictionary<string, string>
{
// Package and project load settings
["AUTO_LOAD_PACKAGES"] = "AutoLoadPackages",
["AUTO_OPEN_NAMESPACES"] = "AutoOpenNamespaces",
["SKIP_AUTO_LOAD_PROJECT"] = "SkipAutoLoadProject",
["FORCE_TARGETING_HEURISTICS"] = "ForceTargetingHeuristics",
// Telemetry and metadata settings
["TELEMETRY_OPT_OUT"] = nameof(TelemetryOptOut),
["HOSTING_ENV"] = "HostingEnvironment",
["USER_AGENT"] = "UserAgent",
["USER_AGENT_EXTRA"] = "UserAgentExtra",
// Logging settings
["LOG_PATH"] = "LogPath",
["FILE_LOG_LEVEL"] = "FileLogLevel",
["BINLOG_PATH"] = "MSBuildBinlogPath",
["SESSION_RECORD_PATH"] = "SessionRecordPath",
}
})
.Build();
var app = new IQSharpKernelApp(
Kernel.Constants.IQSharpKernelProperties, new Startup(Configuration).ConfigureServices
)
.ConfigureLogging(
loggingBuilder => {
// As per https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1#access-configuration-during-startup,
// we need to use an IConfiguration instance directly during
// startup, rather than using the nice binding methods
// like serviceCollection.Configure<TOptions>(configuration).
var options = Configuration.Get<LoggingOptions>();
if (options?.LogPath != null && options.LogPath.Length != 0)
{
loggingBuilder.AddFile(
options.LogPath,
minimumLevel: options.FileLogLevel ?? LogLevel.Debug
);
}
}
)
.WithKernelSpecResources<Kernel.IQSharpEngine>(GetEmbeddedKernelResources());
app.Command(
"server",
cmd =>
{
cmd.HelpOption();
cmd.Description = $"Runs IQSharp as an HTTP server.";
cmd.OnExecute(() =>
{
GetHttpServer(args).Run();
return 0;
});
}
);
CommandOption? userAgentOption = null;
AddWorkspaceOption(
app
.AddInstallCommand(installCmd =>
{
userAgentOption = installCmd.Option(
"--user-agent-extra <AGENT>",
"Sets additional user agent information to be sent to the kernel.",
CommandOptionType.SingleValue
);
})
.WithKernelArguments(() =>
// We know that the closure above is called by the time
// we get to this point, such that userAgentOption is
// not null at this point.
userAgentOption!.HasValue()
? new [] {"--user-agent-extra", userAgentOption!.Value()}
: Array.Empty<string>()
)
.AddKernelCommand(
// These command options will be consumed by the Program.Configuration
// object above, rather than by the kernel application object itself.
// Thus, we only need placeholders to prevent the kernel application
// from raising an exception when unrecognized options are passed.
kernelCmd => {
kernelCmd.Option<string>(
"--user-agent-extra <AGENT>",
"Sets additional user agent information to be sent to the kernel.",
CommandOptionType.SingleValue
);
kernelCmd.Option<string>(
"--user-agent <AGENT>",
"Specifies which user agent has initiated this kernel instance.",
CommandOptionType.SingleValue
);
kernelCmd.Option<string>(
"--hosting-env <ENV>",
"Specifies the hosting environment that this kernel is being run in.",
CommandOptionType.SingleValue
);
}
)
);
return app.Execute(args);
}
catch (CommandParsingException)
{
return 1;
}
}
public static IWebHost GetHttpServer(string[]? args)
{
var builder = WebHost.CreateDefaultBuilder(args ?? Array.Empty<string>())
.UseUrls("http://localhost:8008")
.UseStartup<Startup>();
if (Configuration is not null)
{
builder.UseConfiguration(Configuration);
}
return builder.Build();
}
// Adds the Workspace settings to the "server" and "kernel" commands:
public static KernelApplication AddWorkspaceOption(KernelApplication app)
{
var cacheOption = app.Option("--cacheFolder <FOLDER>",
"Specifies the folder to use to create temporary cache files.", CommandOptionType.SingleValue);
var workspaceOption = app.Option("-w|--workspace <FOLDER>",
"Specifies the workspace root folder. " +
"All .qs files inside this folder will be automatically compiled and the corresponding " +
"operations available for simulation.", CommandOptionType.SingleValue);
var skipAutoLoadProjectOption = app.Option("--skipAutoLoadProject",
"Specifies whether to skip automatically loading the .csproj from the workspace's root folder.", CommandOptionType.SingleValue);
foreach (var command in app.Commands.Where(c => c.Name == "kernel" || c.Name == "server"))
{
command.Options.Add(cacheOption);
command.Options.Add(workspaceOption);
command.Options.Add(skipAutoLoadProjectOption);
}
return app;
}
}
}