/// <summary> /// Copies file from local file path to Temp folder on the remote session. /// </summary> /// <param name="filePath">Path to the file to be sent to remote session.</param> /// <param name="doCleanUp">true to add blob upon transfer for cleanup on dispose, false to ignore it after transfer.</param> /// <returns>Path to the file on the remote machine.</returns> public async Task <string> CopyFileToRemoteTempAsync(string filePath, bool doCleanUp, IProgress <long> progress, CancellationToken cancellationToken) { string fileName = Path.GetFileName(filePath); var blobinfo = await SendFileAsync(filePath, doCleanUp, progress, cancellationToken); return(await _session.EvaluateAsync <string>(Invariant($"rtvs:::save_to_temp_folder({blobinfo.Id}, {fileName.ToRStringLiteral()})"), REvaluationKind.Normal, cancellationToken)); }
public async Task RawResult(byte[] data) { string expr = $"as.raw(c({string.Join(", ", data)}))"; var res = await _session.EvaluateAsync(expr, REvaluationKind.RawResult); res.Result.Should().BeNull(); res.RawResult.Should().Equal(data); var bytes = await _session.EvaluateAsync <byte[]>(expr, REvaluationKind.Normal); bytes.Should().Equal(data); }
/// <summary> /// Gets contents of a remote file and copies it to given stream. This method adds the blob for clean up by default. /// </summary> /// <param name="remoteFile"></param> /// <param name="stream"></param> /// <param name="doCleanUp"></param> public async Task CopyToFileStreamAsync(string remoteFile, Stream stream, bool doCleanUp = true, IProgress <long> progress = null, CancellationToken cancellationToken = default(CancellationToken)) { string filePath = remoteFile.ToRPath().ToRStringLiteral(); IRBlobInfo blob = new RBlobInfo(await _session.EvaluateAsync <ulong>($"rtvs:::create_blob(readBin({filePath}, 'raw', file.info({filePath})$size))", REvaluationKind.Normal, cancellationToken)); using (RBlobStream blobStream = await RBlobStream.OpenAsync(blob, _blobService, cancellationToken)) { await blobStream.CopyToAsync(stream, progress, cancellationToken); } if (doCleanUp) { _cleanup.Add(blob); } }
/// <summary> /// Evaluates an R expresion in the specified environment, and returns an object describing the result. /// </summary> /// <param name="environmentExpression"> /// R expression designating the environment in which <paramref name="expression"/> will be evaluated. /// </param> /// <param name="expression">Expression to evaluate.</param> /// <param name="name"><see cref="IREvaluationResultInfo.Name"/> of the returned evaluation result.</param> /// <param name="properties">Specifies which <see cref="IREvaluationResultInfo"/> properties should be present in the result.</param> /// <param name="repr"> /// An R expression that must evaluate to a function that takes an R value as its sole argument, and returns the /// string representation of that argument as a single-element character vector. The representation is stored in /// <see cref="IRValueInfo.Representation"/> property of the produced result. If this argument is /// <see langword="null"/>, no representation is computed, and <see cref="IRValueInfo.Representation"/> /// will also be <see langword="null"/>. /// Use helper properties and methods in <see cref="RValueRepresentations"/> to obtain an appropriate expression /// for standard R functions such as <c>deparse()</c> or <c>str()</c>. /// </param> /// <remarks> /// <returns> /// If evaluation succeeded, an instance of <see cref="IRValueInfo"/> describing the resulting value. /// If evaluation failed with an error, an instance of <see cref="IRErrorInfo"/> describing the error. /// This method never returns <see cref="IRActiveBindingInfo"/> or <see cref="IRPromiseInfo"/>. /// </returns> public static async Task <IREvaluationResultInfo> TryEvaluateAndDescribeAsync( this IRSession session, string environmentExpression, string expression, string name, REvaluationResultProperties properties, string repr, CancellationToken cancellationToken = default(CancellationToken) ) { if (environmentExpression == null) { throw new ArgumentNullException(nameof(environmentExpression)); } if (expression == null) { throw new ArgumentNullException(nameof(expression)); } await TaskUtilities.SwitchToBackgroundThread(); environmentExpression = environmentExpression ?? "NULL"; var code = Invariant($"rtvs:::eval_and_describe({expression.ToRStringLiteral()}, ({environmentExpression}),, {properties.ToRVector()},, {repr})"); var result = await session.EvaluateAsync <JObject>(code, REvaluationKind.Normal, cancellationToken); return(REvaluationResultInfo.Parse(session, environmentExpression, name, result)); }
private async Task ExportToImageAsync(IRSession session, string format, string filePath, int widthInPixels, int heightInPixels, int resolution) { string script = String.Format("rtvs:::export_to_image({0}, {1}, {2}, {3})", format, widthInPixels, heightInPixels, resolution); var data = await session.EvaluateAsync <byte[]>(script, REvaluationKind.Normal); File.WriteAllBytes(filePath, data); }
public async Task Serialize(string expr, string json) { if (json == SameAsInput) { json = expr; } var res = await _session.EvaluateAsync(expr, REvaluationKind.Normal); res.Error.Should().BeNullOrEmpty(); res.Result.Should().NotBeNull(); res.RawResult.Should().BeNull(); var actualJson = JsonConvert.SerializeObject(res.Result).ToUnicodeQuotes(); actualJson.Should().Be(json); }
private async Task RMarkdownRenderAsync(IRSession session, IFileSystem fs, string inputFilePath, string outputFilePath, string format, int codePage, IApplicationShell appShell) { using (var fts = new DataTransferSession(session, fs)) { string currentStatusText = string.Empty; uint cookie = 0; IVsStatusbar statusBar = null; appShell.DispatchOnUIThread(() => { statusBar = appShell.GetGlobalService <IVsStatusbar>(typeof(SVsStatusbar)); statusBar.GetText(out currentStatusText); statusBar.Progress(ref cookie, 1, "", 0, 0); }); try { appShell.DispatchOnUIThread(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownSendingInputFile.FormatInvariant(Path.GetFileName(inputFilePath)), 0, 3); }); var rmd = await fts.SendFileAsync(inputFilePath); appShell.DispatchOnUIThread(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownPublishingFile.FormatInvariant(Path.GetFileName(inputFilePath)), 1, 3); }); var publishResult = await session.EvaluateAsync <ulong>($"rtvs:::rmarkdown_publish(blob_id = {rmd.Id}, output_format = {format.ToRStringLiteral()}, encoding = 'cp{codePage}')", REvaluationKind.Normal); appShell.DispatchOnUIThread(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownGetOutputFile.FormatInvariant(Path.GetFileName(outputFilePath)), 2, 3); }); await fts.FetchFileAsync(new RBlobInfo(publishResult), outputFilePath); appShell.DispatchOnUIThread(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownPublishComplete.FormatInvariant(Path.GetFileName(outputFilePath)), 3, 3); }); } finally { appShell.DispatchOnUIThread(() => { statusBar?.Progress(ref cookie, 0, "", 0, 0); statusBar?.SetText(currentStatusText); }); } } }
public async Task <IGridData <string> > GetGridDataAsync(string expression, GridRange?gridRange, ISortOrder sortOrder = null) { await TaskUtilities.SwitchToBackgroundThread(); var rows = gridRange?.Rows.ToRString(); var columns = gridRange?.Columns.ToRString(); var rowSelector = (sortOrder != null && !sortOrder.IsEmpty) ? sortOrder.GetRowSelector() : ""; if (_gridData != null && _expression == expression && _rows == rows && _columns == columns && _rowSelector == rowSelector) { return(_gridData); } var expr = Invariant($"rtvs:::grid_data({expression}, {rows}, {columns}, {rowSelector})"); try { _gridData = await _session.EvaluateAsync <GridData>(expr, REvaluationKind.Normal); _expression = expression; _rows = rows; _columns = columns; _rowSelector = rowSelector; } catch (RException ex) { var message = Invariant($"Grid data evaluation failed:{Environment.NewLine}{ex.Message}"); VsAppShell.Current.Log().Write(LogVerbosity.Normal, MessageCategory.Error, message); } return(_gridData); }
private async Task RMarkdownRenderAsync(IRSession session, IFileSystem fs, string inputFilePath, string outputFilePath, string format, int codePage, IApplicationShell appShell) { using (var fts = new DataTransferSession(session, fs)) { string currentStatusText = string.Empty; uint cookie = 0; IVsStatusbar statusBar = null; appShell.DispatchOnUIThread(() => { statusBar = appShell.GetGlobalService<IVsStatusbar>(typeof(SVsStatusbar)); statusBar.GetText(out currentStatusText); statusBar.Progress(ref cookie, 1, "", 0, 0); }); try { // TODO: progress and cancellation handling appShell.DispatchOnUIThread(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownSendingInputFile.FormatInvariant(Path.GetFileName(inputFilePath)), 0, 3); }); var rmd = await fts.SendFileAsync(inputFilePath, true, null, CancellationToken.None); appShell.DispatchOnUIThread(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownPublishingFile.FormatInvariant(Path.GetFileName(inputFilePath)), 1, 3); }); var publishResult = await session.EvaluateAsync<ulong>($"rtvs:::rmarkdown_publish(blob_id = {rmd.Id}, output_format = {format.ToRStringLiteral()}, encoding = 'cp{codePage}')", REvaluationKind.Normal); appShell.DispatchOnUIThread(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownGetOutputFile.FormatInvariant(Path.GetFileName(outputFilePath)), 2, 3); }); await fts.FetchFileAsync(new RBlobInfo(publishResult), outputFilePath, true, null, CancellationToken.None); appShell.DispatchOnUIThread(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownPublishComplete.FormatInvariant(Path.GetFileName(outputFilePath)), 3, 3); }); } finally { appShell.DispatchOnUIThread(() => { statusBar?.Progress(ref cookie, 0, "", 0, 0); statusBar?.SetText(currentStatusText); }); } } }
private async Task RMarkdownRenderAsync(IRSession session, string inputFilePath, string outputFilePath, string format, int codePage, IServiceContainer services) { using (var fts = new DataTransferSession(session, services.FileSystem())) { string currentStatusText = string.Empty; uint cookie = 0; IVsStatusbar statusBar = null; services.MainThread().Post(() => { statusBar = services.GetService <IVsStatusbar>(typeof(SVsStatusbar)); statusBar.GetText(out currentStatusText); statusBar.Progress(ref cookie, 1, "", 0, 0); }); try { // TODO: progress and cancellation handling services.MainThread().Post(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownSendingInputFile.FormatInvariant(Path.GetFileName(inputFilePath)), 0, 3); }); var rmd = await fts.SendFileAsync(inputFilePath, true, null, CancellationToken.None); services.MainThread().Post(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownPublishingFile.FormatInvariant(Path.GetFileName(inputFilePath)), 1, 3); }); var publishResult = await session.EvaluateAsync <ulong>($"rtvs:::rmarkdown_publish(blob_id = {rmd.Id}, output_format = {format.ToRStringLiteral()}, encoding = 'cp{codePage}')", REvaluationKind.Normal); services.MainThread().Post(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownGetOutputFile.FormatInvariant(Path.GetFileName(outputFilePath)), 2, 3); }); await fts.FetchFileAsync(new RBlobInfo(publishResult), outputFilePath, true, null, CancellationToken.None); services.MainThread().Post(() => { statusBar?.Progress(ref cookie, 1, Resources.Info_MarkdownPublishComplete.FormatInvariant(Path.GetFileName(outputFilePath)), 3, 3); }); } finally { services.MainThread().Post(() => { statusBar?.Progress(ref cookie, 0, "", 0, 0); statusBar?.SetText(currentStatusText); }); } } }
private async Task RMarkdownRenderAsync(IRSession session, IFileSystem fs, string inputFilePath, string outputFilePath, string format, int codePage) { using (var fts = new FileTransferSession(session, fs)) { var rmd = await fts.SendFileAsync(inputFilePath); var publishResult = await session.EvaluateAsync <byte[]>($"rtvs:::rmarkdown_publish(blob_id = {rmd.Id}, output_format = {format.ToRStringLiteral()}, encoding = 'cp{codePage}')", REvaluationKind.Normal); File.WriteAllBytes(outputFilePath, publishResult); } }
private async Task ExportToImageAsync(IRSession session, string format, string filePath, int widthInPixels, int heightInPixels, int resolution) { string script = String.Format(@" device_id <- rtvs:::graphics.ide.getactivedeviceid() rtvs:::export_to_image(device_id, rtvs:::graphics.ide.getactiveplotid(device_id), {0}, {1}, {2}, {3}) ", format, widthInPixels, heightInPixels, resolution); var blobid = await session.EvaluateAsync <ulong>(script, REvaluationKind.Normal); using (DataTransferSession dts = new DataTransferSession(session, new FileSystem())) { await dts.FetchFileAsync(new RBlobInfo(blobid), filePath, true, null, CancellationToken.None); } }
public async Task QuantmodGrid() { try { await _session.EvaluateAsync("quantmod::getSymbols", REvaluationKind.NoResult); } catch (REvaluationException) { Assert.True(false, "quantmod package is not installed"); } await Test("quantmod::getSymbols('MSFT', auto.assign=FALSE)['2016-03-23::2016-03-28']", 1, 1, new[, ] { { null, "MSFT.Open", "MSFT.High", "MSFT.Low", "MSFT.Close", "MSFT.Volume", "MSFT.Adjusted" }, { "2016-03-23", "54.11", "54.24", "53.74", "53.97", "20129000", "52.58695" }, { "2016-03-24", "53.84", "54.33", "53.73", "54.21", "19950000", "52.82079" }, { "2016-03-28", "54.21", "54.29", "53.33", "53.54", "17025100", "52.16797" }, }); }
public static async Task<IGridData<string>> GetGridDataAsync(IRSession rSession, string expression, GridRange? gridRange, ISortOrder sortOrder = null) { await TaskUtilities.SwitchToBackgroundThread(); string rows = gridRange?.Rows.ToRString(); string columns = gridRange?.Columns.ToRString(); string rowSelector = (sortOrder != null && !sortOrder.IsEmpty) ? sortOrder.GetRowSelector() : ""; string expr = Invariant($"rtvs:::grid_data({expression}, {rows}, {columns}, {rowSelector})"); try { return await rSession.EvaluateAsync<GridData>(expr, REvaluationKind.Normal); } catch (RException ex) { var message = Invariant($"Grid data evaluation failed:{Environment.NewLine}{ex.Message}"); await VsAppShell.Current.Services.Log.WriteAsync(LogVerbosity.Normal, MessageCategory.Error, message); return null; } }
public static async Task <IGridData <string> > GetGridDataAsync(IRSession rSession, string expression, GridRange?gridRange, ISortOrder sortOrder = null) { await TaskUtilities.SwitchToBackgroundThread(); string rows = gridRange?.Rows.ToRString(); string columns = gridRange?.Columns.ToRString(); string rowSelector = (sortOrder != null && !sortOrder.IsEmpty) ? sortOrder.GetRowSelector() : ""; string expr = Invariant($"rtvs:::grid_data({expression}, {rows}, {columns}, {rowSelector})"); try { return(await rSession.EvaluateAsync <GridData>(expr, REvaluationKind.Normal)); } catch (RException ex) { var message = Invariant($"Grid data evaluation failed:{Environment.NewLine}{ex.Message}"); VsAppShell.Current.Services.Log.Write(LogVerbosity.Normal, MessageCategory.Error, message); return(null); } }
public async Task SetBreakpointOnNull() { const string code = @"f <- function() { NULL }"; var tracer = await _session.TraceExecutionAsync(); using (var sf = new SourceFile(code)) { var bp = await tracer.CreateBreakpointAsync(new RSourceLocation(sf.FilePath, 2)); tracer.Breakpoints.Count.Should().Be(1); await sf.Source(_session); (await _session.EvaluateAsync <bool>("is.function(f)", REvaluationKind.Normal)).Should().BeTrue(); } }
public async Task RefreshEnvironmentsAsync() { await TaskUtilities.SwitchToBackgroundThread(); var envs = new List <REnvironment>(); bool success = false; try { var traceback = (await _rSession.TracebackAsync()) .Skip(1) // skip global - it's in the search path already .Select(frame => new REnvironment(frame)) .Reverse(); if (traceback.Any()) { envs.AddRange(traceback); envs.Add(null); } var searchPath = (await _rSession.EvaluateAsync <string[]>("as.list(search())", REvaluationKind.BaseEnv)) .Except(_hiddenEnvironments) .Select(name => new REnvironment(name)); envs.AddRange(searchPath); success = true; } catch (RException) { } catch (MessageTransportException) { } catch (OperationCanceledException) { } VsAppShell.Current.DispatchOnUIThread(() => { var oldSelection = _selectedEnvironment; _environments.ReplaceWith(success ? envs : _errorEnvironments); IREnvironment newSelection = null; if (oldSelection != null) { newSelection = _environments?.FirstOrDefault(env => env?.Name == oldSelection.Name); } SelectedEnvironment = newSelection ?? _environments.FirstOrDefault(); }); }
private async Task RMarkdownRenderAsync(IRSession session, string inputFilePath, string outputFilePath, string format, int codePage, IServiceContainer services) { using (var fts = new DataTransferSession(session, services.FileSystem())) { var statusBar = services.GetService <IStatusBar>(); using (var progress = await statusBar.ShowProgressAsync(3)) { // TODO: cancellation handling progress.Report(new StatusBarProgressData(Resources.Info_MarkdownSendingInputFile.FormatInvariant(Path.GetFileName(inputFilePath)), 0)); var rmd = await fts.SendFileAsync(inputFilePath, true, null, CancellationToken.None); progress.Report(new StatusBarProgressData(Resources.Info_MarkdownPublishingFile.FormatInvariant(Path.GetFileName(inputFilePath)), 1)); var publishResult = await session.EvaluateAsync <ulong>($"rtvs:::rmarkdown_publish(blob_id = {rmd.Id}, output_format = {format.ToRStringLiteral()}, encoding = 'cp{codePage}')", REvaluationKind.Normal); progress.Report(new StatusBarProgressData(Resources.Info_MarkdownGetOutputFile.FormatInvariant(Path.GetFileName(outputFilePath)), 2)); await fts.FetchFileAsync(new RBlobInfo(publishResult), outputFilePath, true, null, CancellationToken.None); progress.Report(new StatusBarProgressData(Resources.Info_MarkdownPublishComplete.FormatInvariant(Path.GetFileName(outputFilePath)), 3)); } } }
public async Task RemoveBreakpointWhileRunning() { const string code = @"browser() f <- function() { NULL browser() } b <- FALSE; while (TRUE) if (b) f()"; using (var debugSession = new DebugSession(_session)) using (var sf = new SourceFile(code)) { await debugSession.EnableBreakpointsAsync(true); await sf.Source(_session); await debugSession.NextPromptShouldBeBrowseAsync(); var bp = await debugSession.CreateBreakpointAsync(sf, 3); int hitCount = 0; bp.BreakpointHit += delegate { ++hitCount; }; await debugSession.ContinueAsync(); await Task.Delay(100); await bp.DeleteAsync(); await _session.EvaluateAsync("b <- TRUE", REvaluationKind.Mutating); await debugSession.NextPromptShouldBeBrowseAsync(); (await debugSession.GetStackFramesAsync()).Should().HaveTail(new MatchDebugStackFrames { { sf, 4 } }); hitCount.Should().Be(0); } }
/// <summary> /// Retrieve the current call stack, in call order (i.e. the current active frame is last, the one that called it is second to last etc). /// </summary> /// <param name="skipSourceFrames"> /// If <see langword="true"/>, excludes frames that belong to <c>source()</c> or <c>rtvs:::debug_source()</c> internal machinery at the bottom of the stack; /// the first reported frame will be the one with sourced code. /// </param> /// <remarks> /// This method has snapshot semantics for the frames and their properties - that is, the returned collection is not going to change as code runs. /// However, calling various methods on the returned <see cref="IRStackFrame"/> objects, such as <see cref="RStackFrameExtensions.DescribeChildrenAsync"/>, /// will fetch fresh data, possibly from altogether different frames if the call stack has changed. Thus, it is inadvisable to retain the returned /// stack and use it at a later point - it should always be obtained anew at the point where it is used. /// </remarks> public static async Task <IReadOnlyList <IRStackFrame> > TracebackAsync( this IRSession session, bool skipSourceFrames = true, CancellationToken cancellationToken = default ) { await TaskUtilities.SwitchToBackgroundThread(); var jFrames = await session.EvaluateAsync <JArray>("rtvs:::describe_traceback()", REvaluationKind.Normal, cancellationToken); Trace.Assert(jFrames.All(t => t is JObject), "rtvs:::describe_traceback(): array of objects expected.\n\n" + jFrames); var stackFrames = new List <RStackFrame>(); RStackFrame lastFrame = null; int i = 0; foreach (JObject jFrame in jFrames) { lastFrame = new RStackFrame(session, i, lastFrame, jFrame); stackFrames.Add(lastFrame); ++i; } if (skipSourceFrames) { var firstFrame = stackFrames.FirstOrDefault(); if (firstFrame != null && firstFrame.IsGlobal && firstFrame.Call != null) { if (firstFrame.Call.StartsWith("source(") || firstFrame.Call.StartsWith("rtvs::debug_source(")) { // Skip everything until the first frame that has a line number - that will be the sourced code. stackFrames = stackFrames.SkipWhile(f => f.LineNumber == null).ToList(); } } } return(stackFrames); }
public async Task BreakContinue() { const string code = @"browser() x <- 0 while (x >= 0) { x <- x + 1 } browser()"; using (var debugSession = new DebugSession(_session)) using (var sf = new SourceFile(code)) { await sf.Source(_session); await debugSession.NextPromptShouldBeBrowseAsync(); await debugSession.ContinueAsync(); await Task.Delay(100); await debugSession.BreakAsync(); await debugSession.NextPromptShouldBeBrowseAsync(); (await debugSession.GetStackFramesAsync()).Should().HaveTail(new MatchDebugStackFrames { { sf, new MatchRange <int>(1, 3) } }); await _session.EvaluateAsync("x <- -42", REvaluationKind.Mutating); await debugSession.ContinueAsync(); await debugSession.NextPromptShouldBeBrowseAsync(); (await debugSession.GetStackFramesAsync()).Should().HaveTail(new MatchDebugStackFrames { { sf, 6 } }); } }
/// <summary> /// Given function name returns package the function belongs to. /// The package is determined from the interactive R session since /// there may be functions with the same name but from different packages. /// Most recently loaded package typically wins. /// </summary> /// <param name="functionName">R function name</param> /// <returns>Function package or null if undefined</returns> public async Task <string> GetFunctionPackageNameAsync(string functionName) { IRSession session = GetLoadedPackagesInspectionSession(); string packageName = null; if (session != null && session.IsHostRunning) { try { packageName = await session.EvaluateAsync <string>( Invariant( $"as.list(find('{functionName}', mode='function')[1])[[1]]" ), REvaluationKind.Normal); if (packageName != null && packageName.StartsWithOrdinal("package:")) { packageName = packageName.Substring(8); } } catch (Exception) { } } return(packageName); }
/// <summary> /// Computes the children of the object represented by the given expression, and returns a collection of /// evaluation objects describing each child. /// See <see cref="RSessionExtensions.TryEvaluateAndDescribeAsync"/> for the meaning of other parameters. /// </summary> /// <param name="maxCount">If not <see langword="null"/>, return at most that many children.</param> /// <remarks> /// <para> /// The resulting collection has an item for every child. If the child could be retrieved, and represents /// a value, the corresponding item is an <see cref="IRValueInfo"/> instance. If the child represents /// a promise, the promise is not forced, and the item is an <see cref="IRPromiseInfo"/> instance. If the /// child represents an active binding, the binding is not evaluated to retrieve the value, and the item is /// an <see cref="IRActiveBindingInfo"/> instance. If the child could not be retrieved, the item is an /// <see cref="IRErrorInfo"/> instance describing the error that prevented its retrieval. /// </para> /// <para> /// Where order matters (e.g. for children of atomic vectors and lists), children are returned in that order. /// Otherwise, the order is undefined. If an object has both ordered and unordered children (e.g. it is a vector /// with slots), then it is guaranteed that each group is reported as a contiguous sequence within the returned /// collection, and order is honored within each group; but groups themselves are not ordered relative to each other. /// </para> /// </remarks> /// <exception cref="RException"> /// Raised if the operation fails as a whole (note that if only specific children cannot be retrieved, those /// children are represented by <see cref="IRErrorInfo"/> instances in the returned collection instead). /// </exception> public static async Task <IReadOnlyList <IREvaluationResultInfo> > DescribeChildrenAsync( this IRSession session, string environmentExpression, string expression, REvaluationResultProperties properties, string repr, int?maxCount = null, CancellationToken cancellationToken = default(CancellationToken) ) { await TaskUtilities.SwitchToBackgroundThread(); var call = Invariant($"rtvs:::describe_children({expression.ToRStringLiteral()}, {environmentExpression}, {properties.ToRVector()}, {maxCount}, {repr})"); var jChildren = await session.EvaluateAsync <JArray>(call, REvaluationKind.Normal, cancellationToken); Trace.Assert( jChildren.Children().All(t => t is JObject), Invariant($"rtvs:::describe_children(): object of objects expected.\n\n{jChildren}")); var children = new List <REvaluationResultInfo>(); foreach (var child in jChildren) { var childObject = (JObject)child; Trace.Assert( childObject.Count == 1, Invariant($"rtvs:::describe_children(): each object is expected contain one object\n\n")); foreach (var kv in childObject) { var name = kv.Key; var jEvalResult = (JObject)kv.Value; var evalResult = REvaluationResultInfo.Parse(session, environmentExpression, name, jEvalResult); children.Add(evalResult); } } return(children); }
public async Task InteractDuringBrowse() { var tracer = await _session.TraceExecutionAsync(); using (var sf = new SourceFile("x <- 'old'; browser()")) { var browse = new TaskCompletionSource <bool>(); tracer.Browse += (s, e) => { browse.TrySetResult(true); }; await sf.Source(_session); await browse.Task; using (var inter = await _session.BeginInteractionAsync()) { await inter.RespondAsync("x <- 'new'\n"); } var x = await _session.EvaluateAsync <string>("x", REvaluationKind.Normal); x.Should().Be("new"); } }
private static async Task CreateCsvAndStartProcess( IREvaluationResultInfo result, IRSession session, ICoreShell coreShell, string fileName, IFileSystem fileSystem, IProgress <ProgressDialogData> progress, CancellationToken cancellationToken) { await TaskUtilities.SwitchToBackgroundThread(); var sep = CultureInfo.CurrentCulture.TextInfo.ListSeparator; var dec = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; try { var csvDataBlobId = await session.EvaluateAsync <ulong>($"rtvs:::export_to_csv({result.Expression}, sep={sep.ToRStringLiteral()}, dec={dec.ToRStringLiteral()})", REvaluationKind.Normal, cancellationToken); using (DataTransferSession dts = new DataTransferSession(session, fileSystem)) { await dts.FetchAndDecompressFileAsync(csvDataBlobId, fileName, progress, Resources.Status_WritingCSV, cancellationToken); } } catch (RException) { await coreShell.ShowErrorMessageAsync(Resources.Error_CannotExportToCsv, cancellationToken); } }
private static Task <int> GetRSessionProcessId(IRSession session) => session.EvaluateAsync <int>("Sys.getpid()", REvaluationKind.Normal);
public static Task <string> GetFunctionCodeAsync(this IRSession session, string functionName) { return(session.EvaluateAsync <string>(Invariant($"paste0(deparse({functionName}), collapse='\n')"), REvaluationKind.Normal)); }
public static Task <string> GetFunctionCodeAsync(this IRSession session, string functionName, CancellationToken cancellationToken = default(CancellationToken)) => session.EvaluateAsync <string>(Invariant($"paste0(deparse({functionName}), collapse='\n')"), REvaluationKind.Normal, cancellationToken);
private static async Task CreateCsvAndStartProcess( IREvaluationResultInfo result, IRSession session, string fileName, IFileSystem fileSystem, IProgress<ProgressDialogData> progress, CancellationToken cancellationToken) { await TaskUtilities.SwitchToBackgroundThread(); var sep = CultureInfo.CurrentCulture.TextInfo.ListSeparator; var dec = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; var csvDataBlobId = await session.EvaluateAsync<ulong>($"rtvs:::export_to_csv({result.Expression}, sep={sep.ToRStringLiteral()}, dec={dec.ToRStringLiteral()})", REvaluationKind.Normal, cancellationToken); using (DataTransferSession dts = new DataTransferSession(session, fileSystem)) { var total = await session.GetBlobSizeAsync(csvDataBlobId, cancellationToken); progress.Report(new ProgressDialogData(0, statusBarText: Resources.Status_WritingCSV, waitMessage: Resources.Status_WritingCSV)); await dts.FetchAndDecompressFileAsync(new RBlobInfo(csvDataBlobId), fileName, true, new Progress<long>(b => { var step = (int)(b * 100 / total); progress.Report(new ProgressDialogData(step, statusBarText: Resources.Status_WritingCSV, waitMessage: Resources.Status_WritingCSV)); }), cancellationToken); progress.Report(new ProgressDialogData(100, statusBarText: Resources.Status_WritingCSV, waitMessage: Resources.Status_WritingCSV)); } }
private async Task Environments(string script, params IREnvironment[] expectedEnvs) { // Detach all packages that can be detached before doing anything else. The only two that // cannot be detached are .GlobalEnv, which is the first in the list, and package:base, // which is the last. So, just keep detaching the 2nd item until the list only has 2 left. await _session.ExecuteAsync("while (length(search()) > 2) detach(2)"); // Wait for prompt to appear. using (var eval = await _session.BeginInteractionAsync()) { } var envProvider = new REnvironmentProvider(_session); var envTcs = new TaskCompletionSource <IREnvironment[]>(); envProvider.Environments.CollectionChanged += (sender, args) => { envTcs.TrySetResult(envProvider.Environments.ToArray()); }; using (var inter = await _session.BeginInteractionAsync()) { inter.RespondAsync(script + "\n").DoNotWait(); } // Wait until we hit the Browse> prompt. using (var inter = await _session.BeginInteractionAsync()) { inter.Contexts.IsBrowser().Should().BeTrue(); } var actualEnvs = await envTcs.Task; actualEnvs.ShouldAllBeEquivalentTo(expectedEnvs, options => options .Including(env => env.Name) .Including(env => env.Kind) .WithStrictOrdering()); // Validating EnvironmentExpression: // For environments that are on the search list, we can validate it by retrieving environment by name, // and verifying that it is indeed the same. format() generates comparable string values - it returns strings // that are unique for any given environment (using its name if it has one, and its memory address otherwise). // For all other environments, we validate by looking at a variable named 'tag' in that environment, and // comparing its value to the name of the function extracted from the call (i.e. environment name). var expectedObjects = new List <string>(); var actualObjects = new List <string>(); foreach (var env in actualEnvs) { if (env == null) { expectedObjects.Add(null); actualObjects.Add(null); } else if (env.Kind == REnvironmentKind.Function) { int tagEnd = env.Name.IndexOf("("); tagEnd.Should().BePositive(); string tag = env.Name.Substring(0, tagEnd); expectedObjects.Add(tag); actualObjects.Add(await _session.EvaluateAsync <string>( $"({env.EnvironmentExpression})$tag", REvaluationKind.Normal)); } else { expectedObjects.Add(await _session.EvaluateAsync <string>( $"format(as.environment({env.Name.ToRStringLiteral()}))", REvaluationKind.Normal)); actualObjects.Add(await _session.EvaluateAsync <string>( $"format({env.EnvironmentExpression})", REvaluationKind.Normal)); } } actualObjects.Should().Equal(expectedObjects); }
private static Task<int> GetRSessionProcessId(IRSession session) => session.EvaluateAsync<int>("Sys.getpid()", REvaluationKind.Normal);
private async Task ExportToImageAsync(IRSession session, string format, string filePath, int widthInPixels,int heightInPixels, int resolution) { string script = String.Format(@" device_id <- rtvs:::graphics.ide.getactivedeviceid() rtvs:::export_to_image(device_id, rtvs:::graphics.ide.getactiveplotid(device_id), {0}, {1}, {2}, {3}) ", format, widthInPixels, heightInPixels, resolution); var blobid = await session.EvaluateAsync<ulong>(script, REvaluationKind.Normal); using(DataTransferSession dts = new DataTransferSession(session, new FileSystem())) { await dts.FetchFileAsync(new RBlobInfo(blobid), filePath, true, null, CancellationToken.None); } }