-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2126 from posit-dev/mm-r-in-positron
- Loading branch information
Showing
25 changed files
with
280 additions
and
92 deletions.
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
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,74 @@ | ||
// Copyright (C) 2024 by Posit Software, PBC. | ||
|
||
// This is the portion of the Positron API definition | ||
// used by Publisher, here until it is published. | ||
|
||
declare module "positron" { | ||
export interface PositronApi { | ||
version: string; | ||
runtime: runtime; | ||
} | ||
|
||
/** | ||
* LanguageRuntimeMetadata contains information about a language runtime that is known | ||
* before the runtime is started. | ||
*/ | ||
export interface LanguageRuntimeMetadata { | ||
/** The path to the runtime. */ | ||
runtimePath: string; | ||
|
||
/** A unique identifier for this runtime; takes the form of a GUID */ | ||
runtimeId: string; | ||
|
||
/** | ||
* The fully qualified name of the runtime displayed to the user; e.g. "R 4.2 (64-bit)". | ||
* Should be unique across languages. | ||
*/ | ||
runtimeName: string; | ||
|
||
/** | ||
* A language specific runtime name displayed to the user; e.g. "4.2 (64-bit)". | ||
* Should be unique within a single language. | ||
*/ | ||
runtimeShortName: string; | ||
|
||
/** The version of the runtime itself (e.g. kernel or extension version) as a string; e.g. "0.1" */ | ||
runtimeVersion: string; | ||
|
||
/** The runtime's source or origin; e.g. PyEnv, System, Homebrew, Conda, etc. */ | ||
runtimeSource: string; | ||
|
||
/** The free-form, user-friendly name of the language this runtime can execute; e.g. "R" */ | ||
languageName: string; | ||
|
||
/** | ||
* The Visual Studio Code Language ID of the language this runtime can execute; e.g. "r" | ||
* | ||
* See here for a list of known language IDs: | ||
* https://code.visualstudio.com/docs/languages/identifiers#_known-language-identifiers | ||
*/ | ||
languageId: string; | ||
|
||
/** The version of the language; e.g. "4.2" */ | ||
languageVersion: string; | ||
|
||
/** The Base64-encoded icon SVG for the language. */ | ||
base64EncodedIconSvg: string | undefined; | ||
|
||
/** Whether the runtime should start up automatically or wait until explicitly requested */ | ||
// startupBehavior: LanguageRuntimeStartupBehavior; | ||
|
||
/** Where sessions will be located; used as a hint to control session restoration */ | ||
// sessionLocation: LanguageRuntimeSessionLocation; | ||
|
||
/** | ||
* Extra data supplied by the runtime provider; not read by Positron but supplied | ||
* when creating a new session from the metadata. | ||
*/ | ||
extraRuntimeData: any; | ||
} | ||
|
||
export interface runtime { | ||
getPreferredRuntime(languageId: string): Thenable<LanguageRuntimeMetadata>; | ||
} | ||
} |
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
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
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
This file was deleted.
Oops, something went wrong.
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,109 @@ | ||
// Copyright (C) 2024 by Posit Software, PBC. | ||
|
||
import { Uri, commands, workspace } from "vscode"; | ||
import { fileExists, isDir } from "./files"; | ||
import { delay } from "./throttle"; | ||
import { substituteVariables } from "./variables"; | ||
import { LanguageRuntimeMetadata, PositronApi } from "positron"; | ||
|
||
export async function getPythonInterpreterPath(): Promise<string | undefined> { | ||
const workspaceFolder = workspace.workspaceFolders?.[0]; | ||
if (workspaceFolder === undefined) { | ||
return undefined; | ||
} | ||
let configuredPython: string | undefined; | ||
try { | ||
configuredPython = await commands.executeCommand<string>( | ||
"python.interpreterPath", | ||
{ workspaceFolder: workspaceFolder }, | ||
); | ||
} catch (error: unknown) { | ||
console.error( | ||
"getPythonInterpreterPath was unable to execute command. Error = ", | ||
error, | ||
); | ||
} | ||
if (configuredPython === undefined) { | ||
return undefined; | ||
} | ||
let python = substituteVariables(configuredPython, true); | ||
const pythonUri = Uri.file(python); | ||
|
||
if (await isDir(pythonUri)) { | ||
// Configured python can be a directory such as a virtual environment. | ||
const names = [ | ||
"bin/python", | ||
"bin/python3", | ||
"Scripts/python.exe", | ||
"Scripts/python3.exe", | ||
]; | ||
for (const name of names) { | ||
const candidate = Uri.joinPath(pythonUri, name); | ||
if (await fileExists(candidate)) { | ||
python = candidate.fsPath; | ||
} | ||
} | ||
} | ||
console.log("Python interpreter path:", python); | ||
return python; | ||
} | ||
|
||
declare global { | ||
function acquirePositronApi(): PositronApi; | ||
} | ||
|
||
let positronApi: PositronApi | null | undefined; | ||
|
||
function getPositronApi(): PositronApi | null { | ||
if (positronApi === undefined) { | ||
try { | ||
positronApi = acquirePositronApi(); | ||
} catch { | ||
positronApi = null; | ||
} | ||
} | ||
return positronApi; | ||
} | ||
|
||
export async function getRInterpreterPath(): Promise<string | undefined> { | ||
const api = getPositronApi(); | ||
|
||
if (api) { | ||
let runtime: LanguageRuntimeMetadata | undefined; | ||
|
||
// Small number of retries, because getPreferredRuntime | ||
// has its own internal retry logic. | ||
const retries = 3; | ||
const retryInterval = 1000; | ||
|
||
for (let i = 0; i < retries + 1; i++) { | ||
try { | ||
runtime = await api.runtime.getPreferredRuntime("r"); | ||
break; | ||
} catch (error: unknown) { | ||
// Delay and retry | ||
console.error( | ||
"getPreferredRuntime returned an error; retrying. ", | ||
error, | ||
); | ||
await delay(retryInterval); | ||
} | ||
} | ||
|
||
if (runtime) { | ||
const interpreter = runtime.runtimePath; | ||
console.log("Using selected R interpreter", interpreter); | ||
return interpreter; | ||
} else { | ||
console.log( | ||
"Using default R interpreter because getPreferredRuntime did not return one", | ||
); | ||
} | ||
} | ||
// We don't know the interpreter path. | ||
// The backend will run R from PATH. | ||
console.log( | ||
"Using default R interpreter because the Positron API is not available", | ||
); | ||
return undefined; | ||
} |
Oops, something went wrong.