예제 #1
0
        public int InstallKernelSpec(bool develop,
                                     LogLevel logLevel,
                                     string?prefix = null, IEnumerable <string>?extraInstallArgs = null,
                                     IDictionary <string, Func <Stream> >?additionalFiles = null,
                                     IEnumerable <string>?additionalKernelArguments       = null,
                                     string?pathToTool = null)
        {
            var        kernelSpecDir = "";
            KernelSpec kernelSpec;

            if (develop)
            {
                if (pathToTool != null)
                {
                    throw new InvalidDataException("Cannot use development mode together with custom tool paths.");
                }

                System.Console.WriteLine(
                    $"NOTE: Installing a kernel spec which references this directory.\n" +
                    $"      Any changes made in this directory will affect the operation of the {properties.FriendlyName} kernel.\n" +
                    $"      If this was not what you intended, run 'install' without the '--develop' option."
                    );

                // Serialize a new kernel spec that points to this directory.
                kernelSpec = new KernelSpec
                {
                    DisplayName  = properties.FriendlyName,
                    LanguageName = properties.LanguageName,
                    Arguments    = new List <string> {
                        "dotnet", "run",
                        "--project", Directory.GetCurrentDirectory(),
                        "--", "kernel",
                        "--log-level", logLevel.ToString(),
                        "{connection_file}"
                    }
                };
            }
            else
            {
                var kernelArgs = new List <string>();
                if (pathToTool != null)
                {
                    kernelArgs.Add(pathToTool);
                }
                else
                {
                    if (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "dotnet")
                    {
                        kernelArgs.AddRange(new[] { "dotnet", properties.KernelName });
                    }
                    else
                    {
                        kernelArgs.Add(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
                    }
                }

                kernelArgs.AddRange(
                    new[]
                {
                    "kernel",
                    "--log-level", logLevel.ToString(),
                    "{connection_file}"
                }
                    );

                kernelSpec = new KernelSpec
                {
                    DisplayName  = properties.FriendlyName,
                    LanguageName = properties.LanguageName,
                    Arguments    = kernelArgs
                };
            }

            // Add any additional arguments to the kernel spec as needed.
            if (additionalKernelArguments != null)
            {
                kernelSpec.Arguments.AddRange(additionalKernelArguments);
            }

            // Make a temporary directory to hold the kernel spec.
            var tempKernelSpecDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
            var jsonPath          = Path.Combine(tempKernelSpecDir, "kernel.json");

            Directory.CreateDirectory(tempKernelSpecDir);
            File.WriteAllText(jsonPath, JsonConvert.SerializeObject(kernelSpec));
            kernelSpecDir = tempKernelSpecDir;

            // Add any additional files we may need.
            if (additionalFiles != null)
            {
                foreach (var(fileName, streamAction) in additionalFiles)
                {
                    var dest         = Path.Combine(tempKernelSpecDir, fileName);
                    var sourceStream = streamAction();
                    // Create nested directory
                    Directory.CreateDirectory(Path.GetDirectoryName(dest));
                    using (var destStream = File.OpenWrite(dest))
                    {
                        sourceStream.CopyTo(destStream);
                    }
                }
            }

            // Find out if we need any extra arguments.
            var extraArgs = extraInstallArgs?.ToList() ?? new List <string>();

            if (!String.IsNullOrWhiteSpace(prefix))
            {
                extraArgs.Add($"--prefix=\"{prefix}\"");
            }

            Process?process = null;

            try
            {
                process = Process.Start(new ProcessStartInfo
                {
                    FileName  = "jupyter",
                    Arguments = $"kernelspec install \"{kernelSpecDir}\" --name=\"{properties.KernelName}\" {String.Join(" ", extraArgs)}"
                });
            }
            catch (Win32Exception ex)
            {
                System.Console.ForegroundColor = ConsoleColor.Red;
                if (ex.NativeErrorCode == 2)
                {
                    System.Console.Error.WriteLine(
                        "[ERROR] " +
                        $"Could not install {properties.KernelName} into your Jupyter configuration, " +
                        "as `jupyter` was not found on your PATH. " +
                        "Please make sure that Jupyter is installed and is on your PATH. " +
                        "If you are using conda or venv, please " +
                        "make sure that you have the correct environment activated.\n"
                        );
                }
                else
                {
                    System.Console.Error.WriteLine(
                        "[ERROR] " +
                        $"An exception occurred while trying to call `jupyter` to install {properties.KernelName} " +
                        "into your Jupyter configuration.\n"
                        );
                }
                System.Console.ResetColor();
                System.Console.Error.WriteLine(
                    "Full exception details:\n" + ex.ToString()
                    );
            }
            catch (Exception ex)
            {
                System.Console.WriteLine(ex);
                return(-2);
            }

            process?.WaitForExit();

            // Recursively delete all files and subdirectories in temp directory.
            Directory.Delete(tempKernelSpecDir, true);
            return(process?.ExitCode ?? -1);
        }
예제 #2
0
        /// <summary>
        ///      Installs this kernel into Jupyter's list of available kernels.
        /// </summary>
        /// <param name="develop">
        ///      If <c>true</c>, this kernel will be installed in develop mode,
        ///      such that the kernel is rebuilt whenever a new instance is
        ///      started.
        /// </param>
        /// <param name="logLevel">
        ///      The default logging level to be used when starting new kernel
        ///      instances.
        /// </param>
        /// <param name="prefix">
        ///      A path to be provided to <c>jupyter kernelspec install</c>
        ///      as the prefix into which the kernel should be installed.
        ///      Typically, this parameter is used when installing into an environment.
        ///      If <c>null</c>, no prefix is passed to Jupyter.
        /// </param>
        /// <param name="user">
        ///      If <c>true</c>, the kernel will be installed for the current
        ///      user only.
        /// </param>
        /// <param name="additionalFiles">
        ///      Specifies additional files which should be included in the kernelspec
        ///      directory. Files are specified as a dictionary from file names
        ///      to functions yielding streams that read the contents of each
        ///      file.
        /// </param>
        /// <param name="pathToTool">
        ///      If present, the value of this parameter will be used in the
        ///      kernelspec as an explicit path to the kernel being invoked,
        ///      as opposed to using the dotnet command-line program to find
        ///      the appropriate kernel.
        ///      This is not needed in most circumstances, but can be helpful
        ///      when working with CI environments that do not add .NET Global
        ///      Tools to the PATH environment variable.
        /// </param>
        /// <remarks>
        ///      This method dynamically generates a new <c>kernelspec.json</c>
        ///      file representing the kernel properties provided when the
        ///      application was constructed, along with options such as the
        ///      development mode.
        /// </remarks>
        public int InstallKernelSpec(bool develop,
                                     LogLevel logLevel,
                                     string prefix = null, bool user = false,
                                     IDictionary <string, Func <Stream> > additionalFiles = null,
                                     IEnumerable <string> additionalKernelArguments       = null,
                                     string pathToTool = null)
        {
            var        kernelSpecDir = "";
            KernelSpec kernelSpec;

            if (develop)
            {
                if (pathToTool != null)
                {
                    throw new InvalidDataException("Cannot use development mode together with custom tool paths.");
                }
                System.Console.WriteLine(
                    "NOTE: Installing a kernel spec which references this directory.\n" +
                    $"      Any changes made in this directory will affect the operation of the {properties.FriendlyName} kernel.\n" +
                    "      If this was not what you intended, run 'dotnet " +
                    $"{properties.KernelName} install' without the '--develop' option."
                    );

                // Serialize a new kernel spec that points to this directory.
                kernelSpec = new KernelSpec
                {
                    DisplayName  = properties.KernelName,
                    LanguageName = properties.LanguageName,
                    Arguments    = new List <string> {
                        "dotnet", "run",
                        "--project", Directory.GetCurrentDirectory(),
                        "--", "kernel",
                        "--log-level", logLevel.ToString(),
                        "{connection_file}"
                    }
                };
            }
            else
            {
                var kernelArgs = new List <string>();
                if (pathToTool != null)
                {
                    kernelArgs.Add(pathToTool);
                }
                else
                {
                    kernelArgs.AddRange(new[] { "dotnet", properties.KernelName });
                }

                kernelArgs.AddRange(
                    new[]
                {
                    "kernel",
                    "--log-level", logLevel.ToString(),
                    "{connection_file}"
                }
                    );

                kernelSpec = new KernelSpec
                {
                    DisplayName  = properties.DisplayName,
                    LanguageName = properties.LanguageName,
                    Arguments    = kernelArgs
                };
            }

            // Add any additional arguments to the kernel spec as needed.
            if (additionalKernelArguments != null)
            {
                kernelSpec.Arguments.AddRange(additionalKernelArguments);
            }

            // Make a temporary directory to hold the kernel spec.
            var tempKernelSpecDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
            var filesToDelete     = new List <string>();
            var jsonPath          = Path.Combine(tempKernelSpecDir, "kernel.json");

            Directory.CreateDirectory(tempKernelSpecDir);
            File.WriteAllText(jsonPath, JsonConvert.SerializeObject(kernelSpec));
            filesToDelete.Add(jsonPath);
            kernelSpecDir = tempKernelSpecDir;

            // Add any additional files we may need.
            if (additionalFiles != null)
            {
                foreach (var(fileName, streamAction) in additionalFiles)
                {
                    var dest         = Path.Combine(tempKernelSpecDir, fileName);
                    var sourceStream = streamAction();
                    using (var destStream = File.OpenWrite(dest))
                    {
                        sourceStream.CopyTo(destStream);
                    }
                    filesToDelete.Add(dest);
                }
            }

            // Find out if we need any extra arguments.
            var extraArgs = new List <string>();

            if (!String.IsNullOrWhiteSpace(prefix))
            {
                extraArgs.Add($"--prefix=\"{prefix}\"");
            }
            if (user)
            {
                extraArgs.Add("--user");
            }

            var process = Process.Start(new ProcessStartInfo
            {
                FileName  = "jupyter",
                Arguments = $"kernelspec install {kernelSpecDir} --name=\"{properties.KernelName}\" {String.Join(" ", extraArgs)}"
            });

            process.WaitForExit();
            foreach (var fileName in filesToDelete)
            {
                try
                {
                    File.Delete(fileName);
                }
                catch {}
            }
            Directory.Delete(tempKernelSpecDir);
            return(process.ExitCode);
        }