-
Notifications
You must be signed in to change notification settings - Fork 91
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
Track reasons for R discovery and rejection and do stuff with them #5648
Conversation
893aa40
to
c8ed35e
Compare
} | ||
// Find the current R binary(ies) for various definitions of "current". | ||
// The first item here will eventually be marked as The Current R Binary. | ||
const currentBinaries = await currentRBinaryCandidates(); |
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.
There are (at least) 3 possible ways to define the current version of R. currentRBinaryCandidates()
returns them all, because for discovery we want them all, and there's some chance they differ.
The code around the current version of R needs to be factored a certain way because it's used here, but also used by $validateMetadata
in the RRuntimeManager
, via a higher-level function currentRBinary()
, which only returns a single installation.
Positron consults these sources, in this order, to define the current version of R:
Windows | *nix | |
---|---|---|
Registry | ✅ | ❌ |
PATH, via which | ✅ | ✅ |
Target of [Cc]urrent symlink in HQ | ❌ | ✅ |
|
||
// other conventional places we might find an R binary (or a symlink to one) | ||
const possibleBinaries = [ | ||
const moreBinaries = discoverAdHocBinaries([ |
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.
I'm increasingly skeptical that we need to check these places and would be open to dropping them. I think this is something we basically inherited from ?RStudio?
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.
Sadly I do not have anything substantive to offer on this.
} | ||
|
||
/** | ||
* Discovers R language runtimes for Positron; implements | ||
* positron.LanguageRuntimeDiscoverer. | ||
* Discovers R language runtimes for Positron; implements positron.LanguageRuntimeDiscoverer. |
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.
The change in rRuntimeDiscover()
is a mix of actual change and just changing the order of operations. I'll comment on the interesting bits.
// * version < minimum R version supported by positron-r | ||
// * (macOS only) version is not orthogonal and is not the current version of R | ||
// * invalid R installation | ||
const rejectedRInstallations: Array<RInstallation> = []; |
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.
Starting to keep the rejected R installations around, at least for a little while. This lays the groundwork for possibly incorporating this info into a section of a picker (see #5223) that could be hidden/unhidden.
export enum ReasonDiscovered { | ||
affiliated, | ||
registry, | ||
/* eslint-disable @typescript-eslint/naming-convention */ | ||
PATH, | ||
HQ, | ||
/* eslint-enable @typescript-eslint/naming-convention */ | ||
adHoc, | ||
user | ||
} | ||
|
||
/** | ||
* Enum represents why we rejected an R binary. | ||
*/ | ||
export enum ReasonRejected { | ||
invalid = 'invalid', | ||
unsupported = 'unsupported', | ||
nonOrthogonal = 'non-orthogonal' | ||
} |
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.
While expanding the treatment of "reasons", I also did what @jmcphers requested here re: enum handling: https://github.com/posit-dev/positron/pull/4878/files#r1785400981
user = 'user-specified directory' | ||
export interface RBinary { | ||
path: string; | ||
reasons: ReasonDiscovered[] |
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.
Keeping an array of reasons for discovery now. For #5223, it should be possible for certain R installations to appear in more than 1 section of the picker, especially in a future with increased R support for environments, in the renv or conda sense.
toJSON() { | ||
return { | ||
...this, | ||
reasonDiscovered: this.reasonDiscovered?.map(friendlyReason) ?? null, | ||
reasonRejected: this.reasonRejected ? friendlyReason(this.reasonRejected) : null | ||
}; |
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.
This makes human-readable reasons appear in the log. Here's an example of an unusable R installation:
2024-12-06 12:13:40.397 [info] R installation discovered: {
"usable": false,
"supported": true,
"reasonDiscovered": [
"Found in the primary location for R versions on this operating system"
],
"reasonRejected": "Non-orthogonal installation that is also not the current version",
"binpath": "/Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/bin/R",
"homepath": "/Library/Frameworks/R.framework/Resources",
"semVersion": {
"options": {},
"loose": false,
"includePrerelease": false,
"raw": "4.4.2",
"major": 4,
"minor": 4,
"patch": 2,
"prerelease": [],
"build": [],
"version": "4.4.2"
},
"version": "4.4.2",
"arch": "arm64",
"current": false,
"orthogonal": false
}
@@ -42,8 +43,13 @@ export function timeout(ms: number, reason: string) { | |||
} | |||
|
|||
export function readLines(pth: string): Array<string> { | |||
const bigString = fs.readFileSync(pth, 'utf8'); | |||
return bigString.split(/\r?\n/); | |||
try { |
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.
In this journey, I went through a state where I mistakenly read from a non-existent file and discovered we needed better error handling here.
Motivated by making sure this works in Workbench, for example
196c027
to
ab567e7
Compare
const showLog = await positron.window.showSimpleModalDialogPrompt( | ||
vscode.l10n.t('All discovered R installations are unusable by Positron.'), | ||
vscode.l10n.t('Learn more about R discovery at <br><a href="https://positron.posit.co/r-installations.html">https://positron.posit.co/r-installations.html</a>'), | ||
vscode.l10n.t('View logs'), | ||
vscode.l10n.t('Dismiss') | ||
); |
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.
export enum ReasonDiscovered { | ||
affiliated = "affiliated", | ||
registry = "registry", | ||
/* eslint-disable @typescript-eslint/naming-convention */ | ||
PATH = "PATH", | ||
HQ = "HQ", | ||
/* eslint-enable @typescript-eslint/naming-convention */ | ||
adHoc = "adHoc", | ||
user = "user" | ||
} | ||
|
||
/** | ||
* Enum represents why we rejected an R binary. | ||
*/ | ||
export enum ReasonRejected { | ||
invalid = "invalid", | ||
unsupported = "unsupported", | ||
nonOrthogonal = "nonOrthogonal" | ||
} |
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.
These really do need to be string enums, so that, when reason
arrives in friendlyReason()
below, we can use its value to determine which enum we're dealing with. This seems to be a fundamental awkwardness with enums in TypeScript (?), https://stackoverflow.com/q/63753808.
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.
I destroyed my R situation 😆 and this is working great!
I see this in the logs:
[info] R installation discovered: {
"usable": false,
"supported": false,
"reasonDiscovered": [
"Found in PATH, via the `which` command",
"Found in the primary location for R versions on this operating system",
"Found in a conventional location for symlinked R binaries"
],
"reasonRejected": "Unsupported version, i.e. version is less than 4.2.0",
"binpath": "/Library/Frameworks/R.framework/Versions/4.1-arm64/Resources/bin/R",
"homepath": "/Library/Frameworks/R.framework/Versions/4.1-arm64/Resources",
"semVersion": {
"options": {},
"loose": false,
"includePrerelease": false,
"raw": "4.1.3",
"major": 4,
"minor": 1,
"patch": 3,
"prerelease": [],
"build": [],
"version": "4.1.3"
},
"version": "4.1.3",
"arch": "arm64",
"current": true,
"orthogonal": true
}
|
||
// other conventional places we might find an R binary (or a symlink to one) | ||
const possibleBinaries = [ | ||
const moreBinaries = discoverAdHocBinaries([ |
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.
Sadly I do not have anything substantive to offer on this.
Co-authored-by: Julia Silge <[email protected]> Signed-off-by: Jennifer (Jenny) Bryan <[email protected]>
Addresses #1397
Addresses #5220
Continued preparation for #5223
A lot of the changes are very internal, but there are also user-facing improvements:
QA Notes
To experience this, you need to have at least 1 unusable R installation around and 0 usable ones.
For rig-installed R, use
rig rm release
(or similar) to remove an R installation. Repeat as necessary, until all usable R is gone!Older R installers are here for macOS arm64: https://cran.rstudio.com/bin/macosx/big-sur-arm64/base/. This makes it easy to get R 4.1, for example, which is below our minimum supported version.
You should see a modal telling you that all R installations are unusable, allowing you to look at the Positron R Extension output channel or dismiss.